diff --git a/.github/workflows/all_jobs.yaml b/.github/workflows/all_jobs.yaml index ecb2e3d23..fcd209e98 100644 --- a/.github/workflows/all_jobs.yaml +++ b/.github/workflows/all_jobs.yaml @@ -6,45 +6,43 @@ on: env: #General variables - numpy_version: "numpy==1.23.4" # replace with only 'numpy' if no version needed - python_versions: 3.8 - pybind_version: "2.6.0" + python_versions: 3.9 #Windows variables - python_executable: "C:/hostedtoolcache/windows/Python/3.8.10/x64/python.exe" #Cmake needs this to find python on windows + python_executable: "C:/hostedtoolcache/windows/Python/3.9.9/x64/python.exe" #Cmake needs this to find python on windows -jobs: +jobs: - container-ubuntu-20-job: - name: Build Ubuntu 20 Image - runs-on: ubuntu-20.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v2 + container-ubuntu-22-job: + name: Build Ubuntu 22 Image + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v2 - - name: Login to Docker Registry - uses: docker/login-action@v3 - with: - username: ${{ secrets.PSEE_DOCKER_HUB_USER }} - password: ${{ secrets.PSEE_DOCKER_HUB_ACCESS_TOKEN }} + - name: Login to Docker Registry + uses: docker/login-action@v3 + with: + username: ${{ secrets.PSEE_DOCKER_HUB_USER }} + password: ${{ secrets.PSEE_DOCKER_HUB_ACCESS_TOKEN }} - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - - name: Build and Push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: utils/containers/Dockerfile.OpenEB - push: true - build-args: UBUNTU_VERSION=20.04 - tags: prophesee/openeb:ubuntu-20.04 + - name: Build and Push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: utils/containers/Dockerfile.OpenEB + push: true + build-args: BASE_IMAGE_TAG=22.04 + tags: prophesee/openeb:ubuntu-22.04 job1: - name: Ubuntu 20 - needs: container-ubuntu-20-job - runs-on: ubuntu-20.04 + name: Ubuntu 22 + needs: container-ubuntu-22-job + runs-on: ubuntu-22.04 container: - image: prophesee/openeb:ubuntu-20.04 + image: prophesee/openeb:ubuntu-22.04 steps: - name: Checkout Repository uses: actions/checkout@v2 @@ -53,8 +51,9 @@ jobs: - name: Build openEB run: | - cmake -B build -DBUILD_TESTING=ON - cmake --build build --config Release --parallel `nproc` + mkdir build && cd build + cmake .. -DBUILD_TESTING=ON + cmake --build . --config Release --parallel 4 - name: Getting datasets from storage uses: dawidd6/action-download-artifact@v2 @@ -69,37 +68,38 @@ jobs: cd build ctest --output-on-failure - container-ubuntu-22-job: - name: Build Ubuntu 22 Image - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v2 - - name: Login to Docker Registry - uses: docker/login-action@v3 - with: - username: ${{ secrets.PSEE_DOCKER_HUB_USER }} - password: ${{ secrets.PSEE_DOCKER_HUB_ACCESS_TOKEN }} + container-ubuntu-24-job: + name: Build Ubuntu 24 Image + runs-on: ubuntu-24.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v2 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Login to Docker Registry + uses: docker/login-action@v3 + with: + username: ${{ secrets.PSEE_DOCKER_HUB_USER }} + password: ${{ secrets.PSEE_DOCKER_HUB_ACCESS_TOKEN }} - - name: Build and Push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: utils/containers/Dockerfile.OpenEB - push: true - build-args: UBUNTU_VERSION=22.04 - tags: prophesee/openeb:ubuntu-22.04 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and Push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: utils/containers/Dockerfile.OpenEB + push: true + build-args: BASE_IMAGE_TAG=24.04 + tags: prophesee/openeb:ubuntu-24.04 job2: - name: Ubuntu 22 - needs: container-ubuntu-22-job - runs-on: ubuntu-22.04 + name: Ubuntu 24 + needs: container-ubuntu-24-job + runs-on: ubuntu-24.04 container: - image: prophesee/openeb:ubuntu-22.04 + image: prophesee/openeb:ubuntu-24.04 steps: - name: Checkout Repository uses: actions/checkout@v2 @@ -108,9 +108,8 @@ jobs: - name: Build openEB run: | - mkdir build && cd build - cmake .. -DBUILD_TESTING=ON - cmake --build . --config Release --parallel 4 + cmake -B build -DBUILD_TESTING=ON + cmake --build build --config Release --parallel `nproc` - name: Getting datasets from storage uses: dawidd6/action-download-artifact@v2 @@ -125,6 +124,7 @@ jobs: cd build ctest --output-on-failure + job3: name: Windows runs-on: windows-2019 @@ -159,7 +159,7 @@ jobs: cd .. unzip -q "vcpkg-export.zip" 7z x ffmpeg-archive.7z - $python_executable -m pip install pytest $numpy_version opencv-python==4.5.5.64 torch==1.13.1 scipy sk-video==1.1.10 numba==0.56.3 h5py command_runner kornia==0.6.8 pytorch_lightning==1.8.6 pytorch_msssim==0.2.1 + $python_executable -m pip install -r openeb/utils/python/requirements_openeb.txt cd openeb - name: Build openEB diff --git a/.github/workflows/upload_win_binaries.yaml b/.github/workflows/upload_win_binaries.yaml index ee6eac0f4..f780c03f4 100644 --- a/.github/workflows/upload_win_binaries.yaml +++ b/.github/workflows/upload_win_binaries.yaml @@ -6,7 +6,8 @@ on: - cron: "15 2 1 */2 *" env: - win_binaries_download_address: "https://prophesee-bamboo.s3.eu-west-1.amazonaws.com/build-env/vcpkg-export-20230323-MV4.0.0.zip" + # TODO update for v5.0.0 release + win_binaries_download_address: "https://prophesee-bamboo.s3.eu-west-1.amazonaws.com/build-env/vcpkg-export-20240909-MV_V4.6.2.zip" ffmpeg_archive_download_address: "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-full.7z" jobs: diff --git a/.gitmodules b/.gitmodules index 9bbab85b1..7f0ada2b0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "hdf5_ecf"] - path = sdk/modules/driver/cpp/3rdparty/hdf5_ecf + path = sdk/modules/stream/cpp/3rdparty/hdf5_ecf url = https://github.com/prophesee-ai/hdf5_ecf.git diff --git a/CMakeLists.txt b/CMakeLists.txt index a238833f1..87d4143d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,8 +17,8 @@ endif(NOT CMAKE_BUILD_TYPE) cmake_minimum_required(VERSION 3.5) -project(metavision VERSION 4.6.2) -set(PROJECT_VERSION_SUFFIX "") +project(metavision VERSION 5.0.0) +set(PROJECT_VERSION_SUFFIX "dev") if(PROJECT_VERSION_SUFFIX STREQUAL "") set(PROJECT_VERSION_FULL "${PROJECT_VERSION}") @@ -60,7 +60,7 @@ endif (ANDROID) set(HAL_BUILD_PLUGIN_PATH "${PROJECT_BINARY_DIR}/${HAL_INSTALL_PLUGIN_RELATIVE_PATH}") # Set output directory for generated files -set(GENERATE_FILES_DIRECTORY ${CMAKE_BINARY_DIR}/generated) +set(GENERATE_FILES_DIRECTORY ${PROJECT_BINARY_DIR}/generated) file(MAKE_DIRECTORY ${GENERATE_FILES_DIRECTORY}) # Update CMAKE_MODULE_PATH @@ -75,33 +75,35 @@ include(lfs_download) include(add_pytest) include(common_macros) -if (ANDROID AND NOT ENV_CMAKE) - # Those OVERLOAD_ functions are used to be able to bypass default Metavision - # implementation of Android support to give a different own depending on - # dependencies management - set(ENV_CMAKE cmake/android/env.cmake) - set(PREBUILT_BASE_DIR utils/android) - set(PREBUILT_FILENAME prebuilt-3rdparty.tar.gz) - - # Setup 3rd party prebuilt libraries dir - set(ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR ${GENERATE_FILES_DIRECTORY}/android/3rdparty) - if (NOT EXISTS ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) - lfs_download(${PREBUILT_BASE_DIR}/${PREBUILT_FILENAME} COMPILATION) - message(STATUS "Unpacking ${PREBUILT_BASE_DIR}/${PREBUILT_FILENAME} in ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}") - file(MAKE_DIRECTORY ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar -xf ${PROJECT_SOURCE_DIR}/${PREBUILT_BASE_DIR}/${PREBUILT_FILENAME} - WORKING_DIRECTORY ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR} - ) - endif (NOT EXISTS ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) +if (ANDROID) + if (NOT ENV_CMAKE) + # Those OVERLOAD_ functions are used to be able to bypass default Metavision + # implementation of Android support to give a different own depending on + # dependencies management + set(ENV_CMAKE ${PROJECT_SOURCE_DIR}/cmake/android/env.cmake) + set(PREBUILT_BASE_DIR utils/android) + set(PREBUILT_FILENAME prebuilt-3rdparty.tar.gz) + + # Setup 3rd party prebuilt libraries dir + set(ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR ${GENERATE_FILES_DIRECTORY}/android/3rdparty) + if (NOT EXISTS ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) + lfs_download(${PREBUILT_BASE_DIR}/${PREBUILT_FILENAME} COMPILATION) + message(STATUS "Unpacking ${PREBUILT_BASE_DIR}/${PREBUILT_FILENAME} in ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}") + file(MAKE_DIRECTORY ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar -xf ${PROJECT_SOURCE_DIR}/${PREBUILT_BASE_DIR}/${PREBUILT_FILENAME} + WORKING_DIRECTORY ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR} + ) + endif (NOT EXISTS ${ANDROID_PREBUILT_3RDPARTY_EXTRACT_DIR}) + + # Use Android env.cmake to find required dependencies + set(ANDROID_PREBUILT_3RDPARTY_DIR ${GENERATE_FILES_DIRECTORY}/android/3rdparty/prebuilt) + include(${ENV_CMAKE}) + endif() # Include the function required to build an Android APK include(add_android_app) - - # Use Android env.cmake to find required dependencies - set(ANDROID_PREBUILT_3RDPARTY_DIR ${GENERATE_FILES_DIRECTORY}/android/3rdparty/prebuilt) - include(${ENV_CMAKE}) -endif (ANDROID AND NOT ENV_CMAKE) +endif() ################################################### @@ -203,7 +205,7 @@ find_package(Threads REQUIRED) find_package(LibUSB REQUIRED) # Boost -set (boost_components_to_find program_options filesystem timer chrono thread) +set (boost_components_to_find program_options timer chrono thread) find_package(Boost COMPONENTS ${boost_components_to_find} REQUIRED) add_definitions(-DBOOST_BIND_GLOBAL_PLACEHOLDERS) ## needed to get rid of warning `#pragma message: The practice of declaring the Bind placeholders (_1, _2, ...)` @@ -252,11 +254,21 @@ if (BUILD_TESTING) endif() set(PYTEST_CMD ${PYTHON_${PYTEST_PYTHON_VERSION}_EXECUTABLE} -m pytest) + + # Perform additional test to ensure that variable `PYTEST_CMD` resulted to a valid executable. + # Throw fatal error otherwise to inform user something went wrong. + string(COMPARE EQUAL "${PYTEST_CMD}" "-m pytest" PYTEST_CMD_IS_INVALID) + + if(PYTEST_CMD_IS_INVALID) + message(WARNING "Problem with finding valid 'pytest' version, try overriding with: '-DPYTEST_PYTHON_VERSION='! ") + endif(PYTEST_CMD_IS_INVALID) + if(CMAKE_CROSSCOMPILING) # When cross compiling, we cannot use python executable path from the Host set(PYTEST_CMD pytest) # TODO we need a proper way to find python executable path on the TARGET. endif(CMAKE_CROSSCOMPILING) + lfs_download(datasets/openeb/gen31_timer.raw VALIDATION) lfs_download(datasets/openeb/gen31_timer.hdf5 VALIDATION) lfs_download(datasets/openeb/gen31_timer_holes.raw VALIDATION) @@ -265,10 +277,12 @@ if (BUILD_TESTING) lfs_download(datasets/openeb/gen4_evt2_hand.hdf5 VALIDATION) lfs_download(datasets/openeb/gen4_evt3_hand.raw VALIDATION) lfs_download(datasets/openeb/gen4_evt3_hand.hdf5 VALIDATION) + lfs_download(datasets/openeb/gen4_evt4_hand.raw VALIDATION) lfs_download(datasets/openeb/blinking_gen4_with_ext_triggers.raw VALIDATION) lfs_download(datasets/openeb/blinking_gen4_with_ext_triggers.hdf5 VALIDATION) lfs_download(datasets/openeb/claque_doigt_evt21.raw VALIDATION) lfs_download(datasets/openeb/claque_doigt_evt21.hdf5 VALIDATION) + lfs_download(datasets/openeb/claque_doigt_evt4.raw VALIDATION) lfs_download(datasets/openeb/standup_evt21-legacy.raw VALIDATION) lfs_download(datasets/openeb/standup_evt21-legacy.hdf5 VALIDATION) lfs_download(datasets/openeb/diff3d.raw VALIDATION) @@ -347,7 +361,7 @@ endif(CODE_COVERAGE) ################################################### Detect which SDK modules are available -set(METAVISION_SDK_MODULES_OPEN base core driver CACHE STRING "SDK Open modules") +set(METAVISION_SDK_MODULES_OPEN base core stream CACHE STRING "SDK Open modules") if (COMPILE_PYTHON3_BINDINGS) list(APPEND METAVISION_SDK_MODULES_OPEN core_ml) endif (COMPILE_PYTHON3_BINDINGS) @@ -388,6 +402,10 @@ add_cpack_component(PUBLIC metavision-open-lib metavision-open-bin metavision-op if(COMPILE_PYTHON3_BINDINGS) add_cpack_component(PUBLIC metavision-open-python metavision-open-python-samples) add_python_cpack_components(PUBLIC metavision-open) + + install(FILES ${PROJECT_SOURCE_DIR}/utils/python/requirements_openeb.txt + DESTINATION share/metavision/python_requirements + COMPONENT metavision-open-python) endif(COMPILE_PYTHON3_BINDINGS) # Add Metavision SDK debian packages : @@ -397,6 +415,10 @@ if (METAVISION_SDK_ADVANCED_MODULES_AVAILABLE) if(COMPILE_PYTHON3_BINDINGS) add_cpack_component(PUBLIC metavision-sdk-advanced-python metavision-sdk-advanced-python-samples) add_python_cpack_components(PUBLIC metavision-sdk-advanced) + + install(FILES ${PROJECT_SOURCE_DIR}/utils/python/requirements_sdk_advanced.txt + DESTINATION share/metavision/python_requirements + COMPONENT metavision-sdk-advanced-python) endif(COMPILE_PYTHON3_BINDINGS) # SDK diff --git a/README.md b/README.md index 1db9b5b1e..6bfd2be25 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ to the fast-growing event-based vision community. OpenEB is composed of the [Open modules of Metavision SDK](https://docs.prophesee.ai/stable/modules.html#chapter-modules-and-packaging-open): * HAL: Hardware Abstraction Layer to operate any event-based vision device. * Base: Foundations and common definitions of event-based applications. -* Core: Generic algorithms for visualization, event stream manipulation, applicative pipeline generation. +* Core: Generic algorithms for visualization, event stream manipulation. * Core ML: Generic functions for Machine Learning, event_to_video and video_to_event pipelines. -* Driver: High-level abstraction built on the top of HAL to easily interact with event-based cameras. +* Stream: High-level abstraction built on the top of HAL to easily interact with event-based cameras. * UI: Viewer and display controllers for event-based data. OpenEB also contains the source code of [Prophesee camera plugins](https://docs.prophesee.ai/stable/installation/camera_plugins.html), @@ -60,6 +60,23 @@ sudo make uninstall In addition, make a global check in your system paths (`/usr/lib`, `/usr/local/lib`, `/usr/include`, `/usr/local/include`) and in your environment variables (`PATH`, `PYTHONPATH` and `LD_LIBRARY_PATH`) to remove occurrences of Prophesee or Metavision files. + +### Retrieving OpenEB source code + +To retrieve OpenEB source code, you can just clone the [GitHub repository](https://github.com/prophesee-ai/openeb): + +```bash +git clone https://github.com/prophesee-ai/openeb.git --branch 5.0.0 +``` + +In the following sections, absolute path to this directory is called ``OPENEB_SRC_DIR`` + +If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, +you need to ensure that you select a `Full.Source.Code.*` archive instead of using +the automatically generated `Source.Code.*` archives. This is because the latter do not include +a necessary submodule. + + ### Prerequisites Install the following dependencies: @@ -79,20 +96,34 @@ sudo apt -y install libgtest-dev libgmock-dev ``` For the [Python API](https://docs.prophesee.ai/stable/api/python/index.html#chapter-api-python), you will need Python and some additional libraries. -If Python is not available on your system, install it -We support Python 3.8 and 3.9 on Ubuntu 20.04 and Python 3.9 and 3.10 on Ubuntu 22.04. -If you want to use other versions of Python, some source code modifications will be necessary +We support Python 3.9 and 3.10 on Ubuntu 22.04 and Python 3.11 and 3.12 on Ubuntu 24.04. + +We recommend using Python with [virtualenv](https://virtualenv.pypa.io/en/latest/) to avoid conflicts with other installed Python packages. +So, first install it along with some Python development tools: -Then install `pip` and some Python libraries: ```bash -sudo apt -y install python3-pip python3-distutils -sudo apt -y install python3.X-dev # where X is 8, 9 or 10 depending on your Python version (3.8, 3.9 or 3.10) -python3 -m pip install pip --upgrade -python3 -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy -python3 -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner +sudo apt -y install python3.x-venv python3.x-dev +# where "x" is 9, 10, 11 or 12 depending on your Python version ``` -The Python bindings of the C++ API rely on the [pybind11](https://github.com/pybind) library, specifically version 2.6.0. +Next, create a virtual environment and install the necessary dependencies: + +```bash +python3 -m venv /tmp/prophesee/py3venv --system-site-packages +/tmp/prophesee/py3venv/bin/python -m pip install pip --upgrade +/tmp/prophesee/py3venv/bin/python -m pip install -r OPENEB_SRC_DIR/utils/python/python_requirements/requirements_openeb.txt +``` + +Note that when creating the virtual environment, it is necessary to use the `--system-site-packages` option to ensure that +the SDK packages installed in the system directories are accessible. However, this option also makes your local +user site-packages (typically found in `~/.local/lib/pythonX.Y/site-packages`) visible by default. +To prevent this and maintain a cleaner virtual environment, you can set the environment variable `PYTHONNOUSERSITE` to true. + +Optionally, you can run the `activate` command (`source /tmp/prophesee/py3venv/bin/activate`) to modify your shell's environment variables, +setting the virtual environment's Python interpreter and scripts as the default for your current session. +This allows you to use simple commands like `python` without needing to specify the full path each time. + +The Python bindings of the C++ API rely on the [pybind11](https://github.com/pybind) library, specifically version 2.11.0. *Note* that pybind11 is required only if you want to use the Python bindings of the C++ API . You can opt out of creating these bindings by passing the argument `-DCOMPILE_PYTHON3_BINDINGS=OFF` at step 3 during compilation (see below). @@ -101,9 +132,9 @@ In that case, you will not need to install pybind11, but you won't be able to us Unfortunately, there is no pre-compiled version of pybind11 available, so you need to install it manually: ```bash -wget https://github.com/pybind/pybind11/archive/v2.6.0.zip -unzip v2.6.0.zip -cd pybind11-2.6.0/ +wget https://github.com/pybind/pybind11/archive/v2.11.0.zip +unzip v2.11.0.zip +cd pybind11-2.11.0/ mkdir build && cd build cmake .. -DPYBIND11_TEST=OFF cmake --build . @@ -120,30 +151,15 @@ Make sure that you install a version of CUDA that is compatible with your GPUs b Note that, at the moment, we don't support [OpenCL](https://www.khronos.org/opencl/) and AMD GPUs. -Then, you need to install [PyTorch 1.13.1](https://pytorch.org). -Retrieve and execute the pip command of version 1.13.1 from -the [previous versions install guide section](). - -Then install some extra Python libraries: - -```bash -python3 -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning==1.8.6" "tqdm==4.63.0" "kornia==0.6.8" -``` - ### Compilation - 1. Retrieve the code: `git clone https://github.com/prophesee-ai/openeb.git --branch 4.6.2`. - (If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, - you need to ensure that you select a ``Full.Source.Code.*`` archive instead of using - the automatically generated ``Source.Code.*`` archives. This is because the latter do not include - a necessary submodule.) - 2. Create and open the build directory in the `openeb` folder (absolute path to this directory is called `OPENEB_SRC_DIR` in next sections): `cd openeb; mkdir build && cd build` - 3. Generate the makefiles using CMake: `cmake .. -DBUILD_TESTING=OFF`. + 1. Create and open the build directory `OPENEB_SRC_DIR`: `mkdir build && cd build` + 2. Generate the makefiles using CMake: `cmake .. -DBUILD_TESTING=OFF`. If you want to specify to cmake which version of Python to consider, you should use the option ``-DPython3_EXECUTABLE=``. This is useful, for example, when you have a more recent version of Python than the ones we support installed on your system. In that case, cmake would select it and compilation might fail. - 4. Compile: `cmake --build . --config Release -- -j 4` + 3. Compile: `cmake --build . --config Release -- -j 4` Once the compilation is finished, you have two options: you can choose to work directly from the `build` folder or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/local/include`...). @@ -176,7 +192,7 @@ or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/l Note that you can also deploy the OpenEB files (applications, samples, libraries etc.) in a directory of your choice by using the `CMAKE_INSTALL_PREFIX` variable (`-DCMAKE_INSTALL_PREFIX=`) when generating the makefiles - in step 3. Similarly, you can configure the directory where the Python packages will be deployed using the + in step 2. Similarly, you can configure the directory where the Python packages will be deployed using the `PYTHON3_SITE_PACKAGES` variable (`-DPYTHON3_SITE_PACKAGES=`). * you also need to update `LD_LIBRARY_PATH` and `HDF5_PLUGIN_PATH` @@ -232,6 +248,21 @@ Then, if you have previously installed any Prophesee's software, you will need t Remove the folders where you installed Metavision artifacts (check both the `build` folder of the source code and `C:\Program Files\Prophesee` which is the default install path of the deployment step). +### Retrieving OpenEB source code + +To retrieve OpenEB source code, you can just clone the [GitHub repository](https://github.com/prophesee-ai/openeb): + +```bash +git clone https://github.com/prophesee-ai/openeb.git --branch 5.0.0 +``` + +In the following sections, absolute path to this directory is called ``OPENEB_SRC_DIR`` + +If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, +you need to ensure that you select a `Full.Source.Code.*` archive instead of using +the automatically generated `Source.Code.*` archives. This is because the latter do not include +a necessary submodule. + ### Prerequisites Some steps of this procedure don't work on FAT32 and exFAT file system. @@ -284,15 +315,26 @@ Those can be found in the [vcpkg repository](https://github.com/microsoft/vcpkg/ %USERPROFILE%\AppData\Local\Programs\Python\Python38\Scripts %USERPROFILE%\AppData\Local\Microsoft\WindowsApps ```` +We recommend using Python with [virtualenv](https://virtualenv.pypa.io/en/latest/) to avoid conflicts with other installed Python packages. -Then install `pip` and some Python libraries: +Create a virtual environment and install the necessary dependencies: ```bash -python -m pip install pip --upgrade -python -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy -python -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner +python -m venv C:\tmp\prophesee\py3venv --system-site-packages +C:\tmp\prophesee\py3venv\Scripts\python -m pip install pip --upgrade +C:\tmp\prophesee\py3venv\Scripts\python -m pip install -r OPENEB_SRC_DIR\utils\python\python_requirements\requirements_openeb.txt ``` +When creating the virtual environment, it is necessary to use the `--system-site-packages` option to ensure that +the SDK packages installed in the system directories are accessible. However, this option also makes your local +user site-packages visible by default. +To prevent this and maintain a cleaner virtual environment, you can set the environment variable `PYTHONNOUSERSITE` to true. + +Optionally, you can run the `activate` command (`C:\tmp\prophesee\py3venv\Scripts\activate`) to modify your shell's environment variables, +setting the virtual environment's Python interpreter and scripts as the default for your current session. +This allows you to use simple commands like `python` without needing to specify the full path each time. + + #### Install pybind The Python bindings of the C++ API rely on the [pybind11](https://github.com/pybind) library. @@ -309,33 +351,12 @@ To use Machine Learning features, you need to install some additional dependenci First, if you have some Nvidia hardware with GPUs, you can optionally install [CUDA (11.6 or 11.7)](https://developer.nvidia.com/cuda-downloads) and [cuDNN](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html) to leverage them with pytorch and libtorch. -Then, you need to install [PyTorch 1.13.1](https://pytorch.org). -Retrieve and execute the pip command of version 1.13.1 from -the [previous versions install guide section](). - -Then install some extra Python libraries: - -```bash -python -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning==1.8.6" "tqdm==4.63.0" "kornia==0.6.8" -``` ### Compilation -First, retrieve the codebase: - -```bash -git clone https://github.com/prophesee-ai/openeb.git --branch 4.6.2 -``` - -Note that if you choose to download an archive of OpenEB from GitHub rather than cloning the repository, -you need to ensure that you select a ``Full.Source.Code.*`` archive instead of using -the automatically generated ``Source.Code.*`` archives. This is because the latter do not include -a necessary submodule. - - #### Compilation using CMake -Open a command prompt inside the `openeb` folder (absolute path to this directory is called `OPENEB_SRC_DIR` in next sections) and do as follows: +Open a command prompt inside the `OPENEB_SRC_DIR` folder : 1. Create and open the build directory, where temporary files will be created: `mkdir build && cd build` 2. Generate the makefiles using CMake: `cmake .. -A x64 -DCMAKE_TOOLCHAIN_FILE=\cmake\toolchains\vcpkg.cmake -DVCPKG_DIRECTORY=`. @@ -393,7 +414,7 @@ or you can deploy the OpenEB files (applications, samples, libraries etc.) in a #### Compilation using MS Visual Studio -Open a command prompt inside the `openeb` folder (absolute path to this directory is called `OPENEB_SRC_DIR` in next sections) and do as follows: +Open a command prompt inside the `OPENEB_SRC_DIR` folder: 1. Create and open the build directory, where temporary files will be created: `mkdir build && cd build` 2. Generate the Visual Studio files using CMake: `cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_TOOLCHAIN_FILE=\cmake\toolchains\vcpkg.cmake -DVCPKG_DIRECTORY=` (adapt to your Visual Studio version). diff --git a/cmake/Modules/FindPython/Support.cmake b/cmake/Modules/FindPython/Support.cmake index 12506a197..e18896e06 100644 --- a/cmake/Modules/FindPython/Support.cmake +++ b/cmake/Modules/FindPython/Support.cmake @@ -22,9 +22,7 @@ if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) message (FATAL_ERROR "FindPython: INTERNAL ERROR") endif() if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3") - set(_${_PYTHON_PREFIX}_VERSIONS 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) -elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2") - set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) + set(_${_PYTHON_PREFIX}_VERSIONS 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2) else() message (FATAL_ERROR "FindPython: INTERNAL ERROR") endif() @@ -462,7 +460,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (_${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING) if (NAME STREQUAL "PREFIX") - execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('base') or '', sysconfig.get_config_var('installed_base') or '']))" + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('base') or '', sysconfig.get_config_var('installed_base') or '']))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -479,7 +477,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) set (_scheme "posix_prefix") endif() execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('platinclude'),sysconfig.get_path('platinclude','${_scheme}'),sysconfig.get_path('include'),sysconfig.get_path('include','${_scheme}')]))" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('platinclude'),sysconfig.get_path('platinclude','${_scheme}'),sysconfig.get_path('include'),sysconfig.get_path('include','${_scheme}')]))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -491,7 +489,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) endif() elseif (NAME STREQUAL "SOABI") execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '',sysconfig.get_config_var('SO') or '']))\nexcept Exception:\n import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '',sysconfig.get_config_var('SO') or '']))" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '',sysconfig.get_config_var('SO') or '']))\nexcept Exception:\n import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '',sysconfig.get_config_var('SO') or '']))" RESULT_VARIABLE _result OUTPUT_VARIABLE _soabi ERROR_QUIET @@ -516,7 +514,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) set (config_flag "LIBPL") endif() execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))\nexcept Exception:\n import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))\nexcept Exception:\n import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -1776,7 +1774,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # retrieve various package installation directories execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('stdlib'),sysconfig.get_path('platstdlib'),sysconfig.get_path('purelib'),sysconfig.get_path('platlib')]))" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('stdlib'),sysconfig.get_path('platstdlib'),sysconfig.get_path('purelib'),sysconfig.get_path('platlib')]))" RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE _${_PYTHON_PREFIX}_LIBPATHS ERROR_QUIET) diff --git a/cmake/android/env.cmake b/cmake/android/env.cmake index 0a20c2130..8f5bd0b97 100644 --- a/cmake/android/env.cmake +++ b/cmake/android/env.cmake @@ -36,13 +36,7 @@ if (NOT DEFINED METAVISION_ANDROID_ENV_INCLUDED) message(FATAL_ERROR "Could not find android NDK, make sure it is installed or set the ANDROID_NDK_DIR env. variable to point to it") endif (ANDROID_NDK_DIR) - # Get Android ndk version - file(READ ${ANDROID_NDK_DIR}/source.properties _ndk_source_props) - string(REGEX MATCH "Pkg\\.Revision = ([0-9.]*)" _ ${_ndk_source_props}) - set(ANDROID_NDK_VERSION ${CMAKE_MATCH_1}) - if ("${ANDROID_NDK_VERSION}" STREQUAL "") - message(FATAL_ERROR "Could not get Android NDK version from ${ANDROID_NDK_DIR}/source.properties file") - endif ("${ANDROID_NDK_VERSION}" STREQUAL "") + set(ANDROID_NDK_VERSION ${ANDROID_NDK_REVISION} CACHE INTERNAL "Android NDK version") if(DEFINED ENV{ANDROID_ADB}) set(ANDROID_ADB $ENV{ANDROID_ADB}) @@ -59,22 +53,14 @@ if (NOT DEFINED METAVISION_ANDROID_ENV_INCLUDED) message(STATUS "Android ABI : ${ANDROID_ABI}") message(STATUS "Android NDK : ${ANDROID_NDK_VERSION}") - if(ANDROID_NDK_VERSION VERSION_LESS "22") - # @TODO Remove once we update to NDK >22 - if (ANDROID_ABI STREQUAL arm64-v8a) - # arm64-v8a linker seems to not be gold, which causes undefined references - # due to missing transitive dependencies - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold" CACHE STRING "" FORCE) - endif (ANDROID_ABI STREQUAL arm64-v8a) - endif() - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/libs/${ANDROID_ABI} CACHE PATH "Output directory of libraries." FORCE) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/libs/${ANDROID_ABI} CACHE PATH "Output directory of archives." FORCE) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bins/${ANDROID_ABI} CACHE PATH "Output directory of runtimes." FORCE) endif (NOT DEFINED METAVISION_ANDROID_ENV_INCLUDED) if (NOT DEFINED ANDROID_PREBUILT_3RDPARTY_DIR) - set(ANDROID_PREBUILT_3RDPARTY_DIR ${GENERATE_FILES_DIRECTORY}/android/3rdparty/prebuilt) + # if not defined, we are using this in config mode from the prebuilt archive + set(ANDROID_PREBUILT_3RDPARTY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../../) endif (NOT DEFINED ANDROID_PREBUILT_3RDPARTY_DIR) # libusb has no config module, we need to create imported targets by hand @@ -89,113 +75,13 @@ if (NOT TARGET libusb-1.0) set_target_properties(libusb-1.0 PROPERTIES INTERFACE_LINK_LIBRARIES log) endif (NOT TARGET libusb-1.0) -# Boost has no config module, we need to create imported targets by hand -set(_boost_root ${ANDROID_PREBUILT_3RDPARTY_DIR}/boost-1.69.0) -set(_boost_components - atomic - chrono - container - context - contract - coroutine - date_time - fiber - filesystem - graph - iostreams - log - log_setup - math_c99 - math_c99f - math_c99l - math_tr1 - math_tr1f - math_tr1l - prg_exec_monitor - program_options - random - regex - serialization - stacktrace_basic - stacktrace_noop - system - thread - timer - type_erasure - unit_test_framework - wave - wserialization -) -set(Boost_INCLUDE_DIR "${_boost_root}/include") -set(Boost_FOUND TRUE) -foreach(b_comp ${_boost_components}) - string(TOUPPER ${b_comp} b_comp_uc) - if (NOT TARGET Boost::${b_comp}) - add_library(Boost::${b_comp} SHARED IMPORTED) - set_target_properties(Boost::${b_comp} PROPERTIES IMPORTED_LOCATION "${_boost_root}/libs/llvm/${ANDROID_ABI}/libboost_${b_comp}.so") - set_target_properties(Boost::${b_comp} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_boost_root}/include") - # Implicit dependencies - if ("${b_comp}" STREQUAL "filesystem") - set_target_properties(Boost::filesystem PROPERTIES INTERFACE_LINK_LIBRARIES Boost::system) - elseif ("${b_comp}" STREQUAL "timer") - set_target_properties(Boost::timer PROPERTIES INTERFACE_LINK_LIBRARIES Boost::chrono) - endif () - endif (NOT TARGET Boost::${b_comp}) - set(Boost_${b_comp_uc}_FOUND TRUE) -endforeach(b_comp) - -# FFMpeg has no config module, we need to create imported targets by hand -set(_ffmpeg_root ${ANDROID_PREBUILT_3RDPARTY_DIR}/mobile-ffmpeg-min-gpl-4.3) -set(_ffmpeg_components - avcodec - avdevice - avfilter - avformat - avutil - swresample - swscale -) -set(FFMPEG_INCLUDE_DIR "${_ffmpeg_root}/include") -set(FFMPEG_FOUND TRUE) -foreach(b_comp ${_ffmpeg_components}) - string(TOUPPER ${b_comp} b_comp_uc) - if (NOT TARGET FFMPEG::${b_comp}) - add_library(FFMPEG::${b_comp} SHARED IMPORTED) - set_target_properties(FFMPEG::${b_comp} PROPERTIES IMPORTED_LOCATION "${_ffmpeg_root}/android-${ANDROID_ABI}/ffmpeg/lib/lib${b_comp}.so") - set_target_properties(FFMPEG::${b_comp} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_ffmpeg_root}/android-${ANDROID_ABI}/ffmpeg/include") - # Implicit dependencies - if ("${b_comp}" STREQUAL "avdevice") - set_target_properties(FFMPEG::avdevice PROPERTIES INTERFACE_LINK_LIBRARIES FFMPEG::avfilter) - elseif ("${b_comp}" STREQUAL "avfilter") - set_target_properties(FFMPEG::avfilter PROPERTIES INTERFACE_LINK_LIBRARIES FFMPEG::avformat) - elseif ("${b_comp}" STREQUAL "avformat") - set_target_properties(FFMPEG::avformat PROPERTIES INTERFACE_LINK_LIBRARIES FFMPEG::avcodec) - elseif ("${b_comp}" STREQUAL "avcodec") - set_target_properties(FFMPEG::avcodec PROPERTIES INTERFACE_LINK_LIBRARIES FFMPEG::swresample) - elseif ("${b_comp}" STREQUAL "swresample") - set_target_properties(FFMPEG::swresample PROPERTIES INTERFACE_LINK_LIBRARIES FFMPEG::avutil) - elseif ("${b_comp}" STREQUAL "swscale") - set_target_properties(FFMPEG::swscale PROPERTIES INTERFACE_LINK_LIBRARIES FFMPEG::avutil) - endif () - endif (NOT TARGET FFMPEG::${b_comp}) - set(FFMPEG_${b_comp_uc}_FOUND TRUE) -endforeach(b_comp) - +# Boost has a config module +set(Boost_USE_STATIC_LIBS ON) +list(APPEND CMAKE_FIND_ROOT_PATH ${ANDROID_PREBUILT_3RDPARTY_DIR}/boost-1.79.0/libs/arm64-v8a/cmake) +set(Boost_DIR ${ANDROID_PREBUILT_3RDPARTY_DIR}/boost-1.79.0/libs/arm64-v8a/cmake CACHE PATH "Path to precompiled android boost") # OpenCV comes with its own module, let's use it -set(_opencv_root ${ANDROID_PREBUILT_3RDPARTY_DIR}/opencv-4.0.1/sdk/native) -set(OpenCV_DIR ${_opencv_root}/jni) - -# .. however the individual targets are static libraries, so we create a fake one that uses -# libopencv_java which is a shared library as we expect -include_directories(${ANDROID_OPENCV_INC_DIR}) -if (NOT TARGET OpenCV::java) - add_library(OpenCV::java SHARED IMPORTED) - set_target_properties(OpenCV::java PROPERTIES IMPORTED_LOCATION "${_opencv_root}/libs/${ANDROID_ABI}/libopencv_java4.so") - set_target_properties(OpenCV::java PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_opencv_root}/jni/include") - set_target_properties(OpenCV::java PROPERTIES INTERFACE_LINK_LIBRARIES "z;log;android;jnigraphics") -endif (NOT TARGET OpenCV::java) -set(OpenCV_LIBS OpenCV::java) +set(OpenCV_DIR ${ANDROID_PREBUILT_3RDPARTY_DIR}/opencv-4.8.0/sdk/native/jni CACHE PATH "Path to precompiled android opencv") # GTest and GMock set(GTest_DIR "${ANDROID_PREBUILT_3RDPARTY_DIR}/googletest-1.10.0/lib/cmake/GTest") diff --git a/cmake/custom_functions/add_library_version_header.cmake b/cmake/custom_functions/add_library_version_header.cmake index 9b5deb667..0d27e025c 100644 --- a/cmake/custom_functions/add_library_version_header.cmake +++ b/cmake/custom_functions/add_library_version_header.cmake @@ -7,9 +7,9 @@ # 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(GIT_BRANCH "main") -set(GIT_COMMIT_ID "9c0f658666f1927050f21407f6c0f5ae2e120f1f") -set(GIT_COMMIT_DATE "2024-07-01 15:48:10 +0200") +set(GIT_BRANCH "feature/MV-2169-update-openeb-github-actions") +set(GIT_COMMIT_ID "02d6da3c95ac2d7d9daf7d2b3400f6c40a1fc6fc") +set(GIT_COMMIT_DATE "2024-09-10 09:38:21 +0200") find_program(GIT_SCM git DOC "Git version control" HINTS "C:\\Program Files\\Git\\bin\\") @@ -135,17 +135,31 @@ function(add_library_version_header target_name outputfile libname) string(TOUPPER "${libname}" LIBRARY_NAME_UPPER) + set(version_file_command + ${CMAKE_COMMAND} + -DOUTPUTFILE=${outputfile} + -DLIBRARY_NAME_UPPER=${LIBRARY_NAME_UPPER} + -DLIBRARY_VERSION_MAJOR=${LIBRARY_VERSION_MAJOR} + -DLIBRARY_VERSION_MINOR=${LIBRARY_VERSION_MINOR} + -DLIBRARY_VERSION_PATCH=${LIBRARY_VERSION_PATCH} + -DLIBRARY_VERSION_SUFFIX=${LIBRARY_VERSION_SUFFIX} + -P ${cmake_script}) + add_custom_target( ${target_name} ALL - COMMAND ${CMAKE_COMMAND} - -D OUTPUTFILE=${outputfile} - -D LIBRARY_NAME_UPPER=${LIBRARY_NAME_UPPER} - -D LIBRARY_VERSION_MAJOR=${LIBRARY_VERSION_MAJOR} - -D LIBRARY_VERSION_MINOR=${LIBRARY_VERSION_MINOR} - -D LIBRARY_VERSION_PATCH=${LIBRARY_VERSION_PATCH} - -D LIBRARY_VERSION_SUFFIX=${LIBRARY_VERSION_SUFFIX} - -P ${cmake_script} + COMMAND ${version_file_command} COMMENT "Generating version file for library ${libname}" VERBATIM ) + if (NOT EXISTS ${outputfile}) + # Make sure version.h exist at configure then it's updated at runtime + execute_process( + COMMAND ${version_file_command} + ERROR_VARIABLE err + RESULT_VARIABLE ret + ) + if(ret AND NOT ret EQUAL 0) + message(FATAL_ERROR "Error execuding command \n'${version_file_command}' :\n${err}") + endif() + endif() endfunction(add_library_version_header) diff --git a/cmake/custom_functions/python3.cmake b/cmake/custom_functions/python3.cmake index eb1d37f0a..ffab4118e 100644 --- a/cmake/custom_functions/python3.cmake +++ b/cmake/custom_functions/python3.cmake @@ -36,7 +36,7 @@ function(_add_global_alias_library lib alias_lib) if (MSVC) # workaround for a bug in Python on Windows, where the debug lib links to the relase lib file with a relative path set_property(TARGET ${alias_lib} APPEND PROPERTY INTERFACE_LINK_DIRECTORIES "$<$:$>") - endif () + endif() endif() endfunction() @@ -59,7 +59,7 @@ if (COMPILE_PYTHON3_BINDINGS) # FindPython3.cmake stores internal variables relative to the directory in which it is called # If we want to call it multiple times for different python versions, it must be called from # different folders (see https://gitlab.kitware.com/cmake/cmake/-/issues/21797) - add_subdirectory(${GENERATE_FILES_DIRECTORY}/python3 ${CMAKE_BINARY_DIR}/cmake/python3/${_python_version}) + add_subdirectory(${GENERATE_FILES_DIRECTORY}/python3 ${PROJECT_BINARY_DIR}/cmake/python3/${_python_version}) endforeach() else() find_package(Python3 COMPONENTS Interpreter Development REQUIRED) @@ -70,22 +70,26 @@ if (COMPILE_PYTHON3_BINDINGS) endif() foreach (_python_version ${PYBIND11_PYTHON_VERSIONS}) # this is the extension we need to set for the python bindings module - execute_process( - COMMAND "${PYTHON_${_python_version}_EXECUTABLE}" "-c" - "from distutils import sysconfig as s; print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO'));" - OUTPUT_VARIABLE PYTHON_${_python_version}_MODULE_EXTENSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + if(CMAKE_CROSSCOMPILING) + # When cross compiling, we cannot run the python interpreter as it might be compiled for a different architecture. + # Therefore we ask for the user to have already set the library extension suffix. + if(NOT DEFINED PYTHON_${_python_version}_MODULE_EXTENSION) + message(FATAL_ERROR "CMake variable 'PYTHON_${_python_version}_MODULE_EXTENSION' needs to be defined. " + "One can run '$ python3-config --extension-suffix' on your targeted platform to get the actual value (eg. '.cpython-36m-x86_64-linux-gnu.so'). + ") + endif() + else() + execute_process( + COMMAND "${PYTHON_${_python_version}_EXECUTABLE}" "-c" + "import sysconfig as s; print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO'));" + OUTPUT_VARIABLE PYTHON_${_python_version}_MODULE_EXTENSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif(CMAKE_CROSSCOMPILING) # this is the path where we install our python modules for cpack DEB (system) packages ... execute_process( - # select a suitable python module path by following ranking (i.e a path that meets - # criteria 1. is better than 2., and a path that meets criteria 1.+2. is better than 1.+3.) - # 1-a path that does not contain 'local' - # 2-a path that contains 'dist-packages' - # 3-a path that contains 'site-packages' - COMMAND "${PYTHON_${_python_version}_EXECUTABLE}" "-c" - "import site; print(sorted(site.getsitepackages(), key=lambda path: ('local' not in path)*100.0 + ('dist-packages' in path)*10.0 + ('site-packages' in path)*1.0, reverse=True)[0])" + COMMAND "${PYTHON_${_python_version}_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/utils/scripts/get_prefered_site_packages.py" "--site-type" "system" OUTPUT_VARIABLE PYTHON_${_python_version}_SYSTEM_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE ) @@ -102,31 +106,24 @@ if (COMPILE_PYTHON3_BINDINGS) # Otherwise, if no module path is provided, find a proper path to install our modules # note : we do not use the PYTHON_SITE_PACKAGES found by pybind11, as it is wrong execute_process( - # select a suitable python module path by following ranking (i.e a path that meets - # criteria 1. is better than 2., and a path that meets criteria 1.+2. is better than 1.+3.) - # 1-the cmake install prefix - # 2-a path that contains 'dist-packages' - # 3-a path that contains 'site-packages' - COMMAND "${PYTHON_${_python_version}_EXECUTABLE}" "-c" - "import site; print(sorted(site.getsitepackages(), key=lambda path: path.startswith('${CMAKE_INSTALL_PREFIX}')*100.0 + ('dist-packages' in path)*10.0 + ('site-packages' in path)*1.0, reverse=True)[0])" + COMMAND "${PYTHON_${_python_version}_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/utils/scripts/get_prefered_site_packages.py" "--site-type" "local" "--prefer-pattern" "${CMAKE_INSTALL_PREFIX}" OUTPUT_VARIABLE PYTHON_${_python_version}_LOCAL_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE ) file(TO_CMAKE_PATH "${PYTHON_${_python_version}_LOCAL_SITE_PACKAGES}" PYTHON_${_python_version}_LOCAL_SITE_PACKAGES) - # ... it must be relative - string(REGEX REPLACE "^${STAGING_DIR_NATIVE}/usr/" "" PYTHON_${_python_version}_LOCAL_SITE_PACKAGES "${PYTHON_${_python_version}_LOCAL_SITE_PACKAGES}") endif (PYTHON3_SITE_PACKAGES) + # ... it must be relative string(REGEX REPLACE "^${STAGING_DIR_NATIVE}/usr/" "" PYTHON_${_python_version}_LOCAL_SITE_PACKAGES "${PYTHON_${_python_version}_LOCAL_SITE_PACKAGES}") endforeach () # this variable is used to create all python versions packages variables for cpack # but not all of them will be generated, only the one indicated by PYBIND11_PYTHON_VERSIONS - set (PYTHON3_ALL_VERSIONS "3.7;3.8;3.9;3.10") + set (PYTHON3_ALL_VERSIONS "3.7;3.8;3.9;3.10;3.11;3.12") # this variable is used to set the default version for package dependency, i.e this version # is always available for the current installation if (UNIX AND NOT APPLE AND (NOT DEFINED PYTHON3_DEFAULT_VERSION)) - set (PYTHON3_DEFAULT_VERSION "3.8") + set (PYTHON3_DEFAULT_VERSION "3.9") find_program(_lsb_release_exec lsb_release) if (_lsb_release_exec) execute_process(COMMAND ${_lsb_release_exec} -cs @@ -134,7 +131,9 @@ if (COMPILE_PYTHON3_BINDINGS) OUTPUT_STRIP_TRAILING_WHITESPACE ) if ("${_ubuntu_platform}" STREQUAL "jammy") - set (PYTHON3_DEFAULT_VERSION "3.10") + set (PYTHON3_DEFAULT_VERSION "3.10") + elseif ("${_ubuntu_platform}" STREQUAL "noble") + set (PYTHON3_DEFAULT_VERSION "3.12") endif () endif() else() @@ -176,7 +175,7 @@ endif() if (COMPILE_PYTHON3_BINDINGS) # pybind11 should not look for Python anymore, we already handled it set(PYBIND11_NOPYTHON On) - find_package(pybind11 REQUIRED) + find_package(pybind11 2.7 REQUIRED) # private helper function to install a python module for a specific python version with LOCAL and/or SYSTEM python component function(_install_python_bindings_for_version target_name python_version component) @@ -299,10 +298,10 @@ if (COMPILE_PYTHON3_BINDINGS) if(WIN32 AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py - DESTINATION ${CMAKE_BINARY_DIR}/py3/${CMAKE_BUILD_TYPE}/${module} + DESTINATION ${PROJECT_BINARY_DIR}/py3/${CMAKE_BUILD_TYPE}/${module} FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) foreach(_python_version ${PYBIND11_PYTHON_VERSIONS}) - install(DIRECTORY ${CMAKE_BINARY_DIR}/py3/${CMAKE_BUILD_TYPE}/${module} + install(DIRECTORY ${PROJECT_BINARY_DIR}/py3/${CMAKE_BUILD_TYPE}/${module} DESTINATION "${PYTHON_${_python_version}_LOCAL_SITE_PACKAGES}" COMPONENT ${component}-python${_python_version}-local-install PATTERN __pycache__ EXCLUDE) diff --git a/cmake/custom_targets/README_metavision_open.md b/cmake/custom_targets/README_metavision_open.md index 1db9b5b1e..6bfd2be25 100644 --- a/cmake/custom_targets/README_metavision_open.md +++ b/cmake/custom_targets/README_metavision_open.md @@ -10,9 +10,9 @@ to the fast-growing event-based vision community. OpenEB is composed of the [Open modules of Metavision SDK](https://docs.prophesee.ai/stable/modules.html#chapter-modules-and-packaging-open): * HAL: Hardware Abstraction Layer to operate any event-based vision device. * Base: Foundations and common definitions of event-based applications. -* Core: Generic algorithms for visualization, event stream manipulation, applicative pipeline generation. +* Core: Generic algorithms for visualization, event stream manipulation. * Core ML: Generic functions for Machine Learning, event_to_video and video_to_event pipelines. -* Driver: High-level abstraction built on the top of HAL to easily interact with event-based cameras. +* Stream: High-level abstraction built on the top of HAL to easily interact with event-based cameras. * UI: Viewer and display controllers for event-based data. OpenEB also contains the source code of [Prophesee camera plugins](https://docs.prophesee.ai/stable/installation/camera_plugins.html), @@ -60,6 +60,23 @@ sudo make uninstall In addition, make a global check in your system paths (`/usr/lib`, `/usr/local/lib`, `/usr/include`, `/usr/local/include`) and in your environment variables (`PATH`, `PYTHONPATH` and `LD_LIBRARY_PATH`) to remove occurrences of Prophesee or Metavision files. + +### Retrieving OpenEB source code + +To retrieve OpenEB source code, you can just clone the [GitHub repository](https://github.com/prophesee-ai/openeb): + +```bash +git clone https://github.com/prophesee-ai/openeb.git --branch 5.0.0 +``` + +In the following sections, absolute path to this directory is called ``OPENEB_SRC_DIR`` + +If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, +you need to ensure that you select a `Full.Source.Code.*` archive instead of using +the automatically generated `Source.Code.*` archives. This is because the latter do not include +a necessary submodule. + + ### Prerequisites Install the following dependencies: @@ -79,20 +96,34 @@ sudo apt -y install libgtest-dev libgmock-dev ``` For the [Python API](https://docs.prophesee.ai/stable/api/python/index.html#chapter-api-python), you will need Python and some additional libraries. -If Python is not available on your system, install it -We support Python 3.8 and 3.9 on Ubuntu 20.04 and Python 3.9 and 3.10 on Ubuntu 22.04. -If you want to use other versions of Python, some source code modifications will be necessary +We support Python 3.9 and 3.10 on Ubuntu 22.04 and Python 3.11 and 3.12 on Ubuntu 24.04. + +We recommend using Python with [virtualenv](https://virtualenv.pypa.io/en/latest/) to avoid conflicts with other installed Python packages. +So, first install it along with some Python development tools: -Then install `pip` and some Python libraries: ```bash -sudo apt -y install python3-pip python3-distutils -sudo apt -y install python3.X-dev # where X is 8, 9 or 10 depending on your Python version (3.8, 3.9 or 3.10) -python3 -m pip install pip --upgrade -python3 -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy -python3 -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner +sudo apt -y install python3.x-venv python3.x-dev +# where "x" is 9, 10, 11 or 12 depending on your Python version ``` -The Python bindings of the C++ API rely on the [pybind11](https://github.com/pybind) library, specifically version 2.6.0. +Next, create a virtual environment and install the necessary dependencies: + +```bash +python3 -m venv /tmp/prophesee/py3venv --system-site-packages +/tmp/prophesee/py3venv/bin/python -m pip install pip --upgrade +/tmp/prophesee/py3venv/bin/python -m pip install -r OPENEB_SRC_DIR/utils/python/python_requirements/requirements_openeb.txt +``` + +Note that when creating the virtual environment, it is necessary to use the `--system-site-packages` option to ensure that +the SDK packages installed in the system directories are accessible. However, this option also makes your local +user site-packages (typically found in `~/.local/lib/pythonX.Y/site-packages`) visible by default. +To prevent this and maintain a cleaner virtual environment, you can set the environment variable `PYTHONNOUSERSITE` to true. + +Optionally, you can run the `activate` command (`source /tmp/prophesee/py3venv/bin/activate`) to modify your shell's environment variables, +setting the virtual environment's Python interpreter and scripts as the default for your current session. +This allows you to use simple commands like `python` without needing to specify the full path each time. + +The Python bindings of the C++ API rely on the [pybind11](https://github.com/pybind) library, specifically version 2.11.0. *Note* that pybind11 is required only if you want to use the Python bindings of the C++ API . You can opt out of creating these bindings by passing the argument `-DCOMPILE_PYTHON3_BINDINGS=OFF` at step 3 during compilation (see below). @@ -101,9 +132,9 @@ In that case, you will not need to install pybind11, but you won't be able to us Unfortunately, there is no pre-compiled version of pybind11 available, so you need to install it manually: ```bash -wget https://github.com/pybind/pybind11/archive/v2.6.0.zip -unzip v2.6.0.zip -cd pybind11-2.6.0/ +wget https://github.com/pybind/pybind11/archive/v2.11.0.zip +unzip v2.11.0.zip +cd pybind11-2.11.0/ mkdir build && cd build cmake .. -DPYBIND11_TEST=OFF cmake --build . @@ -120,30 +151,15 @@ Make sure that you install a version of CUDA that is compatible with your GPUs b Note that, at the moment, we don't support [OpenCL](https://www.khronos.org/opencl/) and AMD GPUs. -Then, you need to install [PyTorch 1.13.1](https://pytorch.org). -Retrieve and execute the pip command of version 1.13.1 from -the [previous versions install guide section](). - -Then install some extra Python libraries: - -```bash -python3 -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning==1.8.6" "tqdm==4.63.0" "kornia==0.6.8" -``` - ### Compilation - 1. Retrieve the code: `git clone https://github.com/prophesee-ai/openeb.git --branch 4.6.2`. - (If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, - you need to ensure that you select a ``Full.Source.Code.*`` archive instead of using - the automatically generated ``Source.Code.*`` archives. This is because the latter do not include - a necessary submodule.) - 2. Create and open the build directory in the `openeb` folder (absolute path to this directory is called `OPENEB_SRC_DIR` in next sections): `cd openeb; mkdir build && cd build` - 3. Generate the makefiles using CMake: `cmake .. -DBUILD_TESTING=OFF`. + 1. Create and open the build directory `OPENEB_SRC_DIR`: `mkdir build && cd build` + 2. Generate the makefiles using CMake: `cmake .. -DBUILD_TESTING=OFF`. If you want to specify to cmake which version of Python to consider, you should use the option ``-DPython3_EXECUTABLE=``. This is useful, for example, when you have a more recent version of Python than the ones we support installed on your system. In that case, cmake would select it and compilation might fail. - 4. Compile: `cmake --build . --config Release -- -j 4` + 3. Compile: `cmake --build . --config Release -- -j 4` Once the compilation is finished, you have two options: you can choose to work directly from the `build` folder or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/local/include`...). @@ -176,7 +192,7 @@ or you can deploy the OpenEB files in the system path (`/usr/local/lib`, `/usr/l Note that you can also deploy the OpenEB files (applications, samples, libraries etc.) in a directory of your choice by using the `CMAKE_INSTALL_PREFIX` variable (`-DCMAKE_INSTALL_PREFIX=`) when generating the makefiles - in step 3. Similarly, you can configure the directory where the Python packages will be deployed using the + in step 2. Similarly, you can configure the directory where the Python packages will be deployed using the `PYTHON3_SITE_PACKAGES` variable (`-DPYTHON3_SITE_PACKAGES=`). * you also need to update `LD_LIBRARY_PATH` and `HDF5_PLUGIN_PATH` @@ -232,6 +248,21 @@ Then, if you have previously installed any Prophesee's software, you will need t Remove the folders where you installed Metavision artifacts (check both the `build` folder of the source code and `C:\Program Files\Prophesee` which is the default install path of the deployment step). +### Retrieving OpenEB source code + +To retrieve OpenEB source code, you can just clone the [GitHub repository](https://github.com/prophesee-ai/openeb): + +```bash +git clone https://github.com/prophesee-ai/openeb.git --branch 5.0.0 +``` + +In the following sections, absolute path to this directory is called ``OPENEB_SRC_DIR`` + +If you choose to download an archive of OpenEB from GitHub rather than cloning the repository, +you need to ensure that you select a `Full.Source.Code.*` archive instead of using +the automatically generated `Source.Code.*` archives. This is because the latter do not include +a necessary submodule. + ### Prerequisites Some steps of this procedure don't work on FAT32 and exFAT file system. @@ -284,15 +315,26 @@ Those can be found in the [vcpkg repository](https://github.com/microsoft/vcpkg/ %USERPROFILE%\AppData\Local\Programs\Python\Python38\Scripts %USERPROFILE%\AppData\Local\Microsoft\WindowsApps ```` +We recommend using Python with [virtualenv](https://virtualenv.pypa.io/en/latest/) to avoid conflicts with other installed Python packages. -Then install `pip` and some Python libraries: +Create a virtual environment and install the necessary dependencies: ```bash -python -m pip install pip --upgrade -python -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" pandas scipy -python -m pip install jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner +python -m venv C:\tmp\prophesee\py3venv --system-site-packages +C:\tmp\prophesee\py3venv\Scripts\python -m pip install pip --upgrade +C:\tmp\prophesee\py3venv\Scripts\python -m pip install -r OPENEB_SRC_DIR\utils\python\python_requirements\requirements_openeb.txt ``` +When creating the virtual environment, it is necessary to use the `--system-site-packages` option to ensure that +the SDK packages installed in the system directories are accessible. However, this option also makes your local +user site-packages visible by default. +To prevent this and maintain a cleaner virtual environment, you can set the environment variable `PYTHONNOUSERSITE` to true. + +Optionally, you can run the `activate` command (`C:\tmp\prophesee\py3venv\Scripts\activate`) to modify your shell's environment variables, +setting the virtual environment's Python interpreter and scripts as the default for your current session. +This allows you to use simple commands like `python` without needing to specify the full path each time. + + #### Install pybind The Python bindings of the C++ API rely on the [pybind11](https://github.com/pybind) library. @@ -309,33 +351,12 @@ To use Machine Learning features, you need to install some additional dependenci First, if you have some Nvidia hardware with GPUs, you can optionally install [CUDA (11.6 or 11.7)](https://developer.nvidia.com/cuda-downloads) and [cuDNN](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html) to leverage them with pytorch and libtorch. -Then, you need to install [PyTorch 1.13.1](https://pytorch.org). -Retrieve and execute the pip command of version 1.13.1 from -the [previous versions install guide section](). - -Then install some extra Python libraries: - -```bash -python -m pip install "numba==0.56.3" "profilehooks==1.12.0" "pytorch_lightning==1.8.6" "tqdm==4.63.0" "kornia==0.6.8" -``` ### Compilation -First, retrieve the codebase: - -```bash -git clone https://github.com/prophesee-ai/openeb.git --branch 4.6.2 -``` - -Note that if you choose to download an archive of OpenEB from GitHub rather than cloning the repository, -you need to ensure that you select a ``Full.Source.Code.*`` archive instead of using -the automatically generated ``Source.Code.*`` archives. This is because the latter do not include -a necessary submodule. - - #### Compilation using CMake -Open a command prompt inside the `openeb` folder (absolute path to this directory is called `OPENEB_SRC_DIR` in next sections) and do as follows: +Open a command prompt inside the `OPENEB_SRC_DIR` folder : 1. Create and open the build directory, where temporary files will be created: `mkdir build && cd build` 2. Generate the makefiles using CMake: `cmake .. -A x64 -DCMAKE_TOOLCHAIN_FILE=\cmake\toolchains\vcpkg.cmake -DVCPKG_DIRECTORY=`. @@ -393,7 +414,7 @@ or you can deploy the OpenEB files (applications, samples, libraries etc.) in a #### Compilation using MS Visual Studio -Open a command prompt inside the `openeb` folder (absolute path to this directory is called `OPENEB_SRC_DIR` in next sections) and do as follows: +Open a command prompt inside the `OPENEB_SRC_DIR` folder: 1. Create and open the build directory, where temporary files will be created: `mkdir build && cd build` 2. Generate the Visual Studio files using CMake: `cmake .. -G "Visual Studio 17 2022" -A x64 -DCMAKE_TOOLCHAIN_FILE=\cmake\toolchains\vcpkg.cmake -DVCPKG_DIRECTORY=` (adapt to your Visual Studio version). diff --git a/cmake/custom_targets/create_metavision_get_started_archive_folder.cmake b/cmake/custom_targets/create_metavision_get_started_archive_folder.cmake index 9e7b63667..aa22f8129 100644 --- a/cmake/custom_targets/create_metavision_get_started_archive_folder.cmake +++ b/cmake/custom_targets/create_metavision_get_started_archive_folder.cmake @@ -71,7 +71,7 @@ endfunction() # Add some Metavision Python samples to the metavision-get-started folder copy_python_sample("sdk/modules/core/python/samples/metavision_time_surface" "") -copy_python_sample("sdk/modules/ml/python_extended/samples/flow_inference" "flow_viz.py") +copy_python_sample("sdk/modules/ml/python/samples/flow_inference" "") # Add some Metavision C++ samples to the metavision-get-started folder copy_cpp_sample("sdk/modules/core/cpp/samples/metavision_time_surface") diff --git a/cmake/custom_targets/create_metavision_open_archive_folder.cmake b/cmake/custom_targets/create_metavision_open_archive_folder.cmake index e556a606f..8be01a7f4 100644 --- a/cmake/custom_targets/create_metavision_open_archive_folder.cmake +++ b/cmake/custom_targets/create_metavision_open_archive_folder.cmake @@ -18,7 +18,7 @@ string(REPLACE " " ";" HAL_OPEN_PLUGIN_DEVICES "${HAL_OPEN_PLUGIN_DEVICES}") include(overridden_cmake_functions) -set(HAL_OPEN_PLUGIN_FILES apps biasgen cmake CMakeLists.txt lib resources samples test) +set(HAL_OPEN_PLUGIN_FILES apps biasgen cmake CMakeLists.txt lib resources samples python test) set(HAL_OPEN_PLUGIN_INCLUDES boards utils geometries plugin devices/common devices/utils devices/others) set(HAL_OPEN_PLUGIN_HW_LAYER_INCLUDES boards facilities utils devices/common devices/utils devices/psee-video) set(HAL_OPEN_PLUGIN_SOURCES boards CMakeLists.txt facilities plugin utils devices/common devices/utils devices/psee-video devices/others devices/CMakeLists.txt) @@ -34,8 +34,28 @@ list_transform_prepend (HAL_OPEN_PLUGIN_HW_LAYER_INCLUDES psee_hw_layer_headers/ list(APPEND HAL_OPEN_PLUGIN_FILES ${HAL_OPEN_PLUGIN_INCLUDES} ${HAL_OPEN_PLUGIN_SOURCES} ${HAL_OPEN_PLUGIN_HW_LAYER_INCLUDES}) list_transform_prepend (HAL_OPEN_PLUGIN_FILES hal_psee_plugins/) +set(DIRECT_COPY_FILES + CMakeLists.txt + licensing/LICENSE_OPEN + .gitignore conftest.py + pytest.ini + cmake + standalone_samples + hal + ${HAL_OPEN_PLUGIN_FILES} + utils/python/metavision_utils + utils/python/requirements_openeb.txt + utils/cpp utils/scripts + utils/windows/resources.rc.in + utils/windows/vcpkg-openeb.json + utils/CMakeLists.txt + sdk/cmake + sdk/CMakeLists.txt + sdk/modules/CMakeLists.txt +) + # Add the files and folders needed to compile open : -foreach (file_or_dir CMakeLists.txt licensing/LICENSE_OPEN .gitignore conftest.py pytest.ini cmake standalone_samples hal ${HAL_OPEN_PLUGIN_FILES} utils/python/metavision_utils utils/cpp utils/scripts utils/windows/resources.rc.in utils/windows/vcpkg-openeb.json utils/CMakeLists.txt sdk/cmake sdk/CMakeLists.txt sdk/modules/CMakeLists.txt) +foreach (file_or_dir ${DIRECT_COPY_FILES}) if (EXISTS "${PROJECT_SOURCE_DIR}/${file_or_dir}") get_filename_component(dest "${OUTPUT_DIR}/${file_or_dir}" DIRECTORY) file(COPY "${PROJECT_SOURCE_DIR}/${file_or_dir}" @@ -70,7 +90,7 @@ file(REMOVE "${OUTPUT_DIR}/sdk/cmake/MetavisionSDKCPackConfig.cmake") file(REMOVE "${OUTPUT_DIR}/sdk/cmake/MetavisionStudioCPackConfig.cmake") file(REMOVE_RECURSE "${OUTPUT_DIR}/hal/cpp/doc") file(REMOVE_RECURSE "${OUTPUT_DIR}/hal/python/doc") -foreach (mod base core driver ui core_ml) +foreach (mod base core stream ui core_ml) file(COPY "${PROJECT_SOURCE_DIR}/sdk/modules/${mod}" DESTINATION "${OUTPUT_DIR}/sdk/modules") # Remove the code we don't want from the SDK modules (doc): foreach(subdir doc) @@ -87,13 +107,13 @@ endforeach(mod) if (NOT KEEP_GIT_SUBMODULES) # Remove hdf5_ecf submodule - file(REMOVE_RECURSE "${OUTPUT_DIR}/sdk/modules/driver/cpp/3rdparty/hdf5_ecf") + file(REMOVE_RECURSE "${OUTPUT_DIR}/sdk/modules/stream/cpp/3rdparty/hdf5_ecf") endif () # Remove Metavision Studio : file(REMOVE_RECURSE "${OUTPUT_DIR}/sdk/modules/core/cpp/apps/metavision_studio") # Remove evk3d viewer as the plugin is closed source -file(REMOVE_RECURSE "${OUTPUT_DIR}/sdk/modules/driver/cpp/samples/metavision_evk3d_viewer") +file(REMOVE_RECURSE "${OUTPUT_DIR}/sdk/modules/stream/cpp/samples/metavision_evk3d_viewer") # Now we need to modify the way to determine the VCS information (folder created is not be a git repo) string(CONCAT licence_header "# Copyright (c) Prophesee S.A.\n" diff --git a/hal/cpp/include/metavision/hal/decoders/base/base_event_types.h b/hal/cpp/include/metavision/hal/decoders/base/base_event_types.h index 7e2a88793..d580c975d 100644 --- a/hal/cpp/include/metavision/hal/decoders/base/base_event_types.h +++ b/hal/cpp/include/metavision/hal/decoders/base/base_event_types.h @@ -23,8 +23,8 @@ typedef uint8_t EventTypesUnderlying_t; // same for all cameras (it is the case for now, but with every new // sensor we have to check) enum class BaseEventTypes : EventTypesUnderlying_t { - CD_LOW = 0x00, // Left camera CD event, decrease in illumination (polarity '0') - CD_HIGH = 0x01, // Left camera CD event, increase in illumination (polarity '1') + CD_OFF = 0x00, // Left camera CD event, decrease in illumination (polarity '0') + CD_ON = 0x01, // Left camera CD event, increase in illumination (polarity '1') EVT_TIME_HIGH = 0x08, // Timer high bits, also used to synchronize different event flows in the FPGA. EXT_TRIGGER = 0x0A, // External trigger output IMU_EVT = 0x0D, // Inertial Measurement Unit event that relays accelerometer and gyroscope information. diff --git a/hal/cpp/include/metavision/hal/decoders/evt2/evt2_decoder.h b/hal/cpp/include/metavision/hal/decoders/evt2/evt2_decoder.h index eaa1d1f82..7fd6fdbf3 100644 --- a/hal/cpp/include/metavision/hal/decoders/evt2/evt2_decoder.h +++ b/hal/cpp/include/metavision/hal/decoders/evt2/evt2_decoder.h @@ -102,21 +102,23 @@ class EVT2Decoder : public I_EventsStreamDecoder { if (type == static_cast(EventTypesEnum::EVT_TIME_HIGH)) { timestamp new_th = timestamp(ev->trail) << NumBitsInTimestampLSB; const auto last_base_time = base_time_; - if (UPDATE_LOOP) { + if constexpr (UPDATE_LOOP) { new_th += full_shift_; if (has_time_loop(new_th, base_time_)) { full_shift_ += TimeLoop; new_th += TimeLoop; } base_time_ = new_th; + } else if constexpr (APPLY_TIMESHIFT) { + base_time_ = new_th + full_shift_; } else { - base_time_ = APPLY_TIMESHIFT ? new_th + full_shift_ : new_th; + base_time_ = new_th; } // avoid momentary time discrepancies when decoding event per events, time low comes // right after (in an event of another type) to correct the value last_timestamp_ = (base_time_ != last_base_time ? base_time_ : last_timestamp_); - } else if (type == static_cast(EventTypesEnum::CD_LOW) || - type == static_cast(EventTypesEnum::CD_HIGH)) { // CD + } else if (type == static_cast(EventTypesEnum::CD_OFF) || + type == static_cast(EventTypesEnum::CD_ON)) { // CD const EVT2Event2D *ev_td = reinterpret_cast(ev); last_timestamp_ = base_time_ + ev_td->timestamp; last_timestamp_set_ = true; diff --git a/hal/cpp/include/metavision/hal/decoders/evt2/evt2_encoder.h b/hal/cpp/include/metavision/hal/decoders/evt2/evt2_encoder.h new file mode 100644 index 000000000..f865f7160 --- /dev/null +++ b/hal/cpp/include/metavision/hal/decoders/evt2/evt2_encoder.h @@ -0,0 +1,58 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_EVT2_ENCODER_H +#define METAVISION_HAL_EVT2_ENCODER_H + +#include +#include +#include "metavision/sdk/base/utils/timestamp.h" +#include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/events/event_ext_trigger.h" +#include "metavision/hal/decoders/evt2/evt2_event_types.h" + +namespace Metavision { + +/// @brief Class to encode events in EVT2 format +class Evt2Encoder { +public: + /// @brief Constructor + Evt2Encoder() = default; + + /// @brief resets the internal timehigh state of the encoder + void reset_state(); + + /// @brief Encodes a CD event and writes it to the output stream + /// @param ofs Output stream to write the encoded event to + /// @param ev CD event to encode + void encode_event_cd(std::ofstream &ofs, const EventCD &ev); + + /// @brief Encodes a trigger event and writes it to the output stream + /// @param ofs Output stream to write the encoded event to + /// @param ev Trigger event to encode + void encode_event_trigger(std::ofstream &ofs, const EventExtTrigger &ev); + +private: + void write_raw_event(std::ofstream &ofs, const EVT2RawEvent &raw_evt) const; + void write_timehigh(std::ofstream &ofs, timestamp ts_timehigh_ev); + void write_cd(std::ofstream &ofs, const EventCD &ev); + void write_trigger(std::ofstream &ofs, const EventExtTrigger &ev); + void update_timehigh(std::ofstream &ofs, timestamp ts); + + static constexpr timestamp kTime16usMask{(static_cast(1) << 4) - 1}; + bool first_timehigh_written_ = false; + timestamp ts_last_timehigh_ = std::numeric_limits::min(); + timestamp ts_last_ev_ = std::numeric_limits::min(); +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_EVT2_ENCODER_H diff --git a/hal/cpp/include/metavision/hal/decoders/evt2/evt2_event_types.h b/hal/cpp/include/metavision/hal/decoders/evt2/evt2_event_types.h index e5e5e3c1a..cd08a841f 100644 --- a/hal/cpp/include/metavision/hal/decoders/evt2/evt2_event_types.h +++ b/hal/cpp/include/metavision/hal/decoders/evt2/evt2_event_types.h @@ -19,10 +19,10 @@ namespace Metavision { constexpr uint8_t EVT2EventsTimeStampBits = 6; enum class EVT2EventTypes : EventTypesUnderlying_t { - CD_LOW = static_cast( - BaseEventTypes::CD_LOW), // Left camera TD event, decrease in illumination (polarity '0') - CD_HIGH = static_cast( - BaseEventTypes::CD_HIGH), // Left camera TD event, increase in illumination (polarity '1') + CD_OFF = static_cast( + BaseEventTypes::CD_OFF), // Left camera TD event, decrease in illumination (polarity '0') + CD_ON = static_cast( + BaseEventTypes::CD_ON), // Left camera TD event, increase in illumination (polarity '1') EVT_TIME_HIGH = static_cast( BaseEventTypes::EVT_TIME_HIGH), // Timer high bits, also used to synchronize different event flows in the FPGA. EXT_TRIGGER = static_cast(BaseEventTypes::EXT_TRIGGER), // External trigger output @@ -150,6 +150,30 @@ struct EVT2EventMonitorEndOfFrame { static_assert(sizeof(EVT2EventMonitorEndOfFrame) == 4, "The size of the packed struct EVT2EventMonitorEndOfFrame is not the expected one (which is 4 bytes)"); +struct EVT2TimeHigh { + std::uint32_t ts : 28; + std::uint32_t type : 4; +}; +static_assert(sizeof(EVT2TimeHigh) == 4, + "The size of the packed struct EVT2TimeHigh is not the expected one (which is 4 bytes)"); + +struct EVT2EvType { + std::uint32_t unused : 28; + std::uint32_t type : 4; +}; +static_assert(sizeof(EVT2EvType) == 4, + "The size of the packed struct EVT2EvType is not the expected one (which is 4 bytes)"); + +union EVT2RawEvent { + std::uint32_t raw; ///< Raw data type is first to ensure correct brace initialization + EVT2EvType type; + EVT2Event2D cd; + EVT2TimeHigh th; + EVT2EventExtTrigger trig; +}; +static_assert(sizeof(EVT2RawEvent) == 4, + "The size of the packed union EVT2RawEvent is not the expected one (which is 4 bytes)"); + } // namespace Metavision #endif // METAVISION_HAL_EVT2_EVENT_TYPES_H diff --git a/hal/cpp/include/metavision/hal/decoders/evt21/evt21_decoder.h b/hal/cpp/include/metavision/hal/decoders/evt21/evt21_decoder.h index 9eac81d1e..5a1d8ce05 100644 --- a/hal/cpp/include/metavision/hal/decoders/evt21/evt21_decoder.h +++ b/hal/cpp/include/metavision/hal/decoders/evt21/evt21_decoder.h @@ -12,7 +12,10 @@ #ifndef METAVISION_HAL_EVT21_DECODER_H #define METAVISION_HAL_EVT21_DECODER_H +#include + #include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/events/event_cd_vector.h" #include "metavision/sdk/base/events/event_ext_trigger.h" #include "metavision/sdk/base/events/event_erc_counter.h" #include "metavision/sdk/base/utils/detail/bitinstructions.h" @@ -20,24 +23,31 @@ #include "metavision/hal/facilities/i_events_stream_decoder.h" #include "metavision/hal/decoders/base/event_base.h" #include "metavision/hal/decoders/evt21/evt21_event_types.h" +#include "metavision/hal/utils/detail/type_check.h" namespace Metavision { template + typename Event_OTHERS, typename OutputCDType = EventCD> class EVT21GenericDecoder : public I_EventsStreamDecoder { public: - using EventTypesEnum = Evt21EventTypes_4bits; - - EVT21GenericDecoder( - bool time_shifting_enabled, - const std::shared_ptr> &event_cd_decoder = std::shared_ptr>(), - const std::shared_ptr> &event_ext_trigger_decoder = - std::shared_ptr>(), - const std::shared_ptr> &erc_count_event_decoder = - std::shared_ptr>()) : + using EventTypesEnum = Evt21EventTypes_4bits; + using EventCDForwarder = I_EventsStreamDecoder::DecodedEventForwarder; + using OutputCDTypes = std::variant; + + EVT21GenericDecoder(bool time_shifting_enabled, + const std::shared_ptr> &event_cd_decoder = + std::shared_ptr>(), + const std::shared_ptr> &event_ext_trigger_decoder = + std::shared_ptr>(), + const std::shared_ptr> &erc_count_event_decoder = + std::shared_ptr>()) : I_EventsStreamDecoder(time_shifting_enabled, event_cd_decoder, event_ext_trigger_decoder, - erc_count_event_decoder) {} + erc_count_event_decoder) { + static_assert(Metavision::detail::is_in_type_list_v, + "Error, cannot construct EVT21GenericDecoder with specified OutputCDType... Supported types are: " + "{EventCD, EventCDVector}."); + } virtual timestamp get_last_timestamp() const override final { if (!last_timestamp_set_) { @@ -60,7 +70,11 @@ class EVT21GenericDecoder : public I_EventsStreamDecoder { private: template timestamp last_timestamp() const { - return DO_TIMESHIFT ? last_timestamp_ - timestamp_shift_ : last_timestamp_; + if constexpr (DO_TIMESHIFT) { + return last_timestamp_ - timestamp_shift_; + } else { + return last_timestamp_; + } } void decode_impl(const RawData *const cur_raw_data, const RawData *const raw_data_end) override { @@ -95,7 +109,7 @@ class EVT21GenericDecoder : public I_EventsStreamDecoder { template void decode_events_buffer(const RawEvent *&cur_raw_ev, const RawEvent *const raw_ev_end) { - auto &cd_forwarder = cd_event_forwarder(); + auto &cd_forwarder = cd_event_forwarder(); auto &trigger_forwarder = trigger_event_forwarder(); auto &erc_count_forwarder = erc_count_event_forwarder(); @@ -108,21 +122,29 @@ class EVT21GenericDecoder : public I_EventsStreamDecoder { if (type == static_cast(Evt21EventTypes_4bits::EVT_POS) || type == static_cast(Evt21EventTypes_4bits::EVT_NEG)) { const Event_2D *ev_td = reinterpret_cast(cur_ev); - uint16_t last_x = ev_td->x; + uint16_t base_x = ev_td->x; uint16_t y = ev_td->y; last_timestamp_ = (last_timestamp_ & ~((1ULL << 6) - 1)) + ev_td->ts; last_timestamp_set_ = true; - uint32_t valid = ev_td->valid; + uint32_t vector_mask = ev_td->valid; const RawEvent *ev = reinterpret_cast(cur_ev); - bool pol = ev->type == static_cast(Evt21EventTypes_4bits::EVT_POS); - uint16_t off = 0; - while (valid) { - off = ctz_not_zero(valid); - valid &= ~(1 << off); - cd_forwarder.forward(last_x + off, y, static_cast(pol), last_timestamp()); + bool polarity = ev->type == static_cast(Evt21EventTypes_4bits::EVT_POS); + + if constexpr (std::is_same_v) { + uint16_t offset = 0; + while (vector_mask) { + offset = ctz_not_zero(vector_mask); + vector_mask &= ~(1 << offset); + cd_forwarder.forward(base_x + offset, y, static_cast(polarity), last_timestamp()); + } } + + if constexpr (std::is_same_v) { + cd_forwarder.forward(base_x, y, polarity, vector_mask, last_timestamp()); + } + ++cur_ev; } else if (type == static_cast(Evt21EventTypes_4bits::EVT_TIME_HIGH)) { const Event_TIME_HIGH *ev_timehigh = reinterpret_cast(cur_ev); @@ -223,6 +245,9 @@ using EVT21LegacyDecoder = EVT21GenericDecoder; +using EVT21VectorizedDecoder = EVT21GenericDecoder; + } // namespace Metavision #endif // METAVISION_HAL_EVT21_DECODER_H diff --git a/hal/cpp/include/metavision/hal/decoders/evt3/evt3_decoder.h b/hal/cpp/include/metavision/hal/decoders/evt3/evt3_decoder.h index 349634514..6eddd3266 100644 --- a/hal/cpp/include/metavision/hal/decoders/evt3/evt3_decoder.h +++ b/hal/cpp/include/metavision/hal/decoders/evt3/evt3_decoder.h @@ -85,7 +85,11 @@ class EVT3Decoder : public I_EventsStreamDecoder { private: template timestamp last_timestamp() const { - return DO_TIMESHIFT ? last_timestamp_.time - timestamp_shift_ : last_timestamp_.time; + if constexpr (DO_TIMESHIFT) { + return last_timestamp_.time - timestamp_shift_; + } else { + return last_timestamp_.time; + } } virtual void decode_impl(const RawData *const cur_raw_data, const RawData *const raw_data_end) override { diff --git a/hal/cpp/include/metavision/hal/decoders/evt4/evt4_decoder.h b/hal/cpp/include/metavision/hal/decoders/evt4/evt4_decoder.h new file mode 100644 index 000000000..033aa1cca --- /dev/null +++ b/hal/cpp/include/metavision/hal/decoders/evt4/evt4_decoder.h @@ -0,0 +1,289 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_EVT4_DECODER_H +#define METAVISION_HAL_EVT4_DECODER_H + +#include "metavision/hal/facilities/i_events_stream_decoder.h" +#include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/events/event_ext_trigger.h" +#include "metavision/sdk/base/utils/detail/bitinstructions.h" +#include "metavision/hal/facilities/i_event_decoder.h" +#include "metavision/hal/decoders/evt4/evt4_event_types.h" +#include "metavision/hal/decoders/evt4/evt4_validator.h" + +#include +#include +#include + +namespace Metavision { + +namespace detail { + +template +class EVT4Decoder : public I_EventsStreamDecoder { +public: + using RawEvent = Evt4Raw::RawEvent; + using EventTypesEnum = EVT4EventTypes; + using Event_Word_Type = std::uint32_t; + + static constexpr std::uint8_t NumBitsInTimestampLSB{6}; + static constexpr std::uint8_t NumBitsInTimestampMSB{28}; + static constexpr timestamp MaxTimestamp{((static_cast(1) << NumBitsInTimestampMSB) - 1) + << NumBitsInTimestampLSB}; + static constexpr timestamp LoopThreshold{(MaxTimestamp >> 1) + 1}; + static constexpr timestamp TimeLoop{MaxTimestamp + (1 << NumBitsInTimestampLSB)}; + static constexpr std::uint32_t MaxWidth{1 << 11}; + static constexpr std::uint32_t MaxHeight{1 << 11}; + + EVT4Decoder( + bool time_shifting_enabled, const std::optional &width = std::nullopt, + const std::optional &height = std::nullopt, + const std::shared_ptr> &event_cd_decoder = std::shared_ptr>(), + const std::shared_ptr> &event_ext_trigger_decoder = + std::shared_ptr>(), + const std::shared_ptr> &erc_count_event_decoder = + std::shared_ptr>()) : + I_EventsStreamDecoder(time_shifting_enabled, event_cd_decoder, event_ext_trigger_decoder, + erc_count_event_decoder), + validator_(width.value_or(MaxWidth), height.value_or(MaxHeight)) { + ev_other_.subtype = static_cast(EVT4EventSubTypes::UNUSED); + } + + virtual bool get_timestamp_shift(timestamp &ts_shift) const override { + ts_shift = shift_th_; + return shift_set_; + } + + virtual timestamp get_last_timestamp() const override { + return last_timestamp_; + } + + std::uint8_t get_raw_event_size_bytes() const override { + return sizeof(RawEvent); + } + +private: + virtual void decode_impl(const RawData *const cur_raw_data, const RawData *const raw_data_end) override { + const RawEvent *cur_raw_ev = reinterpret_cast(cur_raw_data); + const RawEvent *raw_ev_end = reinterpret_cast(raw_data_end); + + if (!base_time_set_) { + for (; !base_time_set_ && cur_raw_ev < raw_ev_end; ++cur_raw_ev) { + const RawEvent *ev = reinterpret_cast(cur_raw_ev); + switch (ev->type) { + case static_cast(EventTypesEnum::CD_VEC_OFF): + case static_cast(EventTypesEnum::CD_VEC_ON): + cur_raw_ev++; + break; + case static_cast(EventTypesEnum::EVT_TIME_HIGH): { + timestamp t = static_cast(ev->trail) << NumBitsInTimestampLSB; + if (!shift_set_) { + shift_th_ = is_time_shifting_enabled() ? t : 0; + full_shift_ = -shift_th_; + shift_set_ = true; + } + base_time_ = t + full_shift_; + base_time_set_ = true; + last_timestamp_ = base_time_; + } break; + } + } + } + + decode_events_buffer(cur_raw_ev, raw_ev_end); + } + + inline void decode_event_vector(DecodedEventForwarder &cd_forwarder, const Evt4Raw::EVT4EventCD *ev_cd, + uint32_t pol, const uint32_t *vect_data) { + if (!validator_.validate_event_cd_vec(ev_cd, vect_data)) { + return; + } + std::uint32_t valid = *vect_data; + const std::uint32_t x = ev_cd->x; + const std::uint32_t y = ev_cd->y; + while (valid) { + auto off = ctz_not_zero(valid); + valid &= valid - 1; // Reset LSB set bit to zero + cd_forwarder.forward(x + off, y, pol, last_timestamp_); + } + } + + void decode_events_buffer(const RawEvent *&cur_raw_ev, const RawEvent *const raw_ev_end) { + auto &cd_forwarder = cd_event_forwarder(); + auto &trigger_forwarder = trigger_event_forwarder(); + auto &erc_count_forwarder = erc_count_event_forwarder(); + if (cd_vec_open_ && cur_raw_ev < raw_ev_end) { + decode_event_vector(cd_forwarder, &ev_cd_, ev_cd_.type & 0x1, + reinterpret_cast(cur_raw_ev)); + ++cur_raw_ev; + cd_vec_open_ = false; + } + for (; cur_raw_ev < raw_ev_end; ++cur_raw_ev) { + const RawEvent *ev = reinterpret_cast(cur_raw_ev); + const std::uint32_t &type = ev->type; + if (type == static_cast(EventTypesEnum::CD_OFF) || + type == static_cast(EventTypesEnum::CD_ON)) { // CD + const auto *ev_cd = reinterpret_cast(ev); + if (!validator_.validate_event_cd(ev_cd)) { + continue; + } + last_timestamp_ = base_time_ + ev_cd->timestamp; + cd_forwarder.forward(static_cast(ev_cd->x), static_cast(ev_cd->y), + type & 1, last_timestamp_); + } else if (type == static_cast(EventTypesEnum::CD_VEC_OFF) || + type == static_cast(EventTypesEnum::CD_VEC_ON)) { // CD Vector + const auto *ev_cd = reinterpret_cast(ev); + last_timestamp_ = base_time_ + ev_cd->timestamp; + if (++cur_raw_ev >= raw_ev_end) { + cd_vec_open_ = true; + ev_cd_ = *ev_cd; + break; + } + decode_event_vector(cd_forwarder, ev_cd, type & 0x1, + reinterpret_cast(cur_raw_ev)); + } else if (type == static_cast(EventTypesEnum::EVT_TIME_HIGH)) { + timestamp new_th = static_cast(ev->trail) << NumBitsInTimestampLSB; + const auto last_base_time = base_time_; + auto full_shift = full_shift_; + new_th += full_shift; + if (base_time_ >= new_th + LoopThreshold) { + full_shift += TimeLoop; + new_th += TimeLoop; + } + + if (!validator_.validate_time_high(base_time_, new_th)) { + continue; + } + + base_time_ = new_th; + full_shift_ = full_shift; + + // Avoid momentary time discrepancies when decoding event per events, time low comes + // right after (in an event of another type) to correct the value + if (base_time_ != last_base_time) { + last_timestamp_ = base_time_; + } + } else if (type == static_cast(EventTypesEnum::EXT_TRIGGER)) { + if (!validator_.validate_ext_trigger(ev)) { + continue; + } + const auto *ev_ext_raw = reinterpret_cast(ev); + last_timestamp_ = base_time_ + ev_ext_raw->timestamp; + trigger_forwarder.forward(static_cast(ev_ext_raw->value), last_timestamp_, + static_cast(ev_ext_raw->id)); + } else if (type == static_cast(EventTypesEnum::OTHER)) { + if (!validator_.validate_event_other(ev)) { + continue; + } + ev_other_ = *reinterpret_cast(ev); + last_timestamp_ = base_time_ + ev_other_.timestamp; + } else if (type == static_cast(EventTypesEnum::CONTINUED)) { + if (!validator_.validate_event_continued(ev)) { + continue; + } + const std::uint16_t &subtype = ev_other_.subtype; + if (subtype == static_cast(EVT4EventSubTypes::MASTER_IN_CD_EVENT_COUNT) || + subtype == static_cast(EVT4EventSubTypes::MASTER_RATE_CONTROL_CD_EVENT_COUNT)) { + const auto *evssf = reinterpret_cast(ev); + erc_count_forwarder.forward( + last_timestamp_, evssf->count, + subtype == static_cast(EVT4EventSubTypes::MASTER_RATE_CONTROL_CD_EVENT_COUNT)); + } + ev_other_.subtype = static_cast(EVT4EventSubTypes::UNUSED); + } + } + } + + /// @brief Resets the decoder last timestamp + /// @param t Timestamp to reset the decoder to + /// @return True if the reset operation could complete, false otherwise. + /// @note It is expected after this call has succeeded, that @ref get_last_timestamp returns @p timestamp + /// @warning If time shifting is enabled, the @p timestamp must be in the shifted time reference + /// @warning After this function has been called with @p timestamp >= 0, it is assumed that the next buffers of + /// raw data to decode contain events with timestamps >= @p timestamp + bool reset_last_timestamp_impl(const timestamp &t) override { + if (is_time_shifting_enabled() && !shift_set_) { + return false; + } + cd_vec_open_ = false; + if (t >= 0) { + constexpr timestamp min_timer_high_val = (1 << NumBitsInTimestampLSB); + base_time_ = min_timer_high_val * (t / min_timer_high_val); + last_timestamp_ = base_time_ + t % min_timer_high_val; + full_shift_ = -shift_th_ + TimeLoop * (base_time_ / TimeLoop); + base_time_set_ = true; + return true; + } else { + base_time_set_ = false; + return true; + } + return false; + } + + bool reset_timestamp_shift_impl(const timestamp &shift) override { + if (shift >= 0 && is_time_shifting_enabled()) { + shift_th_ = shift; + full_shift_ = -shift_th_; + shift_set_ = true; + return true; + } + return false; + } + + bool base_time_set_{false}; + timestamp base_time_{0}; // Base time to add non timer high events' time stamp low to + timestamp shift_th_{0}; // First time high decoded + timestamp last_timestamp_{-1}; // The timestamp of the last event + timestamp full_shift_{0}; // Includes loop and shift_th in one single variable + bool shift_set_{false}; + Evt4Raw::EVT4EventCD ev_cd_; + bool cd_vec_open_{false}; + Evt4Raw::EVT4EventMonitor ev_other_{}; + Validator validator_; +}; + +} // namespace detail + +using EVT4Decoder = detail::EVT4Decoder; +using UnsafeEVT4Decoder = detail::EVT4Decoder; +using RobustEVT4Decoder = detail::EVT4Decoder; + +inline std::unique_ptr make_evt4_decoder( + bool time_shifting_enabled, const std::optional &width = std::nullopt, + const std::optional &height = std::nullopt, + const std::shared_ptr> &event_cd_decoder = std::shared_ptr>(), + const std::shared_ptr> &event_ext_trigger_decoder = + std::shared_ptr>(), + const std::shared_ptr> &erc_count_event_decoder = + std::shared_ptr>()) { + std::unique_ptr decoder; + + if (std::getenv("MV_FLAGS_EVT4_ROBUST_DECODER")) { + MV_HAL_LOG_INFO() << "Using EVT4 Robust decoder."; + decoder = std::make_unique(time_shifting_enabled, width, height, event_cd_decoder, + event_ext_trigger_decoder, erc_count_event_decoder); + + } else if (std::getenv("MV_FLAGS_EVT4_UNSAFE_DECODER")) { + MV_HAL_LOG_INFO() << "Using EVT4 Unsafe decoder."; + decoder = std::make_unique(time_shifting_enabled, width, height, event_cd_decoder, + event_ext_trigger_decoder, erc_count_event_decoder); + } else { + decoder = std::make_unique(time_shifting_enabled, width, height, event_cd_decoder, + event_ext_trigger_decoder, erc_count_event_decoder); + } + + return decoder; +} + +} // namespace Metavision + +#endif // METAVISION_HAL_EVT4_DECODER_H diff --git a/hal/cpp/include/metavision/hal/decoders/evt4/evt4_event_types.h b/hal/cpp/include/metavision/hal/decoders/evt4/evt4_event_types.h new file mode 100644 index 000000000..5cd3b94cd --- /dev/null +++ b/hal/cpp/include/metavision/hal/decoders/evt4/evt4_event_types.h @@ -0,0 +1,93 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_EVT4_EVENT_TYPES_H +#define METAVISION_HAL_EVT4_EVENT_TYPES_H + +#include "metavision/hal/decoders/base/base_event_types.h" +#include "metavision/hal/decoders/base/event_base.h" + +#include + +namespace Metavision { + +enum class EVT4EventTypes : EventTypesUnderlying_t { + OTHER = static_cast(0x6), // To be used for extensions in the event types + CONTINUED = static_cast(0x7), // Extra data to previous events + EXT_TRIGGER = static_cast(0x9), // External trigger output + CD_OFF = static_cast(0xA), // CD OFF event, decrease in illumination (polarity '0') + CD_ON = static_cast(0xB), // CD ON event, increase in illumination (polarity '1') + CD_VEC_OFF = + static_cast(0xC), // CD Vector OFF event, decrease in illumination (polarity '0') + CD_VEC_ON = static_cast(0xD), // CD Vector ON event, increase in illumination (polarity '1') + EVT_TIME_HIGH = static_cast(0xE), // Timer high bits + PADDING = static_cast(0xF) // Padding is all bits set: 0xFFFFFFFF +}; + +enum class EVT4EventSubTypes : std::uint16_t { + MASTER_IN_CD_EVENT_COUNT = static_cast(0x0014), + MASTER_RATE_CONTROL_CD_EVENT_COUNT = static_cast(0x0016), + UNUSED = static_cast(0xFFFF), +}; + +struct EVT4Timestamp { + timestamp time_low : 6; + timestamp time_high : 28; + timestamp n_loop : 30; +}; + +namespace Evt4Raw { + +using RawEvent = EventBase::RawEvent; + +struct EVT4EventCD { + std::uint32_t y : 11; + std::uint32_t x : 11; + std::uint32_t timestamp : 6; + std::uint32_t type : 4; +}; +static_assert(sizeof(EVT4EventCD) == 4, + "The size of the packed struct EVT4EventCD is not the expected one (which is 4 bytes)"); + +struct EVT4EventExtTrigger { + std::uint32_t value : 1; + std::uint32_t count : 7; + std::uint32_t id : 5; + std::uint32_t unused : 9; + std::uint32_t timestamp : 6; + std::uint32_t type : 4; +}; +static_assert(sizeof(EVT4EventExtTrigger) == 4, + "The size of the packed struct EVT4EventExtTrigger is not the expected one (which is 4 bytes)"); + +struct EVT4EventMonitor { + std::uint32_t subtype : 16; + std::uint32_t reserved : 6; + std::uint32_t timestamp : 6; + std::uint32_t type : 4; +}; +static_assert(sizeof(EVT4EventMonitor) == 4, + "The size of the packed struct EVT4EventMonitor is not the expected one (which is 4 bytes)"); + +struct EVT4EventMonitorMasterInCdEventCount { + std::uint32_t count : 22; + std::uint32_t unused : 6; + std::uint32_t type : 4; +}; +static_assert( + sizeof(EVT4EventMonitorMasterInCdEventCount) == 4, + "The size of the packed struct EVT4EventMonitorMasterInCdEventCount is not the expected one (which is 4 bytes)"); + +} // namespace Evt4Raw + +} // namespace Metavision + +#endif // METAVISION_HAL_EVT4_EVENT_TYPES_H diff --git a/hal/cpp/include/metavision/hal/decoders/evt4/evt4_validator.h b/hal/cpp/include/metavision/hal/decoders/evt4/evt4_validator.h new file mode 100644 index 000000000..68202d809 --- /dev/null +++ b/hal/cpp/include/metavision/hal/decoders/evt4/evt4_validator.h @@ -0,0 +1,267 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_EVT4_VALIDATOR_H +#define METAVISION_HAL_EVT4_VALIDATOR_H + +#include +#include +#include +#include + +#include "metavision/sdk/base/utils/timestamp.h" +#include "metavision/hal/facilities/i_events_stream_decoder.h" +#include "metavision/hal/utils/decoder_protocol_violation.h" +#include "metavision/hal/utils/hal_error_code.h" +#include "metavision/hal/decoders/evt4/evt4_event_types.h" + +namespace Metavision { +namespace decoder { +namespace evt4 { + +template +class ValidatorInterface { +protected: + std::map notifiers_map_; + size_t next_cb_idx_{0}; + std::uint32_t width_; + std::uint32_t height_; + +public: + ValidatorInterface(std::uint32_t width, std::uint32_t height) : height_(height), width_(width) {} + + size_t add_protocol_violation_callback(const I_Decoder::ProtocolViolationCallback_t &cb) { + notifiers_map_[next_cb_idx_] = cb; + return next_cb_idx_++; + } + + bool remove_protocol_violation_callback(size_t callback_id) { + auto it = notifiers_map_.find(callback_id); + if (it != notifiers_map_.end()) { + notifiers_map_.erase(it); + return true; + } + return false; + } + + void notify(DecoderProtocolViolation violation) { + if (notifiers_map_.empty()) { + std::ostringstream oss; + oss << "Evt4 protocol violation detected: " << violation; + if (violation == DecoderProtocolViolation::NonMonotonicTimeHigh || + violation == DecoderProtocolViolation::OutOfBoundsEventCoordinate) { + MV_HAL_LOG_ERROR() << oss.str(); + } else { + MV_HAL_LOG_WARNING() << oss.str(); + } + } else { + for (auto &it : notifiers_map_) { + it.second(violation); + } + } + } + + void reset() { + return static_cast(this)->reset_impl(); + } + + bool validate_event_cd(const Evt4Raw::EVT4EventCD *ev) { + return static_cast(this)->validate_event_cd_impl(ev); + } + + bool validate_event_cd_vec(const Evt4Raw::EVT4EventCD *ev, const std::uint32_t *mask) { + return static_cast(this)->validate_event_cd_vec_impl(ev, mask); + } + + bool validate_time_high(timestamp base_time, timestamp time_high) { + return static_cast(this)->validate_time_high_impl(base_time, time_high); + } + + bool validate_ext_trigger(const Evt4Raw::RawEvent *raw_events) { + return static_cast(this)->validate_ext_trigger_impl(raw_events); + } + + bool validate_event_other(const Evt4Raw::RawEvent *raw_events) { + return static_cast(this)->validate_event_other_impl(raw_events); + } + + bool validate_event_continued(const Evt4Raw::RawEvent *raw_events) { + return static_cast(this)->validate_event_continued_impl(raw_events); + } +}; + +class NullCheckValidator : public ValidatorInterface { +public: + NullCheckValidator(std::uint32_t width, std::uint32_t height) : + ValidatorInterface(width, height) {} + + void reset_impl() {} + + bool validate_event_cd_impl([[maybe_unused]] const Evt4Raw::EVT4EventCD *ev) { + return true; + } + + bool validate_event_cd_vec_impl([[maybe_unused]] const Evt4Raw::EVT4EventCD *ev, + [[maybe_unused]] const std::uint32_t *mask) { + return true; + } + + bool validate_time_high_impl([[maybe_unused]] timestamp prev_time_high, [[maybe_unused]] timestamp time_high) { + return true; + } + + bool validate_ext_trigger_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return true; + } + + bool validate_event_other_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return true; + } + + bool validate_event_continued_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return true; + } +}; + +class NotifyValidator : public ValidatorInterface { +protected: + static constexpr timestamp ThJumpThreshold{1'000}; + +public: + NotifyValidator(std::uint32_t width, std::uint32_t height) : ValidatorInterface(width, height) {} + + void reset_impl() {} + + bool validate_event_cd_impl(const Evt4Raw::EVT4EventCD *ev) { + if (ev->y >= height_ || ev->x >= width_) { + notify(DecoderProtocolViolation::OutOfBoundsEventCoordinate); + } + return true; + } + + bool validate_event_cd_vec_impl(const Evt4Raw::EVT4EventCD *ev, [[maybe_unused]] const std::uint32_t *mask) { + if (ev->y >= height_ || static_cast(ev->x + 31) >= width_) { + notify(DecoderProtocolViolation::OutOfBoundsEventCoordinate); + } + return true; + } + + bool validate_time_high_impl(timestamp base_time, timestamp time_high) { + if (time_high < base_time) { + notify(DecoderProtocolViolation::NonMonotonicTimeHigh); + } else if (time_high >= base_time + ThJumpThreshold) { + notify(DecoderProtocolViolation::NonContinuousTimeHigh); + } + return true; + } + + bool validate_ext_trigger_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return true; + } + + bool validate_event_other_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return true; + } + + bool validate_event_continued_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return true; + } +}; + +class RobustValidator : public ValidatorInterface { +protected: + bool ev_drop_{false}; + bool pending_th_jump_{false}; + timestamp pending_base_time{0}; + static constexpr timestamp ThIncrement{64}; + static constexpr timestamp ThJumpThreshold{1'000}; + +public: + RobustValidator(std::uint32_t width, std::uint32_t height) : ValidatorInterface(width, height) {} + + void reset_impl() { + ev_drop_ = false; + pending_th_jump_ = false; + pending_base_time = 0; + } + + bool validate_event_cd_impl(const Evt4Raw::EVT4EventCD *ev) { + if (ev_drop_) { + return false; + } + if (ev->y >= height_ || ev->x >= width_) { + notify(DecoderProtocolViolation::OutOfBoundsEventCoordinate); + return false; + } + return true; + } + + bool validate_event_cd_vec_impl(const Evt4Raw::EVT4EventCD *ev, [[maybe_unused]] const std::uint32_t *mask) { + if (ev_drop_) { + return false; + } else if (ev->y >= height_ || static_cast(ev->x + 31) >= width_) { + notify(DecoderProtocolViolation::OutOfBoundsEventCoordinate); + return false; + } + return true; + } + + bool validate_time_high_impl(timestamp base_time, timestamp time_high) { + // If there's a small return back (rollback) we drop events until we reach a state where we're above the + // last timestamp. When a timehigh t arrives, if there's a jump forward of more than ThJumpThreshold we + // wait to confirm the jump. We wait for a time high that is either t or t + 64 to confirm the jump, or + // if we receive a time high that is equal to base_time or base_time + 64 we reject the jump. + if (pending_th_jump_) { + if ((time_high >= pending_base_time && time_high <= pending_base_time + ThIncrement) || + (time_high >= base_time && time_high <= base_time + ThIncrement)) { + ev_drop_ = false; + pending_th_jump_ = false; + return true; + } else if (time_high >= base_time) { + pending_base_time = time_high; + } + return false; + } else { + if (time_high < base_time) { + ev_drop_ = true; + notify(DecoderProtocolViolation::NonMonotonicTimeHigh); + return false; + } else if (time_high >= base_time + ThJumpThreshold) { + ev_drop_ = true; + pending_base_time = time_high; + pending_th_jump_ = true; + notify(DecoderProtocolViolation::NonContinuousTimeHigh); + return false; + } else { + ev_drop_ = false; + return true; + } + } + } + + bool validate_ext_trigger_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return !ev_drop_; + } + + bool validate_event_other_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return !ev_drop_; + } + + bool validate_event_continued_impl([[maybe_unused]] const Evt4Raw::RawEvent *raw_events) { + return !ev_drop_; + } +}; + +} // namespace evt4 +} // namespace decoder +} // namespace Metavision + +#endif // METAVISION_HAL_EVT4_VALIDATOR_H diff --git a/hal/cpp/include/metavision/hal/device/device_discovery.h b/hal/cpp/include/metavision/hal/device/device_discovery.h index 41caa22bb..bd219c74d 100644 --- a/hal/cpp/include/metavision/hal/device/device_discovery.h +++ b/hal/cpp/include/metavision/hal/device/device_discovery.h @@ -12,6 +12,7 @@ #ifndef METAVISION_HAL_DEVICE_DISCOVERY_H #define METAVISION_HAL_DEVICE_DISCOVERY_H +#include #include #include #include @@ -38,9 +39,6 @@ struct PluginCameraDescription { /// Type of connection used to communicate with the camera ConnectionType connection_; - - /// System Identification number - long system_id_; }; /// @brief Overloads operator == for class PluginCameraDescription @@ -123,13 +121,14 @@ class DeviceDiscovery { /// @brief Builds a new Device from file /// @param raw_file Path to the file to open /// @return A new Device - static std::unique_ptr open_raw_file(const std::string &raw_file); + static std::unique_ptr open_raw_file(const std::filesystem::path &raw_file); /// @brief Builds a new Device from file /// @param raw_file Path to the file to open /// @param file_config Configuration describing how to read the file (see @ref RawFileConfig) /// @return A new Device - static std::unique_ptr open_raw_file(const std::string &raw_file, const RawFileConfig &file_config); + static std::unique_ptr open_raw_file(const std::filesystem::path &raw_file, + const RawFileConfig &file_config); /// @brief Builds a new Device from a standard input stream /// @param stream The input stream to read from. The device takes ownership of the input stream to ensure its diff --git a/hal/cpp/include/metavision/hal/facilities/detail/i_events_stream_decoder_impl.h b/hal/cpp/include/metavision/hal/facilities/detail/i_events_stream_decoder_impl.h index ec20c2faa..a5aea8a2f 100644 --- a/hal/cpp/include/metavision/hal/facilities/detail/i_events_stream_decoder_impl.h +++ b/hal/cpp/include/metavision/hal/facilities/detail/i_events_stream_decoder_impl.h @@ -12,6 +12,12 @@ #ifndef METAVISION_HAL_I_EVENTS_STREAM_DECODER_IMPL_H #define METAVISION_HAL_I_EVENTS_STREAM_DECODER_IMPL_H +#include + +#include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/events/event_cd_vector.h" +#include "metavision/hal/utils/detail/type_check.h" + namespace Metavision { template @@ -60,10 +66,26 @@ void I_EventsStreamDecoder::DecodedEventForwarder::add_event ev_it_ = ev_buf_.begin(); } -inline I_EventsStreamDecoder::DecodedEventForwarder &I_EventsStreamDecoder::cd_event_forwarder() { - return *cd_event_forwarder_; +template +inline I_EventsStreamDecoder::DecodedEventForwarder &I_EventsStreamDecoder::cd_event_forwarder() { + using OutputCDTypes = std::variant; + + static_assert( + detail::is_in_type_list_v, + "Error, cannot construct I_EventsStreamDecoder::DecodedEventForwarder with specified OutputCDType... Supported types are: {EventCD, EventCDVector}." + ); + + if constexpr(std::is_same_v){ + return *cd_event_forwarder_; + } + + if constexpr(std::is_same_v){ + return *cd_event_vector_forwarder_; + } + } + inline I_EventsStreamDecoder::DecodedEventForwarder & I_EventsStreamDecoder::trigger_event_forwarder() { return *trigger_event_forwarder_; diff --git a/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h b/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h index 7e3202e8c..a59d23766 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h +++ b/hal/cpp/include/metavision/hal/facilities/i_event_frame_decoder.h @@ -19,6 +19,7 @@ #include "metavision/hal/facilities/i_decoder.h" #include "metavision/hal/facilities/i_registrable_facility.h" +#include "metavision/hal/utils/data_transfer.h" namespace Metavision { @@ -56,6 +57,12 @@ class I_EventFrameDecoder : public I_RegistrableFacility +#include #include #include #include @@ -22,7 +23,6 @@ #include #include -#include "metavision/hal/facilities/i_camera_synchronization.h" #include "metavision/hal/facilities/i_registrable_facility.h" #include "metavision/hal/utils/data_transfer.h" #include "metavision/sdk/base/utils/timestamp.h" @@ -40,11 +40,11 @@ class I_EventsStream : public I_RegistrableFacility { using RawData = DataTransfer::Data; /// @brief Constructor - /// @param data_transfer Data transfer class owned by the events stream and used to transfer data + /// @param data_producer Raw data producer class owned by the events stream and used to transfer data /// @param hw_identification Hardware identification associated to this events stream /// @param decoder Decoder associated to this events stream /// @param device_control Device control class for starting and stopping - I_EventsStream(std::unique_ptr data_transfer, + I_EventsStream(std::unique_ptr data_producer, const std::shared_ptr &hw_identification, const std::shared_ptr &decoder = nullptr, const std::shared_ptr &device_control = std::shared_ptr()); @@ -72,19 +72,6 @@ class I_EventsStream : public I_RegistrableFacility { /// - -1 if an error occurred or no more events will ever be available (like when reaching end of file) short wait_next_buffer(); - /// @brief Gets latest raw data from the event buffer - /// - /// Gets raw data from the event buffer received since the last time this function was called. - /// - /// @param n_rawbytes Address of a variable in which to put the number of bytes contained in the buffer - /// @return Pointer to an array of Event structures - /// @note This function must be called to write the buffer of events in the log file defined in @ref - /// log_raw_data - [[deprecated("'RawData *I_EventsStream::get_latest_raw_data(long &)' is deprecated since v4.5.0 and will be removed" - " in future releases, please use 'DataTransfer::BufferPtr I_EventsStream::get_latest_raw_data()'" - " instead.")]] - RawData *get_latest_raw_data(long &n_rawbytes); - /// @brief Gets latest raw data from the event buffer /// /// Gets raw data from the event buffer received since the last time this function was called. @@ -111,13 +98,13 @@ class I_EventsStream : public I_RegistrableFacility { /// Does nothing if no recording has been started void stop_log_raw_data(); - /// @brief Sets name of the file read to avoid writing in the same file when calling log_raw_data - /// @param filename Name of the file from which the events are read + /// @brief Sets the path of file read to avoid writing in the same file when calling log_raw_data + /// @param file Path of the file from which the events are read /// @note This function is directly called when opening a RAW file - void set_underlying_filename(const std::string &filename); + void set_underlying_file(const std::filesystem::path &file); - /// @brief Gets name of the file read to avoid writing in the same file when calling log_raw_data - const std::string &get_underlying_filename() const; + /// @brief Gets path of the file read to avoid writing in the same file when calling log_raw_data + const std::filesystem::path &get_underlying_file() const; /// @brief Structure representing a bookmark that composes the index struct Bookmark { @@ -184,6 +171,12 @@ class I_EventsStream : public I_RegistrableFacility { /// @warning The input device must have been built with the same RAW file used to initialize this class void index(std::unique_ptr device_for_indexing); + /// @brief Gets the DataTransfer object used to transfer data from the device to the host + /// @return A reference to the DataTransfer object + const DataTransfer &get_data_transfer() const { + return data_transfer_; + } + private: /// @brief Builds and loads the index in memory virtual Index index_impl(Device &device); @@ -195,13 +188,13 @@ class I_EventsStream : public I_RegistrableFacility { std::shared_ptr hw_identification_; std::shared_ptr decoder_; - // Name of the file read if one - std::string underlying_filename_; + // Path of the file read if one + std::filesystem::path underlying_file_; std::unique_ptr log_raw_data_; std::mutex log_raw_safety_; - std::unique_ptr data_transfer_; + DataTransfer data_transfer_; std::exception_ptr data_transfer_connection_error_; std::shared_ptr device_control_; std::mutex new_buffer_safety_; @@ -213,8 +206,7 @@ class I_EventsStream : public I_RegistrableFacility { // To achieve this, we copy buffers internally in a temporary buffer pool to always leave the data transfer // buffer pool full when resuming streaming const bool stop_should_release_buffers_; - DataTransfer::BufferPool tmp_buffer_pool_; - std::unordered_set + std::unordered_set data_transfer_buffer_ptrs_; // for quick check if copying is necessary std::mutex start_stop_safety_; diff --git a/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h b/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h index 465c72e0a..cf35bdc5d 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h +++ b/hal/cpp/include/metavision/hal/facilities/i_events_stream_decoder.h @@ -18,11 +18,13 @@ #include #include +#include "metavision/hal/utils/data_transfer.h" #include "metavision/sdk/base/utils/timestamp.h" #include "metavision/hal/facilities/i_decoder.h" #include "metavision/hal/facilities/i_event_decoder.h" #include "metavision/hal/facilities/i_registrable_facility.h" #include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/events/event_cd_vector.h" #include "metavision/sdk/base/events/event_erc_counter.h" #include "metavision/sdk/base/events/event_ext_trigger.h" @@ -51,6 +53,20 @@ class I_EventsStreamDecoder : public I_RegistrableFacility> &erc_count_event_decoder = std::shared_ptr>()); + /// @brief Constructor + /// @param time_shifting_enabled If true, the timestamp of the decoded events will be shifted by the value of first + /// event + /// @param event_cd_vector_decoder Optional decoder of CD vector events + /// @param event_ext_trigger_decoder Optional decoder of trigger events + /// @param erc_count_event_decoder Optional decoder of ERC counter events + I_EventsStreamDecoder( + bool time_shifting_enabled, + const std::shared_ptr> &event_cd_vector_decoder = std::shared_ptr>(), + const std::shared_ptr> &event_ext_trigger_decoder = + std::shared_ptr>(), + const std::shared_ptr> &erc_count_event_decoder = + std::shared_ptr>()); + /// @brief Decodes raw data. Identifies the events in the buffer and dispatches it to the instance of @ref /// I_EventDecoder corresponding to each event type. /// @warning It is mandatory to pass strictly consecutive buffers from the same source to this method @@ -58,6 +74,11 @@ class I_EventsStreamDecoder : public I_RegistrableFacility::iterator ev_it_; }; - /// @brief Gets the reference to the forwarder of CD events - DecodedEventForwarder &cd_event_forwarder(); + /// @brief Gets the reference to the forwarder of CD events of OutputCDType + template + DecodedEventForwarder &cd_event_forwarder(); /// @brief Gets the reference to the forwarder of trigger events DecodedEventForwarder &trigger_event_forwarder(); @@ -194,19 +203,7 @@ class I_EventsStreamDecoder : public I_RegistrableFacility= 0, reset the decoder last timestamp to the actual value @p timestamp - /// If < 0, reset the decoder internal state so that the last timestamp will be found from the - /// next buffer of events to decoder (the timestamp shift and overflow loop counter is not reset) - /// @return True if the reset operation could complete, false otherwise. - /// @note It is expected after this call has succeeded, that @ref get_last_timestamp returns @p timestamp - /// @warning If time shifting is enabled, the @p timestamp must be in the shifted time reference - [[deprecated("'I_EventsStream::reset_timestamp_impl' is deprecated since v4.6.0, " - "please use 'I_EventsStream::reset_last_timestamp_impl' instead.")]] - virtual bool reset_timestamp_impl(const Metavision::timestamp ×tamp); + virtual bool reset_last_timestamp_impl(const Metavision::timestamp ×tamp) = 0; /// @brief Implementation of "reset the decoder timestamp shift" operation /// @param shift Timestamp shift to reset the decoder to @@ -222,6 +219,9 @@ class I_EventsStreamDecoder : public I_RegistrableFacility> cd_event_decoder_; std::unique_ptr> cd_event_forwarder_; + + std::shared_ptr> cd_event_vector_decoder_; + std::unique_ptr> cd_event_vector_forwarder_; std::shared_ptr> ext_trigger_event_decoder_; std::unique_ptr> trigger_event_forwarder_; diff --git a/hal/cpp/include/metavision/hal/facilities/i_hw_identification.h b/hal/cpp/include/metavision/hal/facilities/i_hw_identification.h index 7fc5ea588..5b09ddfac 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_hw_identification.h +++ b/hal/cpp/include/metavision/hal/facilities/i_hw_identification.h @@ -68,11 +68,6 @@ class I_HW_Identification : public I_RegistrableFacility { /// @return Serial number as a string virtual std::string get_serial() const = 0; - /// @brief Returns the system id of the camera - /// @return The system id as an integer - /// @note This number can be used to check the compatibility of biases file - virtual long get_system_id() const = 0; - /// @brief Returns the detail about the available sensor /// @return The sensor information virtual SensorInfo get_sensor_info() const = 0; diff --git a/hal/cpp/include/metavision/hal/facilities/i_ll_biases.h b/hal/cpp/include/metavision/hal/facilities/i_ll_biases.h index 57a5bb3bc..a0c8216f8 100644 --- a/hal/cpp/include/metavision/hal/facilities/i_ll_biases.h +++ b/hal/cpp/include/metavision/hal/facilities/i_ll_biases.h @@ -12,6 +12,7 @@ #ifndef METAVISION_HAL_I_LL_BIASES_H #define METAVISION_HAL_I_LL_BIASES_H +#include #include #include #include @@ -52,6 +53,15 @@ class I_LL_Biases : public I_RegistrableFacility { /// @return A map containing the biases values virtual std::map get_all_biases() const = 0; + /// @brief loads biases from a bias file at biases_file_path + /// @throw HalException in case of failure. This could happen for example if given path does not exists. + /// @param src_file bias file to load biases from + void load_from_file(const std::filesystem::path &src_file); + + /// @brief Save the current biases into a file + /// @param dest_file the destination file + void save_to_file(const std::filesystem::path &dest_file) const; + protected: DeviceConfig device_config_; diff --git a/hal/cpp/include/metavision/hal/plugin/detail/plugin_loader.h b/hal/cpp/include/metavision/hal/plugin/detail/plugin_loader.h index 76b2cf616..96403202a 100644 --- a/hal/cpp/include/metavision/hal/plugin/detail/plugin_loader.h +++ b/hal/cpp/include/metavision/hal/plugin/detail/plugin_loader.h @@ -9,6 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include #include @@ -24,8 +25,9 @@ class PluginLoader { ~PluginLoader(); void clear_folders(); - void insert_folder(const std::string &folder); + void insert_folder(const std::filesystem::path &folder); void insert_folders(const std::vector &folders); + void insert_folders(const std::vector &folders); void load_plugins(); void unload_plugins(); @@ -37,10 +39,10 @@ class PluginLoader { struct PluginInfo; struct Library; - void insert_plugin(const std::string &name, const std::string &library_path); + void insert_plugin(const std::string &name, const std::filesystem::path &library_path); void insert_plugin(const PluginInfo &info); - std::vector folders_; + std::vector folders_; std::vector> libraries_; static std::unique_ptr make_plugin(const std::string &plugin_name); diff --git a/hal/cpp/include/metavision/hal/utils/data_transfer.h b/hal/cpp/include/metavision/hal/utils/data_transfer.h index abecd2b0c..d683ff5ca 100644 --- a/hal/cpp/include/metavision/hal/utils/data_transfer.h +++ b/hal/cpp/include/metavision/hal/utils/data_transfer.h @@ -12,12 +12,17 @@ #ifndef METAVISION_HAL_DATA_TRANSFER_H #define METAVISION_HAL_DATA_TRANSFER_H -#include -#include -#include -#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include #include "metavision/sdk/base/utils/object_pool.h" @@ -35,14 +40,127 @@ class DataTransfer { /// Alias for the type of the data transferred using Data = uint8_t; - /// Alias for the type of the internal buffer of data - using Buffer = std::vector; + /// Convenience alias for a default object handling the buffers pool + using DefaultBufferPool = SharedObjectPool>; + + /// Convenience alias to a object type from the default type pool + using DefaultBufferType = DefaultBufferPool::value_type; + + /// Convenience alias for a default object handling the buffers pool + using DefaultBufferPtr = DefaultBufferPool::ptr_type; + + /// @brief Interface for a Raw Event Data producer + /// Derived class are responsible from reading Raw Event buffers from the platform and feed those buffer + /// to the DataTransfer. + /// @note Buffers are obtained via a Buffer Pool object owned by the derived object. So that the derived object can + /// customise the required underlying memory type for the specific platform. + /// @note DefaultBufferPool can be used as a default buffer pool object type. + class RawDataProducer : public std::enable_shared_from_this { + public: + /// @brief Destructor + virtual ~RawDataProducer() = default; + + /// @brief Start transfer implementation. + /// + /// This method is called before running the transfer thread. + /// It can be used as an initialization steps for the implementation. + /// + /// @note When this method is called, should_stop returns false + virtual void start_impl() {} + + /// @brief Data transfer implementation + /// + /// This method must hold the data polling and transfer logic from a source. + /// It is run in a thread within the base class. + /// + /// When a buffer is ready to be transferred, the implementation must call DataTransfer::transfer_data with the + /// buffer + /// + /// @warning The implementation must ensure that whenever should_stop returns true, this method returns and + /// cleans up resources + virtual void run_impl(const DataTransfer &) = 0; + + /// @brief Stop transfer implementation + /// + /// This method is here to notify run_impl that it must stop if a call to should_stop() is not sufficient. + /// + /// @warning Resources should not be clean up in this method as run_impl could still try to use them. It is + /// advised to do so in the scope of the run_impl method to avoid concurrent calls + virtual void stop_impl() {} + }; + + /// Alias for a shared pointer to a RawDataProducer + using RawDataProducerPtr = std::shared_ptr; + + /// @brief Generic Buffer type used by DataTransfer + /// + /// BufferPtr is a type erased wrapper around a buffer from a Buffer Pool. + /// It is used to hold a buffer of data that can be transferred by the DataTransfer down the pipeline without + /// having them to know about the underlying buffer implementation. + class BufferPtr { + public: + /// @brief Default raw data base type + using PtrType = const Data *; + + /// @brief Default constructor + BufferPtr() = default; + + /// @brief Constructor + /// @param buffer The buffer to hold + /// @param data The data pointer of the buffer + /// @param buffer_size The size of the buffer + BufferPtr(std::any buffer, PtrType data, std::size_t buffer_size); + + /// @brief Equality operator + bool operator==(const BufferPtr &other) const; + + /// @brief bool conversion operator + operator bool() const noexcept; + + /// @brief Accessor to the buffer size + std::size_t size() const noexcept; + + /// @brief Accessor to the buffer data + PtrType data() const noexcept; + + /// @brief Iterator semantic to the beginning of the buffer + PtrType begin() const noexcept; - /// Alias for the object handling the buffers pool - using BufferPool = SharedObjectPool; + /// @brief Iterator semantic to the end of the buffer + PtrType end() const noexcept; - /// Alias for the ptr type returned by the buffer pool - using BufferPtr = BufferPool::ptr_type; + /// @brief Iterator semantic to the beginning of a const buffer + const PtrType cbegin() const noexcept; + + /// @brief Iterator semantic to the end of a const buffer + const PtrType cend() const noexcept; + + /// @brief Clone the buffer by reallocating the data and copying the content + BufferPtr clone() const; + + using CloneType = std::vector; + using SharedCloneType = std::shared_ptr; + + /// @brief Cast back internally stored buffer to its specific type + /// Should throw if the type isn't of a cloned one + SharedCloneType any_clone_cast() const; + + /// @brief Reset the buffer + void reset() noexcept; + + private: + std::any internal_buffer_; + PtrType buffer_data_ = nullptr; + std::size_t buffer_size_ = 0; + }; + + /// @brief Convenience function to create a BufferPtr from a buffer that originates a Buffer Pool + /// @param buffer_ptr The buffer to create a BufferPtr from + /// @return A BufferPtr holding the buffer + template + static BufferPtr make_buffer_ptr(const T &buffer_ptr) { + return {buffer_ptr, reinterpret_cast(buffer_ptr->data()), buffer_ptr->size()}; + } /// Alias for a callback called when the data transfer starts or stops transferring data enum class Status { Started = 0, Stopped = 1 }; @@ -55,20 +173,13 @@ class DataTransfer { using TransferErrorCallback_t = std::function; /// @brief Builds a DataTransfer object - /// @param raw_event_size_bytes The size of a RAW event in bytes - DataTransfer(uint32_t raw_event_size_bytes); - - /// @brief Builds a DataTransfer object - /// @param raw_event_size_bytes The size of a RAW event in bytes - /// @param buffer_pool A user defined buffer pool to use instead of the default one (unbounded, @ref ObjectPool) - /// @param allow_buffer_drop When transferring data buffers using an empty bounded buffer pool, buffers are dropped - /// (@ref transfer_data) - DataTransfer(uint32_t raw_event_size_bytes, const BufferPool &buffer_pool, bool allow_buffer_drop = false); + /// @param data_producer_ptr A Pointer to a data producer that will provide raw event data + explicit DataTransfer(RawDataProducerPtr data_producer_ptr); /// @brief Destructor /// /// Stops all transfers and wait for all thread to join - virtual ~DataTransfer(); + ~DataTransfer(); /// @brief Starts the transfers void start(); @@ -114,103 +225,27 @@ class DataTransfer { /// @brief Removes the callback with input id /// @param cb_id The id of the callback to remove - /// @note This method is not thread safe. You should add/remove the various callback before starting the transfers + /// @note This method is not thread safe. You should add/remove the various callback before starting the + /// transfers void remove_callback(size_t cb_id); - /// @brief Returns whether a buffer can be used from the pool. - /// @note Always return true for a unbounded pool, as it could allocate a new object on the spot if the pool is - /// empty - bool has_available_buffer() const { - if (buffer_pool_.is_bounded()) { - return buffer_pool_.size() > 0; - } - return true; - } - -protected: - /// @brief Returns the size of a RAW event in bytes - /// - /// This is to help ensuring the integrity of the transferred buffer - uint32_t get_raw_event_size_bytes() const; - - /// @brief The implementation must call this method whenever a buffer of data is ready to be transferred - /// - /// @warning The transferred buffer must hold coherent and continuous data. - /// @warning The buffer size may not be a multiple of a RAW event byte size if the last event is split, in which - /// case, the next buffer must contain the remaining bytes of the split event. - /// @warning The implementation must resize the buffer to the actual size of the transferred data - /// @note When bounded pool is used and no buffer is available from the pool, the current buffer is dropped to be - /// reused. - /// @param buffer The buffer filled with RAW data to transfer. - /// @param args Optional arguments to be used when allocating a buffer - /// @return A std::pair with first the next buffer from the pool and second a boolean defining if the input - /// buffer as been dropped - template - std::pair transfer_data(BufferPtr &buffer, Args &&...args) { - bool is_buffer_dropped = false; - if (allow_buffer_drop_ && !has_available_buffer()) { - // No storage left and we don't want to wait on a buffer to be freed. - // We drop the buffer, back to the pool ! - buffer.reset(); - is_buffer_dropped = true; - } else { - fire_callbacks(buffer); - } - - auto new_buffer = get_buffer(std::forward(args)...); - return std::make_pair(new_buffer, is_buffer_dropped); - } + /// @brief Returns the data producer used by the transfer + RawDataProducerPtr get_data_producer() const { + return data_producer_ptr_; + }; - /// @brief Requests a new buffer from the pool - /// @param args Optional arguments to be used when allocating a buffer - /// @return A buffer taken from the object pool - template - DataTransfer::BufferPtr get_buffer(Args &&...args) { - return buffer_pool_.acquire(std::forward(args)...); + /// @brief Convenience function to transfer a buffer of data coming from an object pool by wrapping if to a + /// BufferPtr + template + void transfer_data(const T &buffer) const { + fire_callbacks(make_buffer_ptr(buffer)); } /// @brief Returns whether the transfer must stop as requested by the base class implementation /// /// This method can be called safely by the child implementation to know whether the implementation of the run /// should return - bool should_stop(); - -protected: - /// @brief Returns a reference on the underlying buffer pool - /// @return the underlying buffer pool - BufferPool &get_buffer_pool() { - return buffer_pool_; - } - -private: - /// @brief Start transfer implementation. - /// - /// This method is called before running the transfer thread. - /// It can be used as an initialization steps for the implementation. - /// It also provides a data buffer taken from the object pool to be used for the transfers. - /// - /// @note Additional buffers can be obtained by calling @ref get_buffer if multiple transfers are happening at the - /// same time - /// @note When this method is called, should_stop returns false - /// @param buffer A data buffer taken from the pool - virtual void start_impl(BufferPtr buffer); - - /// @brief Data transfer implementation - /// - /// This method must hold the data polling and transfer logic from a source. - /// It is run in a thread within the base class. - /// - /// @warning The implementation must ensure that whenever should_stop returns true, this method returns and cleans - /// up resources - virtual void run_impl() = 0; - - /// @brief Stop transfer implementation - /// - /// This method is here to notify run_impl that it must stop if a call to should_stop() is not sufficient. - /// - /// @warning Resources should not be clean up in this method as run_impl could still try to use them. It is advised - /// to do so in the scope of the run_impl method to avoid concurrent calls - virtual void stop_impl(); + bool should_stop() const; /// @brief Notify the internal thread that it shall stop /// @@ -218,18 +253,22 @@ class DataTransfer { void notify_stop(); /// @brief Trigger all registered callbacks + /// @warning The transferred buffer must hold coherent and continuous data. + /// @warning The buffer size may not be a multiple of a RAW event byte size if the last event is split, in which + /// case, the next buffer must contain the remaining bytes of the split event. + /// @warning The implementation must resize the buffer to the actual size of the transferred data /// @param buffer The data to be carried forward - void fire_callbacks(const BufferPtr buffer) const; + void fire_callbacks(const BufferPtr &buffer) const; +private: std::thread run_transfers_thread_; - BufferPool buffer_pool_; + RawDataProducerPtr data_producer_ptr_; + std::unordered_map status_change_cbs_; std::unordered_map new_buffer_cbs_; std::unordered_map transfer_error_cbs_; - const uint32_t raw_event_size_bytes_; std::atomic stop_{false}; uint32_t cb_index_{0}; - const bool allow_buffer_drop_{false}; std::mutex suspend_mutex_, running_mutex_; std::condition_variable suspend_cond_, running_cond_; @@ -238,4 +277,11 @@ class DataTransfer { } // namespace Metavision +template<> +struct std::hash { + std::size_t operator()(const Metavision::DataTransfer::BufferPtr &buffer) const { + return std::hash{}(buffer.data()); + } +}; + #endif // METAVISION_HAL_DATA_TRANSFER_H diff --git a/hal/cpp/include/metavision/hal/utils/decoder_protocol_violation.h b/hal/cpp/include/metavision/hal/utils/decoder_protocol_violation.h index 70f252eb9..1640fac34 100644 --- a/hal/cpp/include/metavision/hal/utils/decoder_protocol_violation.h +++ b/hal/cpp/include/metavision/hal/utils/decoder_protocol_violation.h @@ -27,6 +27,7 @@ enum DecoderProtocolViolation : HalErrorCodeType { NonContinuousTimeHigh, MissingYAddr, InvalidVectBase, + OutOfBoundsEventCoordinate, }; inline std::ostream &operator<<(std::ostream &o, const DecoderProtocolViolation protocol_violation) { @@ -38,7 +39,7 @@ inline std::ostream &operator<<(std::ostream &o, const DecoderProtocolViolation {DecoderProtocolViolation::NonContinuousTimeHigh, "NonContinuousTimeHigh"}, {DecoderProtocolViolation::MissingYAddr, "MissingYAddr"}, {DecoderProtocolViolation::InvalidVectBase, "InvalidVectBase"}, - + {DecoderProtocolViolation::OutOfBoundsEventCoordinate, "OutOfBoundsEventCoordinate"}, }; o << protocol_violation_to_str.at(protocol_violation); diff --git a/sdk/modules/core/cpp/samples/metavision_player/inc/params.h b/hal/cpp/include/metavision/hal/utils/detail/type_check.h similarity index 67% rename from sdk/modules/core/cpp/samples/metavision_player/inc/params.h rename to hal/cpp/include/metavision/hal/utils/detail/type_check.h index 79cb9518d..fef0291ed 100644 --- a/sdk/modules/core/cpp/samples/metavision_player/inc/params.h +++ b/hal/cpp/include/metavision/hal/utils/detail/type_check.h @@ -9,27 +9,20 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_PLAYER_PARAMS_H -#define METAVISION_PLAYER_PARAMS_H +#ifndef METAVISION_HAL_DETAIL_TYPE_CHECK_H +#define METAVISION_HAL_DETAIL_TYPE_CHECK_H -/// Structure to hold command line interface parameters. -struct Parameters { - // Input. - std::string in_bias_file; - std::string event_file_path; +#include - // Parameters for the exported files. - std::string out_bias_file; - std::string out_png_file; - std::string out_avi_file; - std::string out_raw_basename; - int out_avi_fps = 25; +namespace Metavision{ +namespace detail{ - // Buffer size in mega events. - int buffer_size_mev = 100; +template class C, typename ... Ts> +constexpr auto is_in_type_list (C const &) -> std::disjunction...>; - // Show bias sliders - bool show_biases = false; -}; +template +static constexpr bool is_in_type_list_v = decltype(is_in_type_list(std::declval()))::value; -#endif // #define METAVISION_PLAYER_PARAMS_H +}} + +#endif //METAVISION_HAL_DETAIL_TYPE_CHECK_H \ No newline at end of file diff --git a/hal/cpp/include/metavision/hal/utils/detail/warning_supression.h b/hal/cpp/include/metavision/hal/utils/detail/warning_supression.h index 44dc8ff06..1b7b85982 100644 --- a/hal/cpp/include/metavision/hal/utils/detail/warning_supression.h +++ b/hal/cpp/include/metavision/hal/utils/detail/warning_supression.h @@ -1,5 +1,16 @@ -#ifndef WARNING_SUPRESSION_HPP -#define WARNING_SUPRESSION_HPP +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_DETAIL_WARNING_SUPRESSION_H +#define METAVISION_HAL_DETAIL_WARNING_SUPRESSION_H #if defined(__GNUC__) @@ -26,4 +37,4 @@ #endif -#endif // WARNING_SUPRESSION_HPP \ No newline at end of file +#endif // METAVISION_HAL_DETAIL_WARNING_SUPRESSION_H \ No newline at end of file diff --git a/hal/cpp/include/metavision/hal/utils/device_config.h b/hal/cpp/include/metavision/hal/utils/device_config.h index ff9650267..6650c7bdc 100644 --- a/hal/cpp/include/metavision/hal/utils/device_config.h +++ b/hal/cpp/include/metavision/hal/utils/device_config.h @@ -154,14 +154,6 @@ class DeviceConfig { /// @overload std::string get(const std::string &key, const std::string &def = std::string()) const; - [[deprecated( - "This function is deprecated since version 4.1.0. Please use get_format_key() instead.")]] static std::string - get_evt_format_key(); - [[deprecated("This function is deprecated since version 4.1.0. Please use format() instead.")]] std::string - evt_format() const; - [[deprecated("This function is deprecated since version 4.1.0. Please use set_format() instead.")]] void - set_evt_format(const std::string &); - private: // private get helper, to avoid template specialization errors on GCC template::value>::type> diff --git a/hal/cpp/include/metavision/hal/utils/file_data_transfer.h b/hal/cpp/include/metavision/hal/utils/file_raw_data_producer.h similarity index 72% rename from hal/cpp/include/metavision/hal/utils/file_data_transfer.h rename to hal/cpp/include/metavision/hal/utils/file_raw_data_producer.h index 64aacaf00..fcb1b7528 100644 --- a/hal/cpp/include/metavision/hal/utils/file_data_transfer.h +++ b/hal/cpp/include/metavision/hal/utils/file_raw_data_producer.h @@ -9,10 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_HAL_FILE_DATA_TRANSFER_H -#define METAVISION_HAL_FILE_DATA_TRANSFER_H +#ifndef METAVISION_HAL_RAW_DATA_PRODUCER_H +#define METAVISION_HAL_RAW_DATA_PRODUCER_H -#include +#include #include #include #include @@ -23,16 +23,16 @@ namespace Metavision { /// @brief Standard stream reader -class FileDataTransfer : public DataTransfer { +class FileRawDataProducer : public DataTransfer::RawDataProducer { public: /// @brief Reads the input standard @a stream batch by batch according to the input configuration /// @param stream The stream to read from /// @param raw_event_size_bytes The size of a RAW event in bytes /// @param config The configuration to use to read the stream - FileDataTransfer(std::unique_ptr stream, uint32_t raw_event_size_bytes, const RawFileConfig &config); - - /// @brief Stops ongoing transfers - ~FileDataTransfer(); + /// @param buffer_pool The bufferpool to be used to allocate memory for the data transfer + FileRawDataProducer(std::unique_ptr stream, uint32_t raw_event_size_bytes, + const RawFileConfig &config, + DataTransfer::DefaultBufferPool buffer_pool = DataTransfer::DefaultBufferPool::make_bounded(4)); /// @brief Seeks the target position in the file /// @param target_position The target position of the cursor to seek in the file @@ -44,13 +44,14 @@ class FileDataTransfer : public DataTransfer { void get_seek_range(std::streampos &data_start_pos, std::streampos &data_end_pos) const; private: - void start_impl(BufferPtr buffer) override final; - void run_impl() override final; + void start_impl() override final; + void run_impl(const DataTransfer &data_transfer) override final; virtual bool seek_impl(const std::streampos &target_position); - /// Buffer - BufferPtr data_read_; + /// Transfer Buffer pool + DataTransfer::DefaultBufferPool buffer_pool_; + using DefaultBufferPtr = DataTransfer::DefaultBufferPool::ptr_type; /// Bytes batch size to read from stream at each read iteration uint32_t read_bytes_size_{0}; @@ -58,8 +59,8 @@ class FileDataTransfer : public DataTransfer { std::mutex seek_mutex_; std::condition_variable seek_cond_; std::atomic seeking_; - BufferPtr seek_buffer_; // extra slack buffer we can use to unblock any pending acquire from the transfer buffer - // pool before doing a seek + DefaultBufferPtr seek_buffer_; // extra slack buffer we can use to unblock any pending acquire from the transfer + // buffer pool before doing a seek std::mutex stream_mutex_; std::condition_variable stream_cond_; @@ -68,4 +69,4 @@ class FileDataTransfer : public DataTransfer { }; } // namespace Metavision -#endif // METAVISION_HAL_FILE_DATA_TRANSFER_H +#endif // METAVISION_HAL_FILE_RAW_DATA_PRODUCER_H diff --git a/hal/cpp/include/metavision/hal/utils/resources_folder.h b/hal/cpp/include/metavision/hal/utils/resources_folder.h index 178660ad3..5ec6d144e 100644 --- a/hal/cpp/include/metavision/hal/utils/resources_folder.h +++ b/hal/cpp/include/metavision/hal/utils/resources_folder.h @@ -13,7 +13,6 @@ #define METAVISION_HAL_RESOURCES_FOLDER_H #include -#include namespace Metavision { @@ -28,11 +27,11 @@ class ResourcesFolder { /// @brief Returns installation path of support directories (like firmwares) /// @return Installation path of support directories - static std::string get_install_path(); + static std::filesystem::path get_install_path(); /// @brief Returns the plugins' installation path /// @return Plugins' installation path - static std::string get_plugin_install_path(); + static std::filesystem::path get_plugin_install_path(); }; } // namespace Metavision diff --git a/hal/cpp/metavision_hal_install_path.h.in b/hal/cpp/metavision_hal_install_path.h.in index bb082981f..f7d60de53 100644 --- a/hal/cpp/metavision_hal_install_path.h.in +++ b/hal/cpp/metavision_hal_install_path.h.in @@ -12,7 +12,7 @@ #ifndef METAVISION_HAL_INSTALL_PATH_H #define METAVISION_HAL_INSTALL_PATH_H -#include +#include #ifdef _WIN32 #include @@ -22,8 +22,8 @@ namespace Metavision { -static const std::string HAL_INSTALL_SUPPORT_RELATIVE_PATH = "@HAL_INSTALL_SUPPORT_RELATIVE_PATH@"; -static const std::string HAL_INSTALL_PLUGIN_RELATIVE_PATH = "@HAL_INSTALL_PLUGIN_RELATIVE_PATH@"; +static const std::filesystem::path HAL_INSTALL_SUPPORT_RELATIVE_PATH = "@HAL_INSTALL_SUPPORT_RELATIVE_PATH@"; +static const std::filesystem::path HAL_INSTALL_PLUGIN_RELATIVE_PATH = "@HAL_INSTALL_PLUGIN_RELATIVE_PATH@"; #ifdef _WIN32 static const LPCSTR METAVISION_SUBKEY = "@METAVISION_SUBKEY@"; static const LPCSTR METAVISION_SUBKEY_INSTALL_PATH = "@METAVISION_SUBKEY_INSTALL_PATH@"; @@ -31,7 +31,7 @@ static const LPCSTR METAVISION_SUBKEY_INSTALL_PATH = "@METAVISION_SUBKEY_INSTALL static const std::string METAVISION_HAL_LIB_RELATIVE_PATH = "lib/$"; -inline std::vector get_root_installation_path_candidates() { +inline std::vector get_root_installation_path_candidates() { return {"@CMAKE_INSTALL_PREFIX@", "/usr"}; } diff --git a/hal/cpp/samples/metavision_hal_raw_cutter/metavision_hal_raw_cutter.cpp b/hal/cpp/samples/metavision_hal_raw_cutter/metavision_hal_raw_cutter.cpp index ddf91698c..8b7ec8583 100644 --- a/hal/cpp/samples/metavision_hal_raw_cutter/metavision_hal_raw_cutter.cpp +++ b/hal/cpp/samples/metavision_hal_raw_cutter/metavision_hal_raw_cutter.cpp @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) { auto ev_buffer = i_eventsstream->get_latest_raw_data(); // Decode the raw buffer - i_eventsstreamdecoder->decode(ev_buffer->data(), ev_buffer->data() + ev_buffer->size()); + i_eventsstreamdecoder->decode(ev_buffer); // Update last timestamp last_ts = i_eventsstreamdecoder->get_last_timestamp(); diff --git a/hal/cpp/samples/metavision_hal_raw_cutter/test/metavision_hal_raw_cutter_pytest.py b/hal/cpp/samples/metavision_hal_raw_cutter/test/metavision_hal_raw_cutter_pytest.py index 4bdad6217..65bfa408a 100644 --- a/hal/cpp/samples/metavision_hal_raw_cutter/test/metavision_hal_raw_cutter_pytest.py +++ b/hal/cpp/samples/metavision_hal_raw_cutter/test/metavision_hal_raw_cutter_pytest.py @@ -186,7 +186,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen31_recording_from_0s_to_6s(d Plugin name hal_plugin_gen31_fx3 Data encoding EVT2 Camera generation 3.1 -Camera systemID \d* Camera serial 00001621 ==================================================================================================== @@ -219,7 +218,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen31_recording_from_8s_to_11s( Plugin name hal_plugin_gen31_fx3 Data encoding EVT2 Camera generation 3.1 -Camera systemID \d* Camera serial 00001621 ==================================================================================================== @@ -252,8 +250,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen4_evt2_recording_full_cut(da Plugin name hal_plugin_gen41_evk3 Data encoding EVT2 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -286,8 +282,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen4_evt2_recording_from_2s_to_ Plugin name hal_plugin_gen41_evk3 Data encoding EVT2 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -320,8 +314,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen4_evt2_recording_from_4s_to_ Plugin name hal_plugin_gen41_evk3 Data encoding EVT2 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -354,8 +346,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen4_evt3_recording_full_cut(da Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -388,8 +378,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen4_evt3_recording_from_3s_to_ Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -422,8 +410,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen4_evt3_recording_from_8s_to_ Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -456,8 +442,6 @@ def pytestcase_test_metavision_hal_raw_cutter_on_gen4_evt3_recording_from_4s_to_ Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_data_transfer.h b/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_data_transfer.h index b7a969e7d..bedbb0fe9 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_data_transfer.h +++ b/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_data_transfer.h @@ -20,7 +20,7 @@ /// @brief Class for getting buffers from cameras or files. /// /// This class is the implementation of HAL's facility @ref Metavision::DataTransfer -class SampleDataTransfer : public Metavision::DataTransfer { +class SampleDataTransfer : public Metavision::DataTransfer::RawDataProducer { public: /// @brief Constructor /// @@ -31,11 +31,11 @@ class SampleDataTransfer : public Metavision::DataTransfer { ~SampleDataTransfer() override; private: - void start_impl(BufferPtr buffer) override final; - void run_impl() override final; + void start_impl() override final; + void run_impl(const Metavision::DataTransfer &) override final; + Metavision::DataTransfer::DefaultBufferPool buffer_pool_; Metavision::timestamp current_time_; - BufferPtr buffer_; struct PatternGenerator; std::unique_ptr gen_; diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_hw_identification.h b/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_hw_identification.h index 2e56e852b..2a6d1c0e0 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_hw_identification.h +++ b/hal/cpp/samples/metavision_hal_sample_plugin/include/sample_hw_identification.h @@ -31,11 +31,6 @@ class SampleHWIdentification : public Metavision::I_HW_Identification { /// @return Serial number as a string std::string get_serial() const override final; - /// @brief Returns the system ID of the camera - /// - /// @return The system id as an integer - long get_system_id() const override final; - /// @brief Returns the detail about the available sensor /// /// @return The sensor information @@ -66,7 +61,6 @@ class SampleHWIdentification : public Metavision::I_HW_Identification { Metavision::DeviceConfigOptionMap get_device_config_options_impl() const override final; static constexpr auto SAMPLE_SERIAL = "000000"; - static constexpr long SAMPLE_SYSTEM_ID = 42; static constexpr auto SAMPLE_INTEGRATOR = "SampleIntegratorName"; static constexpr auto SAMPLE_FORMAT = "SAMPLE-FORMAT-1.0"; diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_camera_discovery.cpp b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_camera_discovery.cpp index dbcd3ec11..7073805d4 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_camera_discovery.cpp +++ b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_camera_discovery.cpp @@ -35,7 +35,6 @@ Metavision::CameraDiscovery::SystemList SampleCameraDiscovery::list_available_so Metavision::PluginCameraDescription description; description.serial_ = SampleHWIdentification::SAMPLE_SERIAL; - description.system_id_ = SampleHWIdentification::SAMPLE_SYSTEM_ID; description.connection_ = Metavision::USB_LINK; systems.push_back(description); diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_data_transfer.cpp b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_data_transfer.cpp index 75e673633..1b739c5bd 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_data_transfer.cpp +++ b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_data_transfer.cpp @@ -13,21 +13,23 @@ #include "sample_data_transfer.h" #include "internal/sample_data_transfer_pattern_generator.h" +#include "metavision/hal/utils/data_transfer.h" +#include "metavision/hal/utils/device_config.h" constexpr short SampleDataTransfer::PatternGenerator::SIZE_SQUARE; constexpr short SampleDataTransfer::PatternGenerator::N_RANDOM; constexpr Metavision::timestamp SampleDataTransfer::PatternGenerator::STEP_RANDOM; SampleDataTransfer::SampleDataTransfer(uint32_t raw_event_size_bytes) : - DataTransfer(raw_event_size_bytes), current_time_(0), gen_(new SampleDataTransfer::PatternGenerator()) {} + buffer_pool_(Metavision::DataTransfer::DefaultBufferPool::make_unbounded(raw_event_size_bytes)), + current_time_(0), + gen_(new SampleDataTransfer::PatternGenerator()) {} SampleDataTransfer::~SampleDataTransfer() = default; -void SampleDataTransfer::start_impl(BufferPtr buffer) { - buffer_ = buffer; -} +void SampleDataTransfer::start_impl() {} -void SampleDataTransfer::run_impl() { +void SampleDataTransfer::run_impl(const Metavision::DataTransfer &data_transfer) { // This is the method that you'll need to implement when writing your own plugin. // In this sample we just generate some fake events, but you'll have to replace // the following code with your implementation (for example, getting data from @@ -38,16 +40,17 @@ void SampleDataTransfer::run_impl() { // events, and sleep for the necessary time Metavision::timestamp time_start = current_time_; uint64_t first_ts_clock_ = Metavision::get_system_time_us(); - while (!should_stop()) { + while (!data_transfer.should_stop()) { // Fill fake_events - buffer_->resize(SIZE_FAKE_EVENTS); - for (auto it = buffer_->begin(); it < buffer_->end(); it += sizeof(SampleEventsFormat)) { + + auto buffer = buffer_pool_.acquire(SIZE_FAKE_EVENTS); + for (auto it = buffer->begin(); it < buffer->end(); it += sizeof(SampleEventsFormat)) { (*gen_)(reinterpret_cast(*it), current_time_); } // Makes the buffer available to the events stream - auto next_buffer = transfer_data(buffer_); - buffer_ = next_buffer.first; + data_transfer.transfer_data(buffer); + uint64_t cur_ts_clock = Metavision::get_system_time_us(); uint64_t expected_ts = first_ts_clock_ + (current_time_ - time_start); if (expected_ts > cur_ts_clock) { diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_file_discovery.cpp b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_file_discovery.cpp index 34c7de365..863c50ff9 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_file_discovery.cpp +++ b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_file_discovery.cpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include "sample_file_discovery.h" #include "sample_hw_identification.h" @@ -45,8 +45,8 @@ bool SampleFileDiscovery::discover(Metavision::DeviceBuilder &device_builder, st // Note that the current facility must take ownership of the stream instance (as it was the case in previous // versions). device_builder.add_facility(std::make_unique( - std::make_unique(std::move(stream), decoder->get_raw_event_size_bytes(), - stream_config), + std::make_unique(std::move(stream), decoder->get_raw_event_size_bytes(), + stream_config), hw_identification, decoder)); return true; diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_hw_identification.cpp b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_hw_identification.cpp index 7a9a48b36..6e774b2a0 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_hw_identification.cpp +++ b/hal/cpp/samples/metavision_hal_sample_plugin/src/sample_hw_identification.cpp @@ -15,7 +15,6 @@ #include "sample_hw_identification.h" constexpr const char *const SampleHWIdentification::SAMPLE_SERIAL; -constexpr long SampleHWIdentification::SAMPLE_SYSTEM_ID; constexpr const char *const SampleHWIdentification::SAMPLE_INTEGRATOR; constexpr const char *const SampleHWIdentification::SAMPLE_FORMAT; @@ -26,9 +25,6 @@ SampleHWIdentification::SampleHWIdentification(const std::shared_ptrget_facility(); ASSERT_NE(nullptr, i_hw_identification); ASSERT_EQ(SampleHWIdentification::SAMPLE_SERIAL, i_hw_identification->get_serial()); - ASSERT_EQ(SampleHWIdentification::SAMPLE_SYSTEM_ID, i_hw_identification->get_system_id()); ASSERT_EQ("Gen1.0", i_hw_identification->get_sensor_info().name_); std::vector available_formats = i_hw_identification->get_available_data_encoding_formats(); ASSERT_EQ(1, available_formats.size()); @@ -140,9 +137,8 @@ TEST_F(HalSamplePlugin_GTest, record_and_read_back) { short ret = i_events_stream->wait_next_buffer(); ASSERT_LE(0, ret); - long n_bytes; auto raw_data = i_events_stream->get_latest_raw_data(); - i_eventsstreamdecoder->decode(raw_data->data(), raw_data->data() + raw_data->size()); + i_eventsstreamdecoder->decode(raw_data); } Metavision::timestamp last_time = i_eventsstreamdecoder->get_last_timestamp(); @@ -169,7 +165,7 @@ TEST_F(HalSamplePlugin_GTest, record_and_read_back) { short ret = i_events_stream->wait_next_buffer(); while (ret > 0) { // To be sure to record something auto raw_data = i_events_stream->get_latest_raw_data(); - i_eventsstreamdecoder->decode(raw_data->data(), raw_data->data() + raw_data->size()); + i_eventsstreamdecoder->decode(raw_data); ret = i_events_stream->wait_next_buffer(); } ASSERT_EQ(number_cd_expected, n_cd_events_decoded); diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_file_info_with_sample_plugin_pytest.py b/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_file_info_with_sample_plugin_pytest.py index c09dfd046..1d1fb230d 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_file_info_with_sample_plugin_pytest.py +++ b/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_file_info_with_sample_plugin_pytest.py @@ -42,7 +42,6 @@ def pytestcase_test_metavision_file_info_with_sample_plugin(dataset_dir): Plugin name hal_sample_plugin Data encoding SAMPLE-FORMAT-1.0 Camera generation 1.0 -Camera systemID \d* Camera serial 000000 ==================================================================================================== diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_hal_raw_cutter_with_sample_plugin_pytest.py b/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_hal_raw_cutter_with_sample_plugin_pytest.py index fa7fb6747..b1dffe850 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_hal_raw_cutter_with_sample_plugin_pytest.py +++ b/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_hal_raw_cutter_with_sample_plugin_pytest.py @@ -77,7 +77,6 @@ def pytestcase_test_metavision_hal_raw_cutter_with_sample_plugin_full_cut(datase Plugin name hal_sample_plugin Data encoding SAMPLE-FORMAT-1.0 Camera generation 1.0 -Camera systemID 42 Camera serial 000000 ==================================================================================================== @@ -108,7 +107,6 @@ def pytestcase_test_metavision_hal_raw_cutter_with_sample_plugin_cut_from_0s_to_ Plugin name hal_sample_plugin Data encoding SAMPLE-FORMAT-1.0 Camera generation 1.0 -Camera systemID 42 Camera serial 000000 ==================================================================================================== @@ -139,7 +137,6 @@ def pytestcase_test_metavision_hal_raw_cutter_with_sample_plugin_cut_from_2s_to_ Plugin name hal_sample_plugin Data encoding SAMPLE-FORMAT-1.0 Camera generation 1.0 -Camera systemID 42 Camera serial 000000 ==================================================================================================== diff --git a/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_platform_info_with_sample_plugin_pytest.py b/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_platform_info_with_sample_plugin_pytest.py index 3fe27def8..a08e2a092 100644 --- a/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_platform_info_with_sample_plugin_pytest.py +++ b/hal/cpp/samples/metavision_hal_sample_plugin/test/metavision_platform_info_with_sample_plugin_pytest.py @@ -34,7 +34,6 @@ def pytestcase_test_metavision_platform_info_with_sample_plugin_system(): Integrator SampleIntegratorName Sensor Name Gen1.0 Serial 000000 -SystemID 42 # Available device config options """ diff --git a/hal/cpp/samples/metavision_hal_seek/metavision_hal_seek.cpp b/hal/cpp/samples/metavision_hal_seek/metavision_hal_seek.cpp index ee54c3df7..2fe811528 100644 --- a/hal/cpp/samples/metavision_hal_seek/metavision_hal_seek.cpp +++ b/hal/cpp/samples/metavision_hal_seek/metavision_hal_seek.cpp @@ -9,7 +9,6 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include #include #include #include @@ -167,7 +166,7 @@ int main(int argc, char **argv) { i_eventsstreamdecoder->reset_last_timestamp(ts_reached); while (i_eventsstream->wait_next_buffer() > 0) { auto buffer = i_eventsstream->get_latest_raw_data(); - i_eventsstreamdecoder->decode(buffer->data(), buffer->data() + buffer->size()); + i_eventsstreamdecoder->decode(buffer); if (i_eventsstreamdecoder->get_last_timestamp() > seek_ts + accumulation_time) { break; } diff --git a/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp b/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp index 270bf081a..31e9cb960 100644 --- a/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp +++ b/hal/cpp/samples/metavision_hal_showcase/metavision_hal_showcase.cpp @@ -90,7 +90,6 @@ int main(int argc, char *argv[]) { std::string plugin_name; std::string pixel_mask_coord; std::string crop_region_coord; - long system_id = -1; std::string temperature, illumination, pixel_dead_time; @@ -135,9 +134,7 @@ int main(int argc, char *argv[]) { } else { device = Metavision::DeviceDiscovery::open_raw_file(in_raw_file_path); } - } catch (Metavision::BaseException &e) { - std::cerr << "Error exception: " << e.what() << std::endl; - } + } catch (Metavision::BaseException &e) { std::cerr << "Error exception: " << e.what() << std::endl; } if (!device) { std::cerr << "Camera opening failed." << std::endl; @@ -153,8 +150,7 @@ int main(int argc, char *argv[]) { Metavision::I_HW_Identification *i_hw_identification = device->get_facility(); if (i_hw_identification) { - system_id = i_hw_identification->get_system_id(); - std::cout << "System ID: " << system_id << std::endl; + std::cout << "Camera serial: " << i_hw_identification->get_serial() << std::endl; } Metavision::I_CameraSynchronization *i_camera_synchronization = @@ -231,8 +227,7 @@ int main(int argc, char *argv[]) { i_triggerdecoder->add_event_buffer_callback( [](const Metavision::EventExtTrigger *begin, const Metavision::EventExtTrigger *end) { for (auto ev = begin; ev != end; ++ev) { - std::cout << "Trigger " - << " " << ev->t << " " << ev->id << " " << ev->p << std::endl; + std::cout << "Trigger " << " " << ev->t << " " << ev->id << " " << ev->p << std::endl; } }); } else { @@ -366,7 +361,7 @@ int main(int argc, char *argv[]) { // This will trigger callbacks set on decoders: in our case EventAnalyzer.process_events if (raw_data) { - i_eventsstreamdecoder->decode(raw_data->data(), raw_data->data() + raw_data->size()); + i_eventsstreamdecoder->decode(raw_data); } /// [buffer] } diff --git a/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp b/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp index a8f1c982e..61845651d 100644 --- a/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp +++ b/hal/cpp/samples/metavision_hal_sync/metavision_hal_sync.cpp @@ -140,9 +140,7 @@ int main(int argc, char *argv[]) { std::unique_ptr device; try { device = Metavision::DeviceDiscovery::open(serial); - } catch (Metavision::BaseException &e) { - std::cerr << "Error exception: " << e.what() << std::endl; - } + } catch (Metavision::BaseException &e) { std::cerr << "Error exception: " << e.what() << std::endl; } if (!device) { std::cerr << "Camera opening failed." << std::endl; @@ -223,7 +221,7 @@ int main(int argc, char *argv[]) { // This will trigger callbacks set on decoders: in our case EventAnalyzer.process_events if (raw_data) { - i_decoder->decode(raw_data->data(), raw_data->data() + raw_data->size()); + i_decoder->decode(raw_data.begin(), raw_data.data() + raw_data.size()); } } }); diff --git a/hal/cpp/samples/metavision_platform_info/CMakeLists.txt b/hal/cpp/samples/metavision_platform_info/CMakeLists.txt index d774f3b5d..cf568afd9 100644 --- a/hal/cpp/samples/metavision_platform_info/CMakeLists.txt +++ b/hal/cpp/samples/metavision_platform_info/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. add_executable(metavision_platform_info metavision_platform_info.cpp) -target_link_libraries(metavision_platform_info PRIVATE MetavisionSDK::base metavision_hal metavision_hal_discovery Boost::program_options Boost::filesystem) +target_link_libraries(metavision_platform_info PRIVATE MetavisionSDK::base metavision_hal metavision_hal_discovery Boost::program_options) install(TARGETS metavision_platform_info RUNTIME DESTINATION bin diff --git a/hal/cpp/samples/metavision_platform_info/CMakeLists.txt.install b/hal/cpp/samples/metavision_platform_info/CMakeLists.txt.install index 2b8d7048f..5294c3b24 100644 --- a/hal/cpp/samples/metavision_platform_info/CMakeLists.txt.install +++ b/hal/cpp/samples/metavision_platform_info/CMakeLists.txt.install @@ -13,7 +13,7 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) find_package(MetavisionHAL REQUIRED) -find_package(Boost COMPONENTS program_options filesystem REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED) add_executable(metavision_platform_info metavision_platform_info.cpp) -target_link_libraries(metavision_platform_info PRIVATE Metavision::HAL_discovery Boost::program_options Boost::filesystem) \ No newline at end of file +target_link_libraries(metavision_platform_info PRIVATE Metavision::HAL_discovery Boost::program_options) \ No newline at end of file diff --git a/hal/cpp/samples/metavision_platform_info/metavision_platform_info.cpp b/hal/cpp/samples/metavision_platform_info/metavision_platform_info.cpp index 0e0b911dd..bf6b5cab2 100644 --- a/hal/cpp/samples/metavision_platform_info/metavision_platform_info.cpp +++ b/hal/cpp/samples/metavision_platform_info/metavision_platform_info.cpp @@ -11,6 +11,7 @@ // Example of using Metavision SDK Base and Metavision HAL APIs to run a system, platform and software diagnosis. +#include #include #include #include @@ -22,7 +23,6 @@ #ifdef __linux__ #include #endif -#include #include #include #include @@ -443,7 +443,7 @@ void do_platform_diagnosis() { } } - if (boost::filesystem::exists(boost::filesystem::path("/.dockerenv"))) { + if (std::filesystem::exists("/.dockerenv")) { MV_LOG_INFO() << Metavision::Log::no_space << std::left << std::setw(label_size) << "Docker:" << "YES" << std::right; } else { diff --git a/hal/cpp/src/CMakeLists.txt b/hal/cpp/src/CMakeLists.txt index 3efaaf21b..abdca50bd 100644 --- a/hal/cpp/src/CMakeLists.txt +++ b/hal/cpp/src/CMakeLists.txt @@ -7,6 +7,7 @@ # 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. +add_subdirectory(decoders) add_subdirectory(device) add_subdirectory(facilities) add_subdirectory(plugin) diff --git a/hal/cpp/src/decoders/CMakeLists.txt b/hal/cpp/src/decoders/CMakeLists.txt new file mode 100644 index 000000000..7843e315f --- /dev/null +++ b/hal/cpp/src/decoders/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +target_sources(metavision_hal PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/evt2_encoder.cpp +) \ No newline at end of file diff --git a/hal/cpp/src/decoders/evt2_encoder.cpp b/hal/cpp/src/decoders/evt2_encoder.cpp new file mode 100644 index 000000000..b8fdebf42 --- /dev/null +++ b/hal/cpp/src/decoders/evt2_encoder.cpp @@ -0,0 +1,84 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/hal/decoders/evt2/evt2_encoder.h" + +namespace Metavision { + +void Evt2Encoder::reset_state() { + first_timehigh_written_ = false; + ts_last_timehigh_ = std::numeric_limits::min(); + ts_last_ev_ = std::numeric_limits::min(); +} + +void Evt2Encoder::encode_event_cd(std::ofstream &ofs, const EventCD &ev) { + if (ev.t < ts_last_ev_) { + throw std::runtime_error("Input events must be encoded in increasing temporal order!"); + } + update_timehigh(ofs, ev.t); + write_cd(ofs, ev); +} + +void Evt2Encoder::encode_event_trigger(std::ofstream &ofs, const EventExtTrigger &ev) { + if (ev.t < ts_last_ev_) { + throw std::runtime_error("Input events must be encoded in increasing temporal order!"); + } + update_timehigh(ofs, ev.t); + write_trigger(ofs, ev); +} + +void Evt2Encoder::write_raw_event(std::ofstream &ofs, const EVT2RawEvent &raw_evt) const { + ofs.write(reinterpret_cast(&raw_evt.raw), sizeof(raw_evt.raw)); +} + +void Evt2Encoder::write_timehigh(std::ofstream &ofs, timestamp ts_timehigh_ev) { + EVT2RawEvent raw_evt{0}; + raw_evt.th.type = static_cast(EVT2EventTypes::EVT_TIME_HIGH); + raw_evt.th.ts = ts_timehigh_ev >> 6; + write_raw_event(ofs, raw_evt); + ts_last_ev_ = ts_timehigh_ev; +} + +void Evt2Encoder::write_cd(std::ofstream &ofs, const EventCD &ev) { + EVT2RawEvent raw_evt{0}; + raw_evt.cd.type = static_cast(ev.p == 1 ? EVT2EventTypes::CD_ON : EVT2EventTypes::CD_OFF); + raw_evt.cd.timestamp = ev.t; + raw_evt.cd.x = ev.x; + raw_evt.cd.y = ev.y; + write_raw_event(ofs, raw_evt); + ts_last_ev_ = ev.t; +} + +void Evt2Encoder::write_trigger(std::ofstream &ofs, const EventExtTrigger &ev) { + EVT2RawEvent raw_evt{0}; + raw_evt.trig.type = static_cast(EVT2EventTypes::EXT_TRIGGER); + raw_evt.trig.timestamp = ev.t; + raw_evt.trig.id = ev.id; + raw_evt.trig.value = ev.p; + write_raw_event(ofs, raw_evt); + ts_last_ev_ = ev.t; +} + +void Evt2Encoder::update_timehigh(std::ofstream &ofs, timestamp ts) { + if (!first_timehigh_written_) { + first_timehigh_written_ = true; + ts_last_timehigh_ = ts & (~kTime16usMask); + Evt2Encoder::write_timehigh(ofs, ts_last_timehigh_); + } else { + while ((ts_last_timehigh_ >> 4) < (ts >> 4)) { + ts_last_timehigh_ = (ts_last_timehigh_ & (~kTime16usMask)) + 16; + Evt2Encoder::write_timehigh(ofs, ts_last_timehigh_); + } + } +} + +} // namespace Metavision diff --git a/hal/cpp/src/device/device_discovery.cpp b/hal/cpp/src/device/device_discovery.cpp index a8233fe80..041e9a437 100644 --- a/hal/cpp/src/device/device_discovery.cpp +++ b/hal/cpp/src/device/device_discovery.cpp @@ -95,8 +95,8 @@ Metavision::PluginLoader::PluginList get_plugins() { std::string delimiter = ":"; #endif size_t pos = 0; - std::string folder; - std::vector folders; + std::filesystem::path folder; + std::vector folders; while ((pos = plugin_folders.find(delimiter)) != std::string::npos) { folder = plugin_folders.substr(0, pos); MV_HAL_LOG_TRACE() << " Adding plugin search path:" << folder; @@ -117,7 +117,7 @@ Metavision::PluginLoader::PluginList get_plugins() { // Remark : we do it here (after adding folders from MV_HAL_PLUGIN_PATH) // because we want to look first in env var MV_HAL_PLUGIN_PATH (if set by the user) // and then in the installation path - std::string plugin_install_path = Metavision::ResourcesFolder::get_plugin_install_path(); + auto plugin_install_path = Metavision::ResourcesFolder::get_plugin_install_path(); if (!plugin_install_path.empty()) { MV_HAL_LOG_TRACE() << " Adding plugin search path:" << plugin_install_path; plugin_loader.insert_folder(plugin_install_path); @@ -196,7 +196,7 @@ std::string CameraDescription::get_full_serial() const { } bool operator==(const PluginCameraDescription &lhs, const PluginCameraDescription &rhs) { - return lhs.serial_ == rhs.serial_ && lhs.connection_ == rhs.connection_ && lhs.system_id_ == rhs.system_id_; + return (lhs.serial_ == rhs.serial_) && (lhs.connection_ == rhs.connection_); } bool operator!=(const PluginCameraDescription &lhs, const PluginCameraDescription &rhs) { return !(lhs == rhs); @@ -418,28 +418,24 @@ std::unique_ptr DeviceDiscovery::open(const std::string &input_serial, c return device; } -std::unique_ptr DeviceDiscovery::open_raw_file(const std::string &raw_file) { +std::unique_ptr DeviceDiscovery::open_raw_file(const std::filesystem::path &raw_file) { const RawFileConfig cfg; return open_raw_file(raw_file, cfg); } -std::unique_ptr DeviceDiscovery::open_raw_file(const std::string &raw_file, const RawFileConfig &file_config) { +std::unique_ptr DeviceDiscovery::open_raw_file(const std::filesystem::path &raw_file, + const RawFileConfig &file_config) { auto ifs = std::make_unique(raw_file, std::ios::in | std::ios::binary); if (!ifs->good()) { - throw HalException(HalErrorCode::FailedInitialization, "Unable to open RAW file '" + raw_file + "'"); + throw HalException(HalErrorCode::FailedInitialization, "Unable to open RAW file '" + raw_file.string() + "'"); } std::unique_ptr device; try { - device = open_stream(std::move(ifs), file_config); - auto *event_stream = device->get_facility(); - if (event_stream) { - event_stream->set_underlying_filename(raw_file); - } - + device = open_stream(std::move(ifs), file_config); auto *events_stream = device->get_facility(); if (events_stream) { - events_stream->set_underlying_filename(raw_file); + events_stream->set_underlying_file(raw_file); if (file_config.build_index_ && device->get_facility()) { // We create an additional dedicated device that we will use for indexing the RAW file // We set build_index_ = false for this device, because it won't be used for seeking, so it does @@ -459,7 +455,7 @@ std::unique_ptr DeviceDiscovery::open_raw_file(const std::string &raw_fi } } - } catch (const HalException &e) { + } catch (const HalException &) { MV_HAL_LOG_ERROR() << Log::no_space << "While opening RAW file '" << raw_file << "':" << std::endl; throw; } diff --git a/hal/cpp/src/facilities/i_events_stream.cpp b/hal/cpp/src/facilities/i_events_stream.cpp index eafb175df..96ea6dc41 100644 --- a/hal/cpp/src/facilities/i_events_stream.cpp +++ b/hal/cpp/src/facilities/i_events_stream.cpp @@ -20,7 +20,7 @@ #include "metavision/hal/facilities/i_hw_identification.h" #include "metavision/hal/facilities/i_hal_software_info.h" #include "metavision/hal/facilities/i_plugin_software_info.h" -#include "metavision/hal/utils/file_data_transfer.h" +#include "metavision/hal/utils/file_raw_data_producer.h" #include "metavision/hal/utils/hal_connection_exception.h" #include "metavision/hal/utils/hal_error_code.h" #include "metavision/hal/utils/hal_exception.h" @@ -69,8 +69,10 @@ const std::string &get_raw_file_index_extension_suffix() { return extension; } -const std::string get_raw_file_index_name(const std::string &raw_file_name) { - return raw_file_name + get_raw_file_index_extension_suffix(); +const std::filesystem::path get_raw_file_index_path(const std::filesystem::path &raw_file_path) { + std::filesystem::path index_path = raw_file_path; + index_path.replace_extension(index_path.extension().string() + get_raw_file_index_extension_suffix()); + return index_path; } bool serialize_bookmark(I_EventsStream::Bookmark &bookmark, std::ofstream &output_index_file) { @@ -152,14 +154,15 @@ bool check_magic_number_presence(std::ifstream &input_index_file) { return is_bookmark_magic_number(bookmark); } -bool build_and_try_writing_bookmarks(Device &device, I_EventsStream::Index &index, const std::string &raw_file_name, - GenericHeader &index_file_header, const std::string &output_index_file_name, +bool build_and_try_writing_bookmarks(Device &device, I_EventsStream::Index &index, + const std::filesystem::path &raw_file_path, GenericHeader &index_file_header, + const std::filesystem::path &output_index_file_path, const std::atomic &abort) { // Opens the output index file - std::ofstream output_index_file(output_index_file_name, std::ios::binary); + std::ofstream output_index_file(output_index_file_path, std::ios::binary); if (!output_index_file) { - MV_HAL_LOG_WARNING() << "Failed to write index file" << output_index_file_name << "for input RAW file" - << raw_file_name; + MV_HAL_LOG_WARNING() << "Failed to write index file" << output_index_file_path << "for input RAW file" + << raw_file_path; MV_HAL_LOG_WARNING() << "Make sure the folder which contains the RAW file is writeable to avoid building " "the index from scratch again next time"; } @@ -175,9 +178,9 @@ bool build_and_try_writing_bookmarks(Device &device, I_EventsStream::Index &inde const long raw_event_size_bytes = decoder->get_raw_event_size_bytes(); // Retrieve byte offset information of the RAW file - std::ifstream raw_file(raw_file_name, std::ios::binary); + std::ifstream raw_file(raw_file_path, std::ios::binary); if (!raw_file) { - MV_HAL_LOG_ERROR() << "Could not build index for the file. Failed to open RAW file at" << raw_file_name; + MV_HAL_LOG_ERROR() << "Could not build index for the file. Failed to open RAW file at" << raw_file_path; return false; } @@ -206,15 +209,15 @@ bool build_and_try_writing_bookmarks(Device &device, I_EventsStream::Index &inde auto now = std::chrono::steady_clock::now(); if (then + std::chrono::seconds(1) <= now) { then = now; - MV_HAL_LOG_TRACE() << "Still building index for" << raw_file_name << "..."; + MV_HAL_LOG_TRACE() << "Still building index for" << raw_file_path << "..."; } - auto buffer = file_events_stream->get_latest_raw_data(); + auto buffer = file_events_stream->get_latest_raw_data(); // Decode the buffer events per events - for (size_t idx = 0; idx < buffer->size(); + for (size_t idx = 0; idx < buffer.size(); idx += raw_event_size_bytes, current_byte_offset += raw_event_size_bytes) { // Decode single event - decoder->decode(buffer->data() + idx, buffer->data() + idx + raw_event_size_bytes); + decoder->decode(buffer.data() + idx, buffer.data() + idx + raw_event_size_bytes); // Wait for timestamp shift to be computed before logging any bookmark if (!ts_shift_computed) { @@ -244,7 +247,7 @@ bool build_and_try_writing_bookmarks(Device &device, I_EventsStream::Index &inde bookmark.timestamp_ = last_ts; bookmark.byte_offset_ = last_byte_offset; if (!add_bookmarks(last_bookmark_index, bookmark_index, bookmark, index, output_index_file)) { - MV_HAL_LOG_ERROR() << "Could not write index to the file" << raw_file_name; + MV_HAL_LOG_ERROR() << "Could not write index to the file" << raw_file_path; return false; } last_byte_offset = current_byte_offset; @@ -259,27 +262,16 @@ bool build_and_try_writing_bookmarks(Device &device, I_EventsStream::Index &inde bookmark.timestamp_ = last_ts; bookmark.byte_offset_ = last_byte_offset; if (!add_bookmarks(last_bookmark_index, last_bookmark_index + 1, bookmark, index, output_index_file)) { - MV_HAL_LOG_ERROR() << "Could not write index to the file" << raw_file_name; + MV_HAL_LOG_ERROR() << "Could not write index to the file" << raw_file_path; return false; } if (!add_magic_number(output_index_file)) { - MV_HAL_LOG_ERROR() << "Could not write index to the file" << raw_file_name; + MV_HAL_LOG_ERROR() << "Could not write index to the file" << raw_file_path; return false; } - if (abort) { - if (output_index_file) { - output_index_file.close(); - // remove incomplete index file - remove(output_index_file_name.c_str()); - } - MV_HAL_LOG_TRACE() << "Indexing for input RAW file" << raw_file_name - << "has been aborted, removing incomplete index file"; - return false; - } - - return true; + return !abort; } I_EventsStream::Bookmarks load_bookmarks(std::ifstream &input_index_file, const std::atomic &abort) { @@ -309,13 +301,13 @@ I_EventsStream::Bookmarks load_bookmarks(std::ifstream &input_index_file, const return bookmarks; } -I_EventsStream::Index build_index(Device &device, const std::string &raw_file_name, const std::atomic &abort) { +I_EventsStream::Index build_index(Device &device, const std::filesystem::path &raw_file_path, + const std::atomic &abort) { I_EventsStream::Index index; - bool do_build_index = false; // ------------------------------ // Retrieve RAW file info - std::ifstream raw_file(raw_file_name, std::ios::binary); + std::ifstream raw_file(raw_file_path, std::ios::binary); if (!raw_file) { // RAW file can't be opened. Should not happen. return index; @@ -339,12 +331,12 @@ I_EventsStream::Index build_index(Device &device, const std::string &raw_file_na // Checks the validity of the index file for the input RAW file // Opens the index file - const std::string raw_file_index_name(get_raw_file_index_name(raw_file_name)); - std::ifstream index_file(raw_file_index_name, std::ios::binary); - if (!index_file) { - // Index file doesn't exist - do_build_index = true; - } else { + const std::filesystem::path raw_file_index_path(get_raw_file_index_path(raw_file_path)); + bool do_build_index = !std::filesystem::exists(raw_file_index_path); + + if (!do_build_index) { + std::ifstream index_file(raw_file_index_path, std::ios::binary); + // Index file exists // Now quick check the content to assert if the indexed file actually indexes the input RAW file @@ -405,13 +397,12 @@ I_EventsStream::Index build_index(Device &device, const std::string &raw_file_na // Make sure that magic number is present do_build_index = do_build_index || !check_magic_number_presence(index_file); }; - index_file.close(); // ------------------------------ // If necessary, compute and write the index if (do_build_index) { // Builds and write the index - MV_HAL_LOG_TRACE() << "Building index for input RAW file" << raw_file_name; + MV_HAL_LOG_TRACE() << "Building index for input RAW file" << raw_file_path; // Write index file's header GenericHeader index_file_header(raw_file_header); @@ -424,10 +415,17 @@ I_EventsStream::Index build_index(Device &device, const std::string &raw_file_na index_file_header.set_field(bookmark_period_key, bookmark_period_us_str); index_file_header.set_field(index_version_key, index_version); - if (!build_and_try_writing_bookmarks(device, index, raw_file_name, index_file_header, raw_file_index_name, + if (!build_and_try_writing_bookmarks(device, index, raw_file_path, index_file_header, raw_file_index_path, abort)) { if (!abort) { - MV_HAL_LOG_WARNING() << "Failed to build index for input RAW file" << raw_file_name; + MV_HAL_LOG_WARNING() << "Failed to build index for input RAW file" << raw_file_path; + } else { + if (std::filesystem::exists(raw_file_index_path)) { + // remove incomplete index file + std::filesystem::remove(raw_file_index_path); + } + MV_HAL_LOG_TRACE() << "Indexing for input RAW file" << raw_file_path + << "has been aborted, removing incomplete index file"; } index.status_ = I_EventsStream::IndexStatus::Bad; return index; @@ -436,11 +434,11 @@ I_EventsStream::Index build_index(Device &device, const std::string &raw_file_na index.bookmark_period_ = bookmark_period_us; // index.ts_shift_us_ and index.bookmarks_ are filled by build_and_try_writing_bookmarks index.status_ = I_EventsStream::IndexStatus::Good; - MV_HAL_LOG_TRACE() << "Index for input RAW file" << raw_file_name << "built"; + MV_HAL_LOG_TRACE() << "Index for input RAW file" << raw_file_path << "built"; } else { - index_file.open(raw_file_index_name, std::ios::binary); + std::ifstream index_file(raw_file_index_path, std::ios::binary); if (!index_file) { - MV_HAL_LOG_ERROR() << "Failed to open index for RAW file at" << raw_file_index_name; + MV_HAL_LOG_ERROR() << "Failed to open index for RAW file at" << raw_file_index_path; index.status_ = I_EventsStream::IndexStatus::Bad; return index; } @@ -452,12 +450,12 @@ I_EventsStream::Index build_index(Device &device, const std::string &raw_file_na index.ts_shift_us_ = std::atoll(index_file_header.get_field(ts_shift_key).c_str()); index.bookmarks_ = load_bookmarks(index_file, abort); if (index.bookmarks_.empty()) { - MV_HAL_LOG_ERROR() << "Failed to open index for RAW file at" << raw_file_index_name; + MV_HAL_LOG_ERROR() << "Failed to open index for RAW file at" << raw_file_index_path; index.status_ = I_EventsStream::IndexStatus::Bad; return index; } index.status_ = I_EventsStream::IndexStatus::Good; - MV_HAL_LOG_TRACE() << "Index for input RAW file" << raw_file_name << "loaded"; + MV_HAL_LOG_TRACE() << "Index for input RAW file" << raw_file_path << "loaded"; } return index; @@ -465,11 +463,11 @@ I_EventsStream::Index build_index(Device &device, const std::string &raw_file_na } // namespace -I_EventsStream::I_EventsStream(std::unique_ptr data_transfer, +I_EventsStream::I_EventsStream(std::unique_ptr data_producer, const std::shared_ptr &hw_identification, const std::shared_ptr &decoder, const std::shared_ptr &device_control) : - data_transfer_(std::move(data_transfer)), + data_transfer_(std::move(data_producer)), hw_identification_(hw_identification), decoder_(decoder), seeking_(false), @@ -477,26 +475,21 @@ I_EventsStream::I_EventsStream(std::unique_ptr data_transfer, // this is not the most elegant way of figuring out if we are transferring data from an offline // recording where we should not release the buffers when the streaming is stopped, but this keeps // binary backward compatibility with previously released interfaces of DataTransfer - stop_should_release_buffers_(dynamic_cast(data_transfer_.get()) == nullptr), - tmp_buffer_pool_(DataTransfer::BufferPool::make_unbounded()), + stop_should_release_buffers_(std::dynamic_pointer_cast(data_transfer_.get_data_producer()) == + nullptr), stop_(true) { if (!hw_identification_) { throw(HalException(HalErrorCode::FailedInitialization, "HW identification facility is null.")); } - data_transfer_->add_new_buffer_callback([this](const DataTransfer::BufferPtr &buffer) { + data_transfer_.add_new_buffer_callback([this](const DataTransfer::BufferPtr &buffer) { std::unique_lock lock(new_buffer_safety_); if (seeking_) { - // to prevent any data loss when seeking, while also preventing a deadlock when trying to stop - // the data transfer before resetting the stream to a different position we need to copy this buffer in a - // temporary buffer pool - auto tmp_buffer = tmp_buffer_pool_.acquire(); - *tmp_buffer = *buffer; - available_buffers_.push(tmp_buffer); + available_buffers_.push(buffer.clone()); } else { if (!stop_) { - auto *buf = buffer.get(); - if (data_transfer_buffer_ptrs_.count(buf) == 0) { - data_transfer_buffer_ptrs_.insert(buf); + auto buff_ptr = buffer.data(); + if (data_transfer_buffer_ptrs_.count(buff_ptr) == 0) { + data_transfer_buffer_ptrs_.insert(buff_ptr); } available_buffers_.push(buffer); new_buffer_cond_.notify_all(); @@ -505,15 +498,14 @@ I_EventsStream::I_EventsStream(std::unique_ptr data_transfer, // streaming is stopped, this buffer comes from the data transfer and we should not release // transferred buffers, so we need to copy this buffer in a temporary buffer pool to make sure the // data transfer buffer pool is empty when streaming is resumed - auto tmp_buffer = tmp_buffer_pool_.acquire(); - *tmp_buffer = *buffer; + auto tmp_buffer = buffer.clone(); available_buffers_.push(tmp_buffer); } } } }); - data_transfer_->add_status_changed_callback([this](DataTransfer::Status status) { + data_transfer_.add_status_changed_callback([this](DataTransfer::Status status) { if (status == DataTransfer::Status::Stopped) { bool should_notify = false; { @@ -534,11 +526,11 @@ I_EventsStream::I_EventsStream(std::unique_ptr data_transfer, } }); - data_transfer_->add_transfer_error_callback([this](std::exception_ptr eptr) { + data_transfer_.add_transfer_error_callback([this](std::exception_ptr eptr) { std::unique_lock lock(new_buffer_safety_); try { std::rethrow_exception(eptr); - } catch (HalConnectionException &e) { + } catch (const HalConnectionException &) { // Only propagate connection exceptions data_transfer_connection_error_ = std::current_exception(); } catch (...) {} @@ -553,7 +545,6 @@ I_EventsStream::~I_EventsStream() { try { stop(); } catch (const std::exception &e) { MV_LOG_ERROR() << "I_EventsStream::stop() raised an exception : " << e.what(); } - data_transfer_.reset(nullptr); data_transfer_connection_error_ = nullptr; } @@ -562,11 +553,10 @@ void I_EventsStream::release_data_transfer_buffers() { std::swap(tmp_queue, available_buffers_); while (!tmp_queue.empty()) { auto buffer = tmp_queue.front(); - if (data_transfer_buffer_ptrs_.count(buffer.get())) { + if (data_transfer_buffer_ptrs_.count(buffer.data())) { // we only copy buffers that are coming from the data transfer pool // those are the ones we need to release - auto tmp_buffer = tmp_buffer_pool_.acquire(); - *tmp_buffer = *buffer; + auto tmp_buffer = buffer.clone(); available_buffers_.push(tmp_buffer); } else { available_buffers_.push(buffer); @@ -581,7 +571,7 @@ void I_EventsStream::start() { std::lock_guard lock(new_buffer_safety_); stop_ = false; } - data_transfer_->start(); + data_transfer_.start(); start_device(); } @@ -604,7 +594,7 @@ void I_EventsStream::stop() { stop_log_raw_data(); } stop_device(); - data_transfer_->stop(); + data_transfer_.stop(); } void I_EventsStream::start_device() { @@ -644,37 +634,6 @@ short I_EventsStream::wait_next_buffer() { return available_buffers_.empty() ? -1 : 1; } -I_EventsStream::RawData *I_EventsStream::get_latest_raw_data(long &size) { - DataTransfer::BufferPtr local_ptr; - { - std::lock_guard lock(new_buffer_safety_); - - if (stop_ && data_transfer_connection_error_) { - std::rethrow_exception(data_transfer_connection_error_); - } - - if (available_buffers_.empty()) { - // If no new buffer available yet - size = 0; - return nullptr; - } - - // Keep a reference to returned buffer to ensure validity until next call to this function - returned_buffer_ = available_buffers_.front(); - size = returned_buffer_->size(); - available_buffers_.pop(); - local_ptr = returned_buffer_; - } - - { - std::lock_guard log_lock(log_raw_safety_); - if (log_raw_data_) { - log_raw_data_->write(reinterpret_cast(local_ptr->data()), size * sizeof(RawData)); - } - } - return local_ptr->data(); -} - DataTransfer::BufferPtr I_EventsStream::get_latest_raw_data() { DataTransfer::BufferPtr res; { @@ -686,7 +645,7 @@ DataTransfer::BufferPtr I_EventsStream::get_latest_raw_data() { if (available_buffers_.empty()) { // If no new buffer available yet - return nullptr; + return {}; } // Reset potential reference from last call @@ -698,7 +657,7 @@ DataTransfer::BufferPtr I_EventsStream::get_latest_raw_data() { { std::lock_guard log_lock(log_raw_safety_); if (log_raw_data_) { - log_raw_data_->write(reinterpret_cast(res->data()), res->size() * sizeof(RawData)); + log_raw_data_->write(reinterpret_cast(res.data()), res.size() * sizeof(RawData)); } } return res; @@ -717,8 +676,8 @@ I_EventsStream::SeekStatus I_EventsStream::seek(timestamp target_ts_us, timestam break; } - auto file_data_transfer = dynamic_cast(data_transfer_.get()); - if (!file_data_transfer || !decoder_) { + auto file_raw_data_producer = std::dynamic_pointer_cast(data_transfer_.get_data_producer()); + if (!file_raw_data_producer || !decoder_) { // should never happen, we check that seeking is possible before indexing... return SeekStatus::SeekCapabilityNotAvailable; } @@ -749,9 +708,8 @@ I_EventsStream::SeekStatus I_EventsStream::seek(timestamp target_ts_us, timestam release_data_transfer_buffers(); } - file_data_transfer->suspend(); - - auto seek_succeed = file_data_transfer->seek(index_.bookmarks_[bookmark_index].byte_offset_); + data_transfer_.suspend(); + auto seek_succeed = file_raw_data_producer->seek(index_.bookmarks_[bookmark_index].byte_offset_); SeekStatus seek_status; if (seek_succeed) { @@ -767,19 +725,19 @@ I_EventsStream::SeekStatus I_EventsStream::seek(timestamp target_ts_us, timestam stop_ = false; } - if (file_data_transfer->stopped()) { + if (data_transfer_.stopped()) { // if the data transfer was stopped because the end of file was reached before seeking, restart it // // Note : even if we start the data transfer now (while seeking_ = true), there is no risk of missing a EOF // (which would be signaled by a Stopped status change ... but ignored because a seek is ongoing) since the // data transfer won't resume reading (and thus reach a potential EOF) before seeking_ = false (c.f wait // loop in status change callback) - file_data_transfer->start(); + data_transfer_.start(); } } else { seek_status = SeekStatus::Failed; - if (file_data_transfer->stopped()) { + if (data_transfer_.stopped()) { // if the data transfer was stopped while we were seeking, and the seek failed, // update our status { @@ -791,7 +749,7 @@ I_EventsStream::SeekStatus I_EventsStream::seek(timestamp target_ts_us, timestam } seeking_ = false; - file_data_transfer->resume(); + data_transfer_.resume(); return seek_status; } @@ -833,34 +791,41 @@ void I_EventsStream::index(std::unique_ptr device_for_indexing) { return; } - if (get_underlying_filename().empty()) { + if (get_underlying_file().empty()) { MV_HAL_LOG_ERROR() << "Can not build index for the stream input (no valid RAW file name found)."; index_.status_ = IndexStatus::Bad; return; } auto indexing_fes = device_for_indexing->get_facility(); - if (!indexing_fes || !dynamic_cast(indexing_fes->data_transfer_.get()) || + if (!indexing_fes || + !std::dynamic_pointer_cast(indexing_fes->data_transfer_.get_data_producer()) || !indexing_fes->decoder_) { MV_HAL_LOG_ERROR() << "Can not build index for the stream input: invalid indexing device."; return; } - if (indexing_fes->get_underlying_filename() != get_underlying_filename()) { + if (indexing_fes->get_underlying_file() != get_underlying_file()) { MV_HAL_LOG_ERROR() << "Can not build index for the stream input: indexing device is built from another RAW " "file as source. The file to index is" - << get_underlying_filename() << "whereas the input indexing device has been built from" - << indexing_fes->get_underlying_filename(); + << get_underlying_file() << "whereas the input indexing device has been built from" + << indexing_fes->get_underlying_file(); } index_.status_ = IndexStatus::Building; // Start the indexing thread index_build_thread_ = std::thread([device_for_indexing = std::move(device_for_indexing), this]() { - auto index = index_impl(*device_for_indexing); - - std::lock_guard lock(index_safety_); - std::swap(index_, index); + try { + auto index = index_impl(*device_for_indexing); + + std::lock_guard lock(index_safety_); + std::swap(index_, index); + } catch (const std::exception &e) { + MV_HAL_LOG_WARNING() << "Unhandled error while building index:"; + MV_HAL_LOG_WARNING() << e.what(); + MV_HAL_LOG_WARNING() << "Seek feature might not work properly."; + } }); // Wait for the thread to be running @@ -869,7 +834,7 @@ void I_EventsStream::index(std::unique_ptr device_for_indexing) { I_EventsStream::Index I_EventsStream::index_impl(Device &device) { abort_index_building_ = false; - auto index = build_index(device, get_underlying_filename(), abort_index_building_); + auto index = build_index(device, get_underlying_file(), abort_index_building_); decoder_->reset_timestamp_shift(index.ts_shift_us_); return index; } @@ -880,7 +845,7 @@ void I_EventsStream::stop_log_raw_data() { } bool I_EventsStream::log_raw_data(const std::string &f) { - if (f == underlying_filename_) { + if (f == underlying_file_) { return false; } @@ -898,12 +863,12 @@ bool I_EventsStream::log_raw_data(const std::string &f) { return true; } -void I_EventsStream::set_underlying_filename(const std::string &filename) { - underlying_filename_ = filename; +void I_EventsStream::set_underlying_file(const std::filesystem::path &file) { + underlying_file_ = file; } -const std::string &I_EventsStream::get_underlying_filename() const { - return underlying_filename_; +const std::filesystem::path &I_EventsStream::get_underlying_file() const { + return underlying_file_; } } // namespace Metavision diff --git a/hal/cpp/src/facilities/i_events_stream_decoder.cpp b/hal/cpp/src/facilities/i_events_stream_decoder.cpp index 36606e67c..df6367b66 100644 --- a/hal/cpp/src/facilities/i_events_stream_decoder.cpp +++ b/hal/cpp/src/facilities/i_events_stream_decoder.cpp @@ -33,6 +33,25 @@ I_EventsStreamDecoder::I_EventsStreamDecoder( } } +I_EventsStreamDecoder::I_EventsStreamDecoder( + bool time_shifting_enabled, const std::shared_ptr> &cd_vector_event_decoder, + const std::shared_ptr> &ext_trigger_event_decoder, + const std::shared_ptr> &erc_count_event_decoder) : + is_time_shifting_enabled_(time_shifting_enabled), + cd_event_vector_decoder_(cd_vector_event_decoder), + ext_trigger_event_decoder_(ext_trigger_event_decoder), + erc_count_event_decoder_(erc_count_event_decoder) { + if (cd_event_vector_decoder_) { + cd_event_vector_forwarder_.reset(new DecodedEventForwarder(cd_event_vector_decoder_.get())); + } + if (ext_trigger_event_decoder_) { + trigger_event_forwarder_.reset(new DecodedEventForwarder(ext_trigger_event_decoder_.get())); + } + if (erc_count_event_decoder_) { + erc_count_event_forwarder_.reset(new DecodedEventForwarder(erc_count_event_decoder_.get())); + } +} + bool I_EventsStreamDecoder::is_time_shifting_enabled() const { return is_time_shifting_enabled_; } @@ -78,6 +97,9 @@ void I_EventsStreamDecoder::decode(const RawData *const raw_data_begin, const Ra if (cd_event_forwarder_) { cd_event_forwarder_->flush(); } + if (cd_event_vector_forwarder_) { + cd_event_vector_forwarder_->flush(); + } if (trigger_event_forwarder_) { trigger_event_forwarder_->flush(); } @@ -90,6 +112,10 @@ void I_EventsStreamDecoder::decode(const RawData *const raw_data_begin, const Ra } } +void I_EventsStreamDecoder::decode(const DataTransfer::BufferPtr &raw_buffer) { + decode(raw_buffer.begin(), raw_buffer.end()); +} + size_t I_EventsStreamDecoder::add_time_callback(const TimeCallback_t &cb) { time_cbs_map_[next_cb_idx_] = cb; return next_cb_idx_++; @@ -104,38 +130,9 @@ bool I_EventsStreamDecoder::remove_time_callback(size_t callback_id) { return false; } -// Exception only used to detect which of reset_timestamp or reset_last_timestamp is implemented -// Should be removed once reset_timestamp is removed -class ResetTimestampNotImplementedException : public std::exception {}; - -bool I_EventsStreamDecoder::reset_timestamp(const timestamp ×tamp) { - return reset_last_timestamp(timestamp); -} - bool I_EventsStreamDecoder::reset_last_timestamp(const timestamp ×tamp) { incomplete_raw_data_.clear(); - try { - return reset_timestamp_impl(timestamp); - } catch (const ResetTimestampNotImplementedException &e) { - try { - return reset_last_timestamp_impl(timestamp); - } catch (const ResetTimestampNotImplementedException &e) { - // Plugin is broken - throw HalException(HalErrorCode::OperationNotImplemented, - "I_EventsStreamDecoder::reset_timestamp/reset_last_timestamp" - " operation is not implemented by the current plugin"); - } - } - return false; -} - -bool I_EventsStreamDecoder::reset_timestamp_impl(const timestamp ×tamp) { - throw ResetTimestampNotImplementedException(); -} - -// Should made pure virtual once I_EventsStreamDecoder::reset_timestamp is removed -bool I_EventsStreamDecoder::reset_last_timestamp_impl(const timestamp ×tamp) { - throw ResetTimestampNotImplementedException(); + return reset_last_timestamp_impl(timestamp); } bool I_EventsStreamDecoder::reset_timestamp_shift(const timestamp &t) { diff --git a/hal/cpp/src/facilities/i_hw_identification.cpp b/hal/cpp/src/facilities/i_hw_identification.cpp index 87e11df74..3c4e3ce23 100644 --- a/hal/cpp/src/facilities/i_hw_identification.cpp +++ b/hal/cpp/src/facilities/i_hw_identification.cpp @@ -38,7 +38,6 @@ I_HW_Identification::I_HW_Identification(const std::shared_ptr #include +#include "metavision/sdk/base/utils/generic_header.h" #include "metavision/hal/facilities/i_ll_biases.h" #include "metavision/hal/utils/hal_exception.h" #include "metavision/hal/utils/hal_log.h" @@ -62,6 +64,98 @@ bool I_LL_Biases::get_bias_info(const std::string &bias_name, LL_Bias_Info &bias return true; } +void I_LL_Biases::load_from_file(const std::filesystem::path &src_file) { + // Check extension + const auto extension = src_file.extension().string(); + if (extension != ".bias") { + throw HalException(HalErrorCode::InvalidArgument, + "For bias file '" + src_file.string() + + "' : expected '.bias' extension to set the bias from this file but got '." + + extension + "'"); + } + + // open file + std::ifstream bias_file(src_file); + if (!bias_file.is_open()) { + throw HalException(HalErrorCode::InvalidArgument, + "Could not open file '" + src_file.string() + "' for reading. Failed to set biases."); + } + + // Skip header if any + GenericHeader header(bias_file); + + // Get available biases : + std::map available_biases = get_all_biases(); + + // Parse the file to get the list of the biases that the user wants to set + std::map biases_to_set; + for (std::string line; std::getline(bias_file, line) && !line.empty();) { + std::stringstream ss(line); + + // Get value and name + std::string value_str, bias_name, separator; + ss >> value_str >> separator >> bias_name; + std::transform(value_str.begin(), value_str.end(), value_str.begin(), ::tolower); + + if (value_str.empty() || bias_name.empty()) { + throw HalException(HalErrorCode::InvalidArgument, + "Cannot read bias file '" + src_file.string() + "' : wrong line format '" + line + "'"); + } + int value; + if (value_str.find("0x") != std::string::npos) { + value = std::stoi(value_str, 0, 16); + + } else { + value = std::stol(value_str); + } + + // Check if the bias that we want to set is compatible and not read only + LL_Bias_Info bias_info; + get_bias_info(bias_name, bias_info); + if (!bias_info.is_modifiable()) { + continue; + } + + auto it = biases_to_set.find(bias_name); + if (it != biases_to_set.end()) { + if (value != it->second) { + throw HalException(HalErrorCode::InvalidArgument, "Given two different values for bias '" + + bias_name + "' in file '" + src_file.string() + "'"); + } + } + biases_to_set.emplace(bias_name, value); + } + + // If we get here, no error was found, and we can proceed in setting the biases + for (auto it = biases_to_set.begin(), it_end = biases_to_set.end(); it != it_end; ++it) { + set(it->first, it->second); + } +} + +void I_LL_Biases::save_to_file(const std::filesystem::path &dest_file) const { + const auto extension = dest_file.extension().string(); + if (extension != ".bias") { + throw HalException(HalErrorCode::InvalidArgument, + "For bias file '" + dest_file.string() + + "' : expected '.bias' extension to set the bias from this file but got '." + + extension + "'"); + } + + std::ofstream output_file(dest_file); + if (!output_file.is_open()) { + throw HalException(HalErrorCode::InvalidArgument, + "Could not open file '" + dest_file.string() + "' for writing. Failed to save biases."); + } + + // Get available biases : + std::map available_biases = get_all_biases(); + + for (auto it = available_biases.begin(), it_end = available_biases.end(); it != it_end; ++it) { + output_file << std::left << std::setw(5) << it->second << "% " << it->first << std::endl; + } + output_file.close(); +} + LL_Bias_Info::LL_Bias_Info(int min_value, int max_value, const std::string &description, bool modifiable, const std::string &category) : description_(description), diff --git a/hal/cpp/src/plugin/plugin_loader.cpp b/hal/cpp/src/plugin/plugin_loader.cpp index c563e7437..2cb95e00f 100644 --- a/hal/cpp/src/plugin/plugin_loader.cpp +++ b/hal/cpp/src/plugin/plugin_loader.cpp @@ -113,31 +113,28 @@ struct dlcloser { namespace Metavision { struct PluginLoader::PluginInfo { - PluginInfo(const std::string &folder, const std::string &filename) { + PluginInfo(const std::filesystem::path &folder, const std::string &filename) { #ifdef _WIN32 #ifdef _DEBUG name = get_plugin_name(filename, "dll", "", "_d", true); - path = folder + "\\" + filename; #else name = get_plugin_name(filename, "dll", "", "_d", false); - path = folder + "\\" + filename; #endif #elif defined __APPLE__ name = get_plugin_name(filename, "dylib"); - path = folder + "/" + filename; #else name = get_plugin_name(filename, "so"); - path = folder + "/" + filename; #endif + path = folder / filename; } std::string name; - std::string path; + std::filesystem::path path; }; struct PluginLoader::Library { - Library(const std::string &entrypoint_name, const std::string &name, const std::string &path) : - handle(load_library(path.c_str())) { + Library(const std::string &entrypoint_name, const std::string &name, const std::filesystem::path &path) : + handle(load_library(path)) { if (handle && !entrypoint_name.empty()) { auto entrypoint = reinterpret_cast(load_entrypoint(handle.get(), entrypoint_name.c_str())); if (entrypoint) { @@ -148,37 +145,30 @@ struct PluginLoader::Library { } #ifdef _WIN32 - void *load_library(const char *name) { - char abs_path[MAX_PATH]; - GetFullPathName(name, MAX_PATH, abs_path, nullptr); - name = abs_path; + void *load_library(const std::filesystem::path &path) { + const std::filesystem::path dir = std::filesystem::canonical(path).parent_path(); - std::string dir = abs_path; LPSTR old_dll_dir = nullptr; - auto dir_sep_pos = dir.rfind("\\"); - if (dir_sep_pos != std::string::npos) { - dir = dir.substr(0, dir_sep_pos); - if (dir != "") { - // Save old dll directory - DWORD size = GetDllDirectoryA(0, old_dll_dir); - if (size > 0) { - old_dll_dir = new char[size + 1]; - GetDllDirectoryA(size + 1, old_dll_dir); - if (std::string(old_dll_dir) == "") { - delete[] old_dll_dir; - old_dll_dir = nullptr; - } + if (!dir.empty()) { + // Save old dll directory + DWORD size = GetDllDirectoryA(0, old_dll_dir); + if (size > 0) { + old_dll_dir = new char[size + 1]; + GetDllDirectoryA(size + 1, old_dll_dir); + if (std::string(old_dll_dir) == "") { + delete[] old_dll_dir; + old_dll_dir = nullptr; } - SetDllDirectoryA(dir.c_str()); } + SetDllDirectoryA(dir.string().c_str()); } - void *handler = (void *)LoadLibraryA(name); + void *handler = (void *)LoadLibraryA(std::filesystem::canonical(path).string().c_str()); if (handler == nullptr) { showErrorMsg("LoadLibraryA"); } - if (dir != "" && dir_sep_pos != std::string::npos) { + if (!dir.empty()) { // Restore dll directory SetDllDirectoryA(old_dll_dir); } @@ -198,9 +188,9 @@ struct PluginLoader::Library { return entrypoint; } #else - void *load_library(const char *name) { + void *load_library(const std::filesystem::path &path) { dlerror(); - void *handler = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); + void *handler = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); if (handler == nullptr) { showErrorMsg(std::string("dlopen error: ") + std::string(dlerror())); } @@ -231,7 +221,7 @@ void PluginLoader::clear_folders() { folders_.clear(); } -void PluginLoader::insert_folder(const std::string &folder) { +void PluginLoader::insert_folder(const std::filesystem::path &folder) { if (std::find(folders_.begin(), folders_.end(), folder) == folders_.end()) { folders_.push_back(folder); } @@ -243,18 +233,19 @@ void PluginLoader::insert_folders(const std::vector &folders) { } } +void PluginLoader::insert_folders(const std::vector &folders) { + for (const auto &folder : folders) { + insert_folder(folder); + } +} + void PluginLoader::load_plugins() { for (auto folder : folders_) { - DIR *dir_descriptor; - dir_descriptor = opendir(folder.c_str()); - if (dir_descriptor) { - struct dirent *entries; - while ((entries = readdir(dir_descriptor)) != NULL) { - std::string filename = entries->d_name; - auto plugin_info = PluginInfo(folder, filename); + if (std::filesystem::is_directory(folder)) { + for (auto const &dir_entry : std::filesystem::directory_iterator(folder)) { + auto plugin_info = PluginInfo(folder, dir_entry.path().filename().string()); insert_plugin(plugin_info); } - closedir(dir_descriptor); } } } @@ -264,7 +255,7 @@ void PluginLoader::unload_plugins() { libraries_.clear(); } -void PluginLoader::insert_plugin(const std::string &name, const std::string &library_path) { +void PluginLoader::insert_plugin(const std::string &name, const std::filesystem::path &library_path) { if (!name.empty() && !library_path.empty()) { auto library = std::make_unique(get_plugin_entry_point(), name, library_path); if (library->plugin) { diff --git a/hal/cpp/src/utils/CMakeLists.txt b/hal/cpp/src/utils/CMakeLists.txt index 5db6cad15..ca166dd84 100644 --- a/hal/cpp/src/utils/CMakeLists.txt +++ b/hal/cpp/src/utils/CMakeLists.txt @@ -15,7 +15,7 @@ target_sources(metavision_hal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/device_config.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hal_exception.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hal_software_info.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/file_data_transfer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/file_raw_data_producer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/file_discovery.cpp ${CMAKE_CURRENT_SOURCE_DIR}/raw_file_header.cpp ${CMAKE_CURRENT_SOURCE_DIR}/resources_folder.cpp diff --git a/hal/cpp/src/utils/data_transfer.cpp b/hal/cpp/src/utils/data_transfer.cpp index 854170b0c..4c312a074 100644 --- a/hal/cpp/src/utils/data_transfer.cpp +++ b/hal/cpp/src/utils/data_transfer.cpp @@ -9,28 +9,17 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include "metavision/hal/utils/hal_connection_exception.h" #include "metavision/hal/utils/hal_exception.h" #include "metavision/hal/utils/data_transfer.h" namespace Metavision { -DataTransfer::DataTransfer(uint32_t raw_event_size_bytes) : raw_event_size_bytes_(raw_event_size_bytes) {} - -DataTransfer::DataTransfer(uint32_t raw_event_size_bytes, const BufferPool &buffer_pool, bool allow_buffer_drop) : - raw_event_size_bytes_(raw_event_size_bytes), buffer_pool_(buffer_pool), allow_buffer_drop_(allow_buffer_drop) { - if (buffer_pool_.is_bounded() && buffer_pool_.size() < 3) { - throw HalException(HalErrorCode::InvalidArgument, - "A DataTransfer can not be initialized with a bounded object pool of size < 3 (got size " + - std::to_string(buffer_pool_.size()) + ")."); - } -} +DataTransfer::DataTransfer(RawDataProducerPtr data_producer_ptr) : data_producer_ptr_(data_producer_ptr) {} DataTransfer::~DataTransfer() { - // not calling stop here, rather leaving this "burden" to the user of the data transfer - // will will most probably be in the destructor of I_EventStream - // if done from this destructor, it will be too late to call a derived version of stop_impl - // if one was defined + stop(); } void DataTransfer::start() { @@ -51,9 +40,14 @@ void DataTransfer::start() { stop_ = false; running_ = false; } - start_impl(get_buffer()); - run_transfers_thread_ = std::thread([this]() { + data_producer_ptr_->start_impl(); + + std::promise thread_is_started; + std::future has_started = thread_is_started.get_future(); + + run_transfers_thread_ = std::thread([this, &thread_is_started]() { + thread_is_started.set_value(); for (auto cb : status_change_cbs_) { cb.second(Status::Started); } @@ -68,7 +62,8 @@ void DataTransfer::start() { std::unique_lock lock(running_mutex_); running_ = true; } - run_impl(); + + data_producer_ptr_->run_impl(*this); if (!suspend_) { break; @@ -96,7 +91,7 @@ void DataTransfer::start() { } }); - while (!run_transfers_thread_.joinable()) {} + has_started.wait(); } void DataTransfer::stop() { @@ -105,7 +100,7 @@ void DataTransfer::stop() { } try { - stop_impl(); + data_producer_ptr_->stop_impl(); } catch (const HalConnectionException &) { notify_stop(); // We can't be sure the thread will terminate @@ -162,7 +157,7 @@ size_t DataTransfer::add_new_buffer_callback(NewBufferCallback_t cb) { size_t DataTransfer::add_transfer_error_callback(TransferErrorCallback_t cb) { transfer_error_cbs_[cb_index_] = cb; - auto ret = cb_index_; + auto ret = cb_index_; ++cb_index_; return ret; } @@ -173,11 +168,7 @@ void DataTransfer::remove_callback(size_t cb_id) { transfer_error_cbs_.erase(cb_id); } -uint32_t DataTransfer::get_raw_event_size_bytes() const { - return raw_event_size_bytes_; -} - -bool DataTransfer::should_stop() { +bool DataTransfer::should_stop() const { return stop_ || suspend_; } @@ -185,14 +176,69 @@ bool DataTransfer::stopped() const { return stop_; } -void DataTransfer::start_impl(BufferPtr buffer) {} - -void DataTransfer::stop_impl() {} - -void DataTransfer::fire_callbacks(const BufferPtr buffer) const { +void DataTransfer::fire_callbacks(const BufferPtr &buffer) const { for (auto &cb : new_buffer_cbs_) { cb.second(buffer); } } +DataTransfer::BufferPtr::BufferPtr(std::any buffer, PtrType data, std::size_t buffer_size) : + internal_buffer_(buffer), buffer_data_(data), buffer_size_(buffer_size) {} + +bool DataTransfer::BufferPtr::operator==(const BufferPtr &other) const { + if (other.buffer_size_ != buffer_size_) { + return false; + } + + return std::equal(begin(), end(), other.begin()); +} + +DataTransfer::BufferPtr::operator bool() const noexcept { + return buffer_data_ != nullptr; +} + +std::size_t DataTransfer::BufferPtr::size() const noexcept { + return buffer_size_; +} + +DataTransfer::BufferPtr::PtrType DataTransfer::BufferPtr::data() const noexcept { + return buffer_data_; +} + +DataTransfer::BufferPtr::PtrType DataTransfer::BufferPtr::begin() const noexcept { + return buffer_data_; +} + +DataTransfer::BufferPtr::PtrType DataTransfer::BufferPtr::end() const noexcept { + return buffer_data_ + buffer_size_; +} + +const DataTransfer::BufferPtr::PtrType DataTransfer::BufferPtr::cbegin() const noexcept { + return begin(); +} + +const DataTransfer::BufferPtr::PtrType DataTransfer::BufferPtr::cend() const noexcept { + return end(); +} + +DataTransfer::BufferPtr DataTransfer::BufferPtr::clone() const { + auto new_buffer = std::make_shared(); + new_buffer->reserve(buffer_size_); + + auto from = buffer_data_; + auto end = buffer_data_ + buffer_size_; + std::copy(from, end, std::back_inserter(*new_buffer)); + + return make_buffer_ptr(new_buffer); +} + +DataTransfer::BufferPtr::SharedCloneType DataTransfer::BufferPtr::any_clone_cast() const { + return std::any_cast(internal_buffer_); +} + +void DataTransfer::BufferPtr::reset() noexcept { + internal_buffer_ = {}; + buffer_data_ = nullptr; + buffer_size_ = 0; +} } // namespace Metavision diff --git a/hal/cpp/src/utils/device_config.cpp b/hal/cpp/src/utils/device_config.cpp index be0fc8091..d15b72665 100644 --- a/hal/cpp/src/utils/device_config.cpp +++ b/hal/cpp/src/utils/device_config.cpp @@ -208,21 +208,6 @@ void DeviceConfig::set_format(const std::string &format) { set(get_format_key(), format); } -// deprecated : forward call -std::string DeviceConfig::get_evt_format_key() { - return get_format_key(); -} - -// deprecated : forward call -std::string DeviceConfig::evt_format() const { - return format(); -} - -// deprecated : forward call -void DeviceConfig::set_evt_format(const std::string &format) { - set_format(format); -} - std::string DeviceConfig::get_biases_range_check_bypass_key() { return "ll_biases_range_check_bypass"; } diff --git a/hal/cpp/src/utils/file_data_transfer.cpp b/hal/cpp/src/utils/file_raw_data_producer.cpp similarity index 76% rename from hal/cpp/src/utils/file_data_transfer.cpp rename to hal/cpp/src/utils/file_raw_data_producer.cpp index 97045850f..6a9d4701f 100644 --- a/hal/cpp/src/utils/file_data_transfer.cpp +++ b/hal/cpp/src/utils/file_raw_data_producer.cpp @@ -9,21 +9,15 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include -#include -#include - -#include "metavision/hal/utils/hal_log.h" +#include "metavision/hal/utils/data_transfer.h" #include "metavision/hal/utils/hal_exception.h" -#include "metavision/hal/utils/file_data_transfer.h" +#include "metavision/hal/utils/file_raw_data_producer.h" namespace Metavision { -FileDataTransfer::FileDataTransfer(std::unique_ptr stream, uint32_t raw_event_size_bytes, - const RawFileConfig &config) : - DataTransfer(raw_event_size_bytes, BufferPool::make_bounded(std::max(4u, config.n_read_buffers_))), - seeking_(false), - stream_to_read_(std::move(stream)) { +FileRawDataProducer::FileRawDataProducer(std::unique_ptr stream, uint32_t raw_event_size_bytes, + const RawFileConfig &config, DataTransfer::DefaultBufferPool pool) : + buffer_pool_(pool), seeking_(false), stream_to_read_(std::move(stream)) { // Constraint on the configuration if (raw_event_size_bytes == 0) { throw HalException(HalErrorCode::InvalidArgument, "RAW event byte size must be greater than 0."); @@ -34,7 +28,7 @@ FileDataTransfer::FileDataTransfer(std::unique_ptr stream, uint32_ "events to read per read iteration must be greater than 0."); } - read_bytes_size_ = config.n_events_to_read_ * get_raw_event_size_bytes(); + read_bytes_size_ = config.n_events_to_read_ * raw_event_size_bytes; data_start_pos_ = stream_to_read_->tellg(); stream_to_read_->seekg(0, std::ios::end); @@ -43,14 +37,10 @@ FileDataTransfer::FileDataTransfer(std::unique_ptr stream, uint32_ stream_to_read_->clear(); stream_to_read_->seekg(data_start_pos_); - seek_buffer_ = get_buffer(); -} - -FileDataTransfer::~FileDataTransfer() { - stop(); + seek_buffer_ = buffer_pool_.acquire(); } -bool FileDataTransfer::seek(const std::streampos &target_position) { +bool FileRawDataProducer::seek(const std::streampos &target_position) { // If input position is outside the seek range in the stream if (target_position < data_start_pos_ || target_position > data_end_pos_) { return false; @@ -59,17 +49,15 @@ bool FileDataTransfer::seek(const std::streampos &target_position) { return seek_impl(target_position); } -void FileDataTransfer::get_seek_range(std::streampos &data_start_pos, std::streampos &data_end_pos) const { +void FileRawDataProducer::get_seek_range(std::streampos &data_start_pos, std::streampos &data_end_pos) const { data_start_pos = data_start_pos_; data_end_pos = data_end_pos_; } -void FileDataTransfer::start_impl(BufferPtr buffer) { - data_read_ = buffer; -} +void FileRawDataProducer::start_impl() {} -void FileDataTransfer::run_impl() { - while (!should_stop()) { +void FileRawDataProducer::run_impl(const DataTransfer &data_transfer) { + while (!data_transfer.should_stop()) { { std::unique_lock lock(seek_mutex_); seek_cond_.wait(lock, [this] { return !seeking_; }); @@ -77,16 +65,17 @@ void FileDataTransfer::run_impl() { if (!seek_buffer_) { // make sure we always have one buffer of slack to unblock any pending transfer // while trying to perform an operation that could invalidate the stream - seek_buffer_ = get_buffer(); + seek_buffer_ = buffer_pool_.acquire(); } } { std::lock_guard lock(stream_mutex_); - data_read_->resize(read_bytes_size_); // Does not reallocate if enough memory already allocated. + auto data_read = buffer_pool_.acquire(); + data_read->resize(read_bytes_size_); // Does not reallocate if enough memory already allocated. - stream_to_read_->read(reinterpret_cast(data_read_->data()), read_bytes_size_); + stream_to_read_->read(reinterpret_cast(data_read->data()), read_bytes_size_); // get size of what have been read (in bytes) auto count = stream_to_read_->gcount(); @@ -96,9 +85,8 @@ void FileDataTransfer::run_impl() { if (count > 0) { // If something has been read, transfer the data - data_read_->resize(count); - auto next_data_read = transfer_data(data_read_); - data_read_ = next_data_read.first; + data_read->resize(count); + data_transfer.transfer_data(data_read); } else if (!good) { // Otherwise stop break; @@ -107,7 +95,7 @@ void FileDataTransfer::run_impl() { } } -bool FileDataTransfer::seek_impl(const std::streampos &target_position) { +bool FileRawDataProducer::seek_impl(const std::streampos &target_position) { // we need to do free at least one buffer in the pool to unblock an ongoing transfer (if any) // otherwise, we could deadlock waiting for the mutex to be freed after the transfer completes { diff --git a/hal/cpp/src/utils/resources_folder.cpp b/hal/cpp/src/utils/resources_folder.cpp index 5253a255d..73c8bb637 100644 --- a/hal/cpp/src/utils/resources_folder.cpp +++ b/hal/cpp/src/utils/resources_folder.cpp @@ -12,10 +12,6 @@ #ifdef _WIN32 #include #include -#else -#include -#include -#include #endif #include @@ -48,13 +44,6 @@ std::string read_registry_subkey_hklm(LPCSTR subkey, LPCSTR registry_value_name) } return result; } -#else - -bool exists(const std::string &name) { - struct stat buffer; - return (stat(name.c_str(), &buffer) == 0); -} - #endif } /* anonymous namespace */ @@ -93,57 +82,45 @@ std::filesystem::path ResourcesFolder::get_user_path() { } #endif -std::string ResourcesFolder::get_install_path() { +std::filesystem::path ResourcesFolder::get_install_path() { char *p = getenv("MV_HAL_INSTALL_PATH"); if (p) { return p; } + std::filesystem::path parent_dir; #ifdef _WIN32 - return read_registry_subkey_hklm(METAVISION_SUBKEY, METAVISION_SUBKEY_INSTALL_PATH) + "\\" + - HAL_INSTALL_SUPPORT_RELATIVE_PATH; + parent_dir = read_registry_subkey_hklm(METAVISION_SUBKEY, METAVISION_SUBKEY_INSTALL_PATH); #else - auto path_candidates = Metavision::get_root_installation_path_candidates(); for (auto &candidate : path_candidates) { - if (exists(candidate + "/" + Metavision::METAVISION_HAL_LIB_RELATIVE_PATH)) { - return candidate + "/" + HAL_INSTALL_SUPPORT_RELATIVE_PATH; + if (std::filesystem::exists(candidate / Metavision::METAVISION_HAL_LIB_RELATIVE_PATH)) { + parent_dir = candidate; } } - return ""; + if (parent_dir.empty()) { + return ""; + } #endif + + return parent_dir / HAL_INSTALL_SUPPORT_RELATIVE_PATH; } -std::string ResourcesFolder::get_plugin_install_path() { +std::filesystem::path ResourcesFolder::get_plugin_install_path() { #ifdef _WIN32 - return read_registry_subkey_hklm(METAVISION_SUBKEY, METAVISION_SUBKEY_INSTALL_PATH) + "\\" + + return std::filesystem::path(read_registry_subkey_hklm(METAVISION_SUBKEY, METAVISION_SUBKEY_INSTALL_PATH)) / HAL_INSTALL_PLUGIN_RELATIVE_PATH; #else auto path_candidates = Metavision::get_root_installation_path_candidates(); for (auto &path_candidate : path_candidates) { - std::string candidate = path_candidate + "/" + Metavision::HAL_INSTALL_PLUGIN_RELATIVE_PATH; - if (exists(candidate)) { - // Check if folder is empty or not - DIR *dir_descriptor; - dir_descriptor = opendir(candidate.c_str()); - if (dir_descriptor) { - struct dirent *entries; - // Loop over the contents of the directory, to make sure that it's not empty and that it doesn't contain - // only subdirectories - // Remark : readdir() doesn't guarantee a specific order, so we loop over the all directory - while ((entries = readdir(dir_descriptor)) != NULL) { - // Verify that the entry is not a directory - struct stat statbuf; - bool is_dir = false; - if (stat(entries->d_name, &statbuf) == 0) { - is_dir = S_ISDIR(statbuf.st_mode); - } - if (!is_dir) { - closedir(dir_descriptor); - return candidate; - } + std::filesystem::path candidate = path_candidate / Metavision::HAL_INSTALL_PLUGIN_RELATIVE_PATH; + if (std::filesystem::is_directory(candidate)) { + // Loop over the contents of the directory, to make sure that it's not empty and that it doesn't contain + // only subdirectories + for (auto const &dir_entry : std::filesystem::directory_iterator(candidate)) { + if (!dir_entry.is_directory()) { + return candidate; } - closedir(dir_descriptor); } } } diff --git a/hal/cpp/test/CMakeLists.txt b/hal/cpp/test/CMakeLists.txt index b6ac7e2fc..22ac027bb 100644 --- a/hal/cpp/test/CMakeLists.txt +++ b/hal/cpp/test/CMakeLists.txt @@ -23,10 +23,11 @@ set(metavision_hal_tests_src ${CMAKE_CURRENT_SOURCE_DIR}/i_roi_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tencoder_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/timer_high_encoder_gtest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/dummy_test_plugin_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_ll_biases_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/decoders_evt21_decoder_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/decoders_evt3_decoder_gtest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/decoders_evt4_decoder_gtest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/data_transfer_gtest.cpp ) add_executable(gtest_metavision_hal ${metavision_hal_tests_src}) @@ -55,6 +56,6 @@ add_custom_command(TARGET hal_dummy_test_plugin POST_BUILD add_dependencies(gtest_metavision_hal hal_dummy_test_plugin) # Until we execute ctest in docker on Windows, the embedded paths to resources used in the code -# can not be absolute. Here the path is relative to the working directory of the test (which is the +# can not be absolute. Here the path is relative to the working directory of the test (which is the # current binary dir). target_compile_definitions(gtest_metavision_hal PRIVATE HAL_DUMMY_TEST_PLUGIN="plugins") diff --git a/hal/cpp/test/decoders_evt21_decoder_gtest.cpp b/hal/cpp/test/decoders_evt21_decoder_gtest.cpp index 973b9e74d..cf070c5ae 100644 --- a/hal/cpp/test/decoders_evt21_decoder_gtest.cpp +++ b/hal/cpp/test/decoders_evt21_decoder_gtest.cpp @@ -11,6 +11,7 @@ #include "metavision/hal/decoders/evt21/evt21_decoder.h" #include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/events/event_cd_vector.h" #include #include @@ -18,11 +19,15 @@ using namespace Metavision; using namespace ::testing; -using EventCdDecoder = I_EventDecoder; +template +using EventCdDecoder = I_EventDecoder; + using EventExtDecoder = I_EventDecoder; using EventErcDecoder = I_EventDecoder; -using EventCdBuffer = std::vector; +template +using EventCdBuffer = std::vector; + using EventExtBuffer = std::vector; using EventErcBuffer = std::vector; @@ -47,11 +52,14 @@ uint64_t event_2d(uint16_t x, uint16_t y, uint8_t ts, bool pol, uint32_t valid_v return *reinterpret_cast(&e_2d); } -using DecodedBuffers = std::tuple; +template +using DecodedBuffers = std::tuple, EventExtBuffer, EventErcBuffer>; -DecodedBuffers decode_buffer(DataBuffer &data, I_Decoder &decoder, EventCdDecoder &event_cd_decoder, - EventExtDecoder &event_ext_decoder, EventErcDecoder &event_erc_decoder) { - std::vector event_cd_buffer; +template +DecodedBuffers decode_buffer(DataBuffer &data, I_Decoder &decoder, + EventCdDecoder &event_cd_decoder, + EventExtDecoder &event_ext_decoder, EventErcDecoder &event_erc_decoder) { + std::vector event_cd_buffer; auto cb_cb_id = event_cd_decoder.add_event_buffer_callback( [&](auto beg, auto end) { std::copy(beg, end, std::back_inserter(event_cd_buffer)); }); @@ -76,31 +84,36 @@ TEST(Evt21_decoder, should_construct_evt21_decoder) { EXPECT_NO_THROW((EVT21Decoder{false})); } +TEST(Evt21_vector_decoder, should_construct_evt21_vector_decoder) { + EXPECT_NO_THROW((EVT21VectorizedDecoder{false})); +} + struct Evt21DecoderTest : public ::testing::Test { - std::shared_ptr event_cd_decoder = std::make_shared(); - std::shared_ptr event_ext_decoder = std::make_shared(); - std::shared_ptr event_erc_decoder = std::make_shared(); + std::shared_ptr> event_cd_decoder = std::make_shared>(); + std::shared_ptr event_ext_decoder = std::make_shared(); + std::shared_ptr event_erc_decoder = std::make_shared(); EVT21Decoder decoder{false, event_cd_decoder, event_ext_decoder, event_erc_decoder}; - DecodedBuffers decode(DataBuffer &&data) { - return decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + DecodedBuffers decode(DataBuffer &&data) { + return decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); } template T decode(DataBuffer &&data) { - auto events_buffers = decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + auto events_buffers = + decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); return std::get(events_buffers); } }; TEST_F(Evt21DecoderTest, should_decode_empty_evt21_stream) { - auto events = decode({}); + auto events = decode>({}); EXPECT_EQ(events.size(), 0); } TEST_F(Evt21DecoderTest, should_decode_basic_evt21_stream) { - auto events = decode({ + auto events = decode>({ time_high(0), event_2d(2, 1, 0, false), event_2d(3, 1, 0, true), @@ -116,7 +129,7 @@ TEST_F(Evt21DecoderTest, should_decode_basic_evt21_stream) { } TEST_F(Evt21DecoderTest, should_drop_events_before_1st_timehigh) { - auto events = decode({ + auto events = decode>({ event_2d(2, 1, 0, false), time_high(3), event_2d(5, 4, 0, false), @@ -130,7 +143,7 @@ TEST_F(Evt21DecoderTest, should_drop_events_before_1st_timehigh) { } TEST_F(Evt21DecoderTest, should_decode_event_vect) { - auto events = decode({ + auto events = decode>({ time_high(0), event_2d(5, 4, 0, false, 1 << 7 | 1 << 3 | 1), event_2d(10, 6, 0, true, 1 << 14 | 1 << 10 | 1 << 4), @@ -145,7 +158,7 @@ TEST_F(Evt21DecoderTest, should_decode_event_vect) { } TEST_F(Evt21DecoderTest, should_decode_event_timestamps) { - auto events = decode({ + auto events = decode>({ time_high(0), event_2d(5, 4, 5, false), event_2d(10, 6, 20, true), @@ -166,7 +179,7 @@ TEST_F(Evt21DecoderTest, should_decode_event_timestamps) { } TEST_F(Evt21DecoderTest, should_decode_event_timestamp_loop) { - auto events = decode({ + auto events = decode>({ time_high(0), event_2d(5, 4, 5, false), time_high((1ULL << 28) - 1), @@ -190,7 +203,7 @@ TEST_F(Evt21DecoderTest, should_decode_event_timestamp_loop) { TEST_F(Evt21DecoderTest, should_decode_negative_32bit_as_unsigned_timehigh) { // Timehigh with bit 25 set creates a timestamp with bit 32 set which is a negative value for signed ints - auto events = decode({ + auto events = decode>({ time_high(1ULL << 25), event_2d(5, 4, 5, false), }); @@ -202,3 +215,121 @@ TEST_F(Evt21DecoderTest, should_decode_negative_32bit_as_unsigned_timehigh) { EXPECT_THAT(events, ContainerEq(expected_events)); } + +struct Evt21VectorDecoderTest : public ::testing::Test { + std::shared_ptr> event_cd_decoder = std::make_shared>(); + std::shared_ptr event_ext_decoder = std::make_shared(); + std::shared_ptr event_erc_decoder = std::make_shared(); + + EVT21VectorizedDecoder decoder{false, event_cd_decoder, event_ext_decoder, event_erc_decoder}; + + DecodedBuffers decode(DataBuffer &&data) { + return decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + } + + template + T decode(DataBuffer &&data) { + auto events_buffers = + decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + return std::get(events_buffers); + } +}; + +TEST_F(Evt21VectorDecoderTest, should_decode_empty_evt21_stream) { + auto events = decode>({}); + EXPECT_EQ(events.size(), 0); +} + +TEST_F(Evt21VectorDecoderTest, should_decode_basic_evt21_stream) { + auto events = decode>({ + time_high(0), + event_2d(2, 1, 0, false), + event_2d(3, 1, 0, true), + }); + + const std::vector expected_events = {// base_x, y, polarity, vector_mask, event_timestamp + {2, 1, false, 1U, 0}, + {3, 1, true, 1U, 0}}; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt21VectorDecoderTest, should_drop_events_before_1st_timehigh) { + auto events = decode>({ + event_2d(2, 1, 0, false), + time_high(3), + event_2d(5, 4, 0, false), + }); + + const std::vector expected_events = {// base_x, y, polarity, vector_mask, event_timestamp + {5, 4, false, 1U, 3 << 6}}; + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt21VectorDecoderTest, should_decode_event_vect) { + auto events = decode>({ + time_high(0), + event_2d(5, 4, 0, false, (1 << 7 | 1 << 3 | 1)), + event_2d(10, 6, 0, true, (1 << 14 | 1 << 10 | 1 << 4)), + }); + + const std::vector expected_events = {// base_x, y, polarity, vector_mask, event_timestamp + {5, 4, false, (1 << 7 | 1 << 3 | 1), 0}, + {10, 6, true, (1 << 14 | 1 << 10 | 1 << 4), 0}}; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt21VectorDecoderTest, should_decode_event_timestamps) { + auto events = decode>({ + time_high(0), + event_2d(5, 4, 5, false), + event_2d(10, 6, 20, true), + time_high(15), + event_2d(5, 4, 5, false), + event_2d(10, 6, 20, true), + }); + + const std::vector expected_events = {// base_x, y, polarity, vector_mask, event_timestamp + {5, 4, false, 1U, 5}, + {10, 6, true, 1U, 20}, + {5, 4, false, 1U, (15 << 6) + 5}, + {10, 6, true, 1U, (15 << 6) + 20}}; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt21VectorDecoderTest, should_decode_event_timestamp_loop) { + auto events = decode>({ + time_high(0), + event_2d(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high(0), + event_2d(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high(0), + event_2d(5, 4, 5, false), + }); + + const std::vector expected_events = {// base_x, y, polarity, vector_mask, event_timestamp + {5, 4, false, 1U, 5}, + {5, 4, false, 1U, (1ULL << 34) + 5}, + {5, 4, false, 1U, (2ULL << 34) + 5} + + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt21VectorDecoderTest, should_decode_negative_32bit_as_unsigned_timehigh) { + // Timehigh with bit 25 set creates a timestamp with bit 32 set which is a negative value for signed ints + auto events = decode>({ + time_high(1ULL << 25), + event_2d(5, 4, 5, false), + }); + + const std::vector expected_events = {// base_x, y, polarity, vector_mask, event_timestamp + {5, 4, false, 1U, ((1ULL << 25) << 6) + 5}}; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} diff --git a/hal/cpp/test/decoders_evt4_decoder_gtest.cpp b/hal/cpp/test/decoders_evt4_decoder_gtest.cpp new file mode 100644 index 000000000..4d86a264c --- /dev/null +++ b/hal/cpp/test/decoders_evt4_decoder_gtest.cpp @@ -0,0 +1,727 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/hal/decoders/base/event_base.h" +#include "metavision/hal/decoders/evt4/evt4_decoder.h" +#include "metavision/sdk/base/events/event_cd.h" + +#include +#include +#include +#include + +namespace Evt4Test { + +using namespace Metavision; +using namespace ::testing; + +using EventCdDecoder = I_EventDecoder; +using EventExtDecoder = I_EventDecoder; +using EventErcDecoder = I_EventDecoder; + +using EventCdBuffer = std::vector; +using EventExtBuffer = std::vector; +using EventErcBuffer = std::vector; + +using DataBuffer = std::vector; + +I_Decoder::RawData const *const begin(DataBuffer &buff) { + return reinterpret_cast(buff.data()); +} + +I_Decoder::RawData const *const end(DataBuffer &buff) { + return reinterpret_cast(buff.data() + buff.size()); +} + +std::uint32_t time_high(std::uint32_t time = 0) { + EventBase::RawEvent ev_time{time, static_cast(EVT4EventTypes::EVT_TIME_HIGH)}; + return *reinterpret_cast(&ev_time); +} + +std::uint32_t event_cd(std::uint16_t x, std::uint16_t y, std::uint8_t ts, bool pol) { + Evt4Raw::EVT4EventCD ev_cd{y, x, ts, std::uint32_t(pol ? EVT4EventTypes::CD_ON : EVT4EventTypes::CD_OFF)}; + return *reinterpret_cast(&ev_cd); +} + +std::uint32_t event_cd_vec(std::uint16_t x, std::uint16_t y, std::uint8_t ts, bool pol) { + Evt4Raw::EVT4EventCD ev_cd_vec{y, x, ts, + std::uint32_t(pol ? EVT4EventTypes::CD_VEC_ON : EVT4EventTypes::CD_VEC_OFF)}; + return *reinterpret_cast(&ev_cd_vec); +} + +std::uint32_t event_cd_vec_mask(std::uint32_t valid) { + return valid; +} + +std::uint32_t padding() { + return 0xFFFFFFFF; +} + +std::uint32_t raw_event(EVT4EventTypes raw_event_type, std::uint32_t data) { + EventBase::RawEvent raw{data, static_cast(raw_event_type)}; + return *reinterpret_cast(&raw); +} + +std::uint32_t raw_event(std::uint32_t raw_event_type, std::uint32_t data) { + EventBase::RawEvent raw{data, raw_event_type}; + return *reinterpret_cast(&raw); +} + +using DecodedBuffers = std::tuple; + +DecodedBuffers decode_buffer(DataBuffer &data, I_Decoder &decoder, EventCdDecoder &event_cd_decoder, + EventExtDecoder &event_ext_decoder, EventErcDecoder &event_erc_decoder) { + std::vector event_cd_buffer; + auto cb_cb_id = event_cd_decoder.add_event_buffer_callback( + [&](auto beg, auto end) { std::copy(beg, end, std::back_inserter(event_cd_buffer)); }); + + std::vector event_ext_buffer; + auto ext_cb_id = event_ext_decoder.add_event_buffer_callback( + [&](auto beg, auto end) { std::copy(beg, end, std::back_inserter(event_ext_buffer)); }); + + std::vector event_erc_buffer; + auto erc_cb_id = event_erc_decoder.add_event_buffer_callback( + [&](auto beg, auto end) { std::copy(beg, end, std::back_inserter(event_erc_buffer)); }); + + decoder.decode(begin(data), end(data)); + + event_cd_decoder.remove_callback(cb_cb_id); + event_ext_decoder.remove_callback(ext_cb_id); + event_erc_decoder.remove_callback(erc_cb_id); + + return std::make_tuple(event_cd_buffer, event_ext_buffer, event_erc_buffer); +} + +TEST(Evt4Decoder, should_construct_evt4_decoder) { + EXPECT_NO_THROW((EVT4Decoder{false})); +} + +struct Evt4DecoderTest : public ::testing::Test { + std::shared_ptr event_cd_decoder = std::make_shared(); + std::shared_ptr event_ext_decoder = std::make_shared(); + std::shared_ptr event_erc_decoder = std::make_shared(); + + EVT4Decoder decoder{false, std::nullopt, std::nullopt, event_cd_decoder, event_ext_decoder, event_erc_decoder}; + + DecodedBuffers decode(DataBuffer &&data) { + return decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + } + + template + T decode(DataBuffer &&data) { + auto events_buffers = decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + return std::get(events_buffers); + } +}; + +TEST_F(Evt4DecoderTest, should_decode_empty_evt4_stream) { + auto events = decode({}); + EXPECT_EQ(events.size(), 0); +} + +TEST_F(Evt4DecoderTest, should_decode_basic_evt4_stream) { + auto events = decode({ + time_high(0), + event_cd(3, 2, 0, false), + event_cd(6, 5, 0, true), + }); + + const std::vector expected_events = { + // x, y, p, t + {3, 2, 0, 0}, + {6, 5, 1, 0}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt4DecoderTest, should_drop_events_before_1st_timehigh) { + auto events = decode({ + event_cd(3, 2, 1, false), + event_cd(6, 5, 4, true), + event_cd_vec(9, 8, 7, false), + event_cd_vec_mask(0x11), + event_cd_vec(12, 11, 10, true), + event_cd_vec_mask(0x22), + time_high(3), + event_cd(5, 4, 1, false), + event_cd(7, 6, 2, true), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, (3 << 6) + 1}, + {7, 6, 1, (3 << 6) + 2}, + }; + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt4DecoderTest, should_decode_event_vect) { + auto events = decode({ + time_high(0), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 6, 0, true), + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 0}, {5 + 3, 4, 0, 0}, {5 + 7, 4, 0, 0}, {10 + 4, 6, 1, 0}, {10 + 10, 6, 1, 0}, {10 + 14, 6, 1, 0}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt4DecoderTest, should_decode_event_timestamps) { + auto events = decode({ + time_high(0), + event_cd(5, 4, 5, false), + event_cd(10, 6, 20, true), + time_high(15), + event_cd(5, 4, 5, false), + event_cd(10, 6, 20, true), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 5}, + {10, 6, 1, 20}, + {5, 4, 0, (15 << 6) + 5}, + {10, 6, 1, (15 << 6) + 20}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt4DecoderTest, should_decode_event_timestamp_loop) { + auto events = decode({ + time_high(0), + event_cd(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high((1ULL << 28) - 1), + time_high(0), + event_cd(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high((1ULL << 28) - 1), + time_high(0), + event_cd(5, 4, 5, false), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 5}, + {5, 4, 0, (1ULL << 34) + 5}, + {5, 4, 0, (2ULL << 34) + 5}, + + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt4DecoderTest, should_decode_negative_32bit_as_unsigned_timehigh) { + // Timehigh with bit 25 set creates a timestamp with bit 32 set which is a negative value for signed ints + auto events = decode({ + time_high(1ULL << 25), + event_cd(5, 4, 5, false), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, ((1ULL << 25) << 6) + 5}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(Evt4DecoderTest, should_decode_cd_vec_accross_multiple_calls) { + auto events_1 = decode({ + time_high(0), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 6, 0, true), + }); + EXPECT_EQ(events_1.size(), 3); + + auto events_2 = decode({ + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + event_cd_vec(15, 8, 0, false), + event_cd_vec_mask(1 << 21 | 1 << 17 | 8), + }); + EXPECT_EQ(events_2.size(), 6); +} + +TEST_F(Evt4DecoderTest, should_skip_padding) { + auto events = decode({ + padding(), + time_high(0), + padding(), + event_cd(3, 2, 0, false), + padding(), + event_cd(6, 5, 0, true), + padding(), + }); + EXPECT_EQ(events.size(), 2); +} + +TEST_F(Evt4DecoderTest, should_skip_unknown_type) { + auto events = decode({ + raw_event(1, 0), + time_high(0), + raw_event(3, 2), + event_cd(3, 2, 0, false), + raw_event(5, 4), + event_cd(6, 5, 0, true), + padding(), + }); + EXPECT_EQ(events.size(), 2); +} + +TEST(UnsafeEVT4Decoder, should_construct_evt4_decoder) { + EXPECT_NO_THROW((UnsafeEVT4Decoder{false})); +} + +struct UnsafeEvt4DecoderTest : public ::testing::Test { + std::shared_ptr event_cd_decoder = std::make_shared(); + std::shared_ptr event_ext_decoder = std::make_shared(); + std::shared_ptr event_erc_decoder = std::make_shared(); + + UnsafeEVT4Decoder decoder{ + false, std::nullopt, std::nullopt, event_cd_decoder, event_ext_decoder, event_erc_decoder}; + + DecodedBuffers decode(DataBuffer &&data) { + return decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + } + + template + T decode(DataBuffer &&data) { + auto events_buffers = decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + return std::get(events_buffers); + } +}; + +TEST_F(UnsafeEvt4DecoderTest, should_decode_empty_evt4_stream) { + auto events = decode({}); + EXPECT_EQ(events.size(), 0); +} + +TEST_F(UnsafeEvt4DecoderTest, should_decode_basic_evt4_stream) { + auto events = decode({ + time_high(0), + event_cd(3, 2, 0, false), + event_cd(6, 5, 0, true), + }); + + const std::vector expected_events = { + // x, y, p, t + {3, 2, 0, 0}, + {6, 5, 1, 0}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(UnsafeEvt4DecoderTest, should_drop_events_before_1st_timehigh) { + auto events = decode({ + event_cd(3, 2, 1, false), + event_cd(6, 5, 4, true), + event_cd_vec(9, 8, 7, false), + event_cd_vec_mask(0x11), + event_cd_vec(12, 11, 10, true), + event_cd_vec_mask(0x22), + time_high(3), + event_cd(5, 4, 1, false), + event_cd(7, 6, 2, true), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, (3 << 6) + 1}, + {7, 6, 1, (3 << 6) + 2}, + }; + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(UnsafeEvt4DecoderTest, should_decode_event_vect) { + auto events = decode({ + time_high(0), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 6, 0, true), + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 0}, {5 + 3, 4, 0, 0}, {5 + 7, 4, 0, 0}, {10 + 4, 6, 1, 0}, {10 + 10, 6, 1, 0}, {10 + 14, 6, 1, 0}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(UnsafeEvt4DecoderTest, should_decode_event_timestamps) { + auto events = decode({ + time_high(0), + event_cd(5, 4, 5, false), + event_cd(10, 6, 20, true), + time_high(15), + event_cd(5, 4, 5, false), + event_cd(10, 6, 20, true), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 5}, + {10, 6, 1, 20}, + {5, 4, 0, (15 << 6) + 5}, + {10, 6, 1, (15 << 6) + 20}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(UnsafeEvt4DecoderTest, should_decode_event_timestamp_loop) { + auto events = decode({ + time_high(0), + event_cd(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high(0), + event_cd(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high(0), + event_cd(5, 4, 5, false), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 5}, + {5, 4, 0, (1ULL << 34) + 5}, + {5, 4, 0, (2ULL << 34) + 5}, + + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(UnsafeEvt4DecoderTest, should_decode_negative_32bit_as_unsigned_timehigh) { + // Timehigh with bit 25 set creates a timestamp with bit 32 set which is a negative value for signed ints + auto events = decode({ + time_high(1ULL << 25), + event_cd(5, 4, 5, false), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, ((1ULL << 25) << 6) + 5}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(UnsafeEvt4DecoderTest, should_decode_cd_vec_accross_multiple_calls) { + auto events_1 = decode({ + time_high(0), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 6, 0, true), + }); + EXPECT_EQ(events_1.size(), 3); + + auto events_2 = decode({ + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + event_cd_vec(15, 8, 0, false), + event_cd_vec_mask(1 << 21 | 1 << 17 | 8), + }); + EXPECT_EQ(events_2.size(), 6); +} + +TEST_F(UnsafeEvt4DecoderTest, should_skip_padding) { + auto events = decode({ + padding(), + time_high(0), + padding(), + event_cd(3, 2, 0, false), + padding(), + event_cd(6, 5, 0, true), + padding(), + }); + EXPECT_EQ(events.size(), 2); +} + +TEST_F(UnsafeEvt4DecoderTest, should_skip_unknown_type) { + auto events = decode({ + raw_event(1, 0), + time_high(0), + raw_event(3, 2), + event_cd(3, 2, 0, false), + raw_event(5, 4), + event_cd(6, 5, 0, true), + padding(), + }); + EXPECT_EQ(events.size(), 2); +} + +TEST(RobustEvt4Decoder, should_construct_evt4_decoder) { + EXPECT_NO_THROW((RobustEVT4Decoder{false})); +} + +struct RobustEvt4DecoderTest : public ::testing::Test { + std::shared_ptr event_cd_decoder = std::make_shared(); + std::shared_ptr event_ext_decoder = std::make_shared(); + std::shared_ptr event_erc_decoder = std::make_shared(); + + RobustEVT4Decoder decoder{false, 1280, 720, event_cd_decoder, event_ext_decoder, event_erc_decoder}; + + DecodedBuffers decode(DataBuffer &&data) { + return decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + } + + template + T decode(DataBuffer &&data) { + auto events_buffers = decode_buffer(data, decoder, *event_cd_decoder, *event_ext_decoder, *event_erc_decoder); + return std::get(events_buffers); + } +}; + +TEST_F(RobustEvt4DecoderTest, should_decode_empty_evt4_stream) { + auto events = decode({}); + EXPECT_EQ(events.size(), 0); +} + +TEST_F(RobustEvt4DecoderTest, should_decode_basic_evt4_stream) { + auto events = decode({ + time_high(0), + event_cd(3, 2, 0, false), + event_cd(6, 5, 0, true), + }); + + const std::vector expected_events = { + // x, y, p, t + {3, 2, 0, 0}, + {6, 5, 1, 0}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(RobustEvt4DecoderTest, should_drop_events_before_1st_timehigh) { + auto events = decode({ + event_cd(3, 2, 1, false), + event_cd(6, 5, 4, true), + event_cd_vec(9, 8, 7, false), + event_cd_vec_mask(0x11), + event_cd_vec(12, 11, 10, true), + event_cd_vec_mask(0x22), + time_high(3), + event_cd(5, 4, 1, false), + event_cd(7, 6, 2, true), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, (3 << 6) + 1}, + {7, 6, 1, (3 << 6) + 2}, + }; + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(RobustEvt4DecoderTest, should_decode_event_vect) { + auto events = decode({ + time_high(0), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 6, 0, true), + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 0}, {5 + 3, 4, 0, 0}, {5 + 7, 4, 0, 0}, {10 + 4, 6, 1, 0}, {10 + 10, 6, 1, 0}, {10 + 14, 6, 1, 0}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(RobustEvt4DecoderTest, should_decode_event_timestamps) { + auto events = decode({ + time_high(0), + event_cd(5, 4, 5, false), + event_cd(10, 6, 20, true), + time_high(15), + event_cd(5, 4, 5, false), + event_cd(10, 6, 20, true), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 5}, + {10, 6, 1, 20}, + {5, 4, 0, (15 << 6) + 5}, + {10, 6, 1, (15 << 6) + 20}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(RobustEvt4DecoderTest, should_decode_event_timestamp_loop) { + auto events = decode({ + time_high(0), + event_cd(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high((1ULL << 28) - 1), + time_high(0), + event_cd(5, 4, 5, false), + time_high((1ULL << 28) - 1), + time_high((1ULL << 28) - 1), + time_high(0), + event_cd(5, 4, 5, false), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 5}, + {5, 4, 0, (1ULL << 34) + 5}, + {5, 4, 0, (2ULL << 34) + 5}, + + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(RobustEvt4DecoderTest, should_decode_negative_32bit_as_unsigned_timehigh) { + // Timehigh with bit 25 set creates a timestamp with bit 32 set which is a negative value for signed ints + auto events = decode({ + time_high(1ULL << 25), + event_cd(5, 4, 5, false), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, ((1ULL << 25) << 6) + 5}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(RobustEvt4DecoderTest, should_decode_cd_vec_accross_multiple_calls) { + auto events_1 = decode({ + time_high(0), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 6, 0, true), + }); + EXPECT_EQ(events_1.size(), 3); + + auto events_2 = decode({ + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + event_cd_vec(15, 8, 0, false), + event_cd_vec_mask(1 << 21 | 1 << 17 | 8), + }); + EXPECT_EQ(events_2.size(), 6); +} + +TEST_F(RobustEvt4DecoderTest, should_skip_padding) { + auto events = decode({ + padding(), + time_high(0), + padding(), + event_cd(3, 2, 0, false), + padding(), + event_cd(6, 5, 0, true), + padding(), + }); + EXPECT_EQ(events.size(), 2); +} + +TEST_F(RobustEvt4DecoderTest, should_skip_unknown_type) { + auto events = decode({ + raw_event(1, 0), + time_high(0), + raw_event(3, 2), + event_cd(3, 2, 0, false), + raw_event(5, 4), + event_cd(6, 5, 0, true), + padding(), + }); + EXPECT_EQ(events.size(), 2); +} + +TEST_F(RobustEvt4DecoderTest, should_skip_out_of_bouds_events) { + auto events = decode({ + time_high(0), + event_cd(2, 1, 0, false), + event_cd(4, 3, 0, true), + event_cd(1280, 1, 0, false), + event_cd(4, 720, 0, true), + padding(), + }); + EXPECT_EQ(events.size(), 2); +} + +TEST_F(RobustEvt4DecoderTest, should_skip_out_of_bouds_events_vect) { + auto events = decode({ + time_high(0), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 720, 0, true), + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + event_cd_vec(1280 - 31, 6, 0, true), + event_cd_vec_mask(1 << 21 | 1 << 17 | 1 << 8), + padding(), + }); + + const std::vector expected_events = { + // x. y, p, t + {5, 4, 0, 0}, + {5 + 3, 4, 0, 0}, + {5 + 7, 4, 0, 0}, + }; + + EXPECT_THAT(events, ContainerEq(expected_events)); +} + +TEST_F(RobustEvt4DecoderTest, should_skip_th_jump) { + auto events_1 = decode({ + time_high(0), + event_cd(2, 1, 0, false), + time_high(100), + event_cd(4, 3, 0, true), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + event_cd_vec(10, 720, 0, true), + }); + + auto events_2 = decode({ + event_cd_vec_mask(1 << 14 | 1 << 10 | 1 << 4), + time_high(100), + event_cd(6, 5, 0, true), + event_cd_vec(5, 4, 0, false), + event_cd_vec_mask(1 << 7 | 1 << 3 | 1), + }); + + const std::vector expected_events_1 = { + // x. y, p, t + {2, 1, 0, 0}, + }; + + const std::vector expected_events_2 = { + // x. y, p, t + {6, 5, 1, 6400}, + {5 + 0, 4, 0, 6400}, + {5 + 3, 4, 0, 6400}, + {5 + 7, 4, 0, 6400}, + }; + + EXPECT_THAT(events_1, ContainerEq(expected_events_1)); + EXPECT_THAT(events_2, ContainerEq(expected_events_2)); +} + +} // namespace Evt4Test diff --git a/hal/cpp/test/device_discovery_gtest.cpp b/hal/cpp/test/device_discovery_gtest.cpp index 560cb0306..0523c0d59 100644 --- a/hal/cpp/test/device_discovery_gtest.cpp +++ b/hal/cpp/test/device_discovery_gtest.cpp @@ -31,17 +31,13 @@ class DeviceDiscovery_GTest : public GTestWithTmpDir { rawfile_to_log_path_ = tmpdir_handler_->get_full_path("rawfile_" + std::to_string(++raw_counter) + ".raw"); } - void write_header(long system_id, RawFileHeader header_to_write = RawFileHeader()) { + void write_header(RawFileHeader header_to_write = RawFileHeader()) { std::ofstream rawfile_to_log(rawfile_to_log_path_, std::ios::out | std::ios::binary); if (!rawfile_to_log.is_open()) { std::cerr << "Could not open file for writing at " << rawfile_to_log_path_ << std::endl; FAIL(); } - // Psee custom field only. Duplicates what PseeRawFileHeader does for the sake of encoding/reading RAW file for - // the test - header_to_write.set_field("system_ID", std::to_string(system_id)); - rawfile_to_log << header_to_write; rawfile_to_log.close(); } @@ -75,11 +71,10 @@ TEST_F(DeviceDiscovery_GTest, open_rawfile_success_with_dummy_test_plugin) { const std::string plugin_integrator_name("__DummyTestPlugin__"); const std::string plugin_name("hal_dummy_test_plugin"); const std::string camera_integrator_name("__DummyTestCamera__"); - long dummy_system_id = 0; header.set_plugin_integrator_name(plugin_integrator_name); header.set_plugin_name(plugin_name); header.set_camera_integrator_name(camera_integrator_name); - write_header(dummy_system_id, header); + write_header(header); ASSERT_NO_THROW(device = DeviceDiscovery::open_raw_file(rawfile_to_log_path_)); I_HW_Identification *hw_id = device->get_facility(); @@ -119,11 +114,10 @@ TEST_F(DeviceDiscovery_GTest, open_rawfile_success_with_dummy_test_plugin_and_de const std::string plugin_integrator_name("__DummyTestPlugin__"); const std::string plugin_name("hal_dummy_test_plugin"); const std::string camera_integrator_name("__DummyTestCamera__"); - long dummy_system_id = 0; header.set_plugin_integrator_name(plugin_integrator_name); header.set_plugin_name(plugin_name); header.set_camera_integrator_name(camera_integrator_name); - write_header(dummy_system_id, header); + write_header(header); ASSERT_NO_THROW(device = DeviceDiscovery::open_raw_file(rawfile_to_log_path_)); I_HW_Identification *hw_id = device->get_facility(); ASSERT_EQ(camera_integrator_name, hw_id->get_integrator()); @@ -164,11 +158,10 @@ TEST_F(DeviceDiscovery_GTest, open_rawfile_success_with_dummy_test_plugin_and_pl const std::string plugin_integrator_name("__DummyTestPlugin__"); const std::string plugin_name("hal_dummy_test_plugin"); const std::string camera_integrator_name("__DummyTestCamera__"); - long dummy_system_id = 0; header.set_plugin_integrator_name(plugin_integrator_name); header.set_plugin_name(plugin_name); header.set_camera_integrator_name(camera_integrator_name); - write_header(dummy_system_id, header); + write_header(header); ASSERT_NO_THROW(device = DeviceDiscovery::open_raw_file(rawfile_to_log_path_)); I_HW_Identification *hw_id = device->get_facility(); ASSERT_EQ(camera_integrator_name, hw_id->get_integrator()); diff --git a/hal/cpp/test/dummy_raw_data_producer.h b/hal/cpp/test/dummy_raw_data_producer.h new file mode 100644 index 000000000..8099103e9 --- /dev/null +++ b/hal/cpp/test/dummy_raw_data_producer.h @@ -0,0 +1,52 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_TEST_DUMMY_RAW_DATA_PRODUCER_H +#define METAVISION_HAL_TEST_DUMMY_RAW_DATA_PRODUCER_H + +#include +#include + +#include "metavision/hal/utils/data_transfer.h" +#include "metavision/sdk/base/utils/object_pool.h" + +// This DataTransfer will transfer 255 values an incremental counter on buffers doubling length at each iteration +// as follows: {0}, {1, 2}, {3, 4, 5, 6}, {7, 8, 9, 10, 11, 12, 13, 14}, ... +// The DummyAllocator has no specific behavior and is just meant to check DataTransfer::Allocator properties + +using custom_vector = std::vector; + +struct DummyRawDataProducer : public Metavision::DataTransfer::RawDataProducer { + using Pool = Metavision::SharedObjectPool>; + Pool pool; + + DummyRawDataProducer() : pool(Pool::make_bounded(4)) {} + + virtual void run_impl(const Metavision::DataTransfer &data_transfer) override { + auto buff = pool.acquire(); + int size = 1; + int counter = 0; + + buff->reserve(128); + + for (int i = 0; (i < 8) && !data_transfer.should_stop(); i++) { + buff->resize(size); + for (auto &data : *buff) { + data = counter++; + } + data_transfer.transfer_data(buff); + size *= 2; + buff = pool.acquire(); + } + } +}; + +#endif // METAVISION_HAL_TEST_DUMMY_RAW_DATA_PRODUCER_H diff --git a/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp b/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp index fed770bf0..e88926efa 100644 --- a/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp +++ b/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp @@ -33,13 +33,13 @@ #include "metavision/hal/facilities/i_trigger_out.h" #include "metavision/hal/plugin/plugin.h" #include "metavision/hal/plugin/plugin_entrypoint.h" -#include "metavision/hal/utils/data_transfer.h" #include "metavision/hal/utils/device_builder.h" #include "metavision/hal/utils/file_discovery.h" #include "metavision/hal/utils/hal_software_info.h" #include #include "dummy_test_plugin_facilities.h" +#include "dummy_raw_data_producer.h" using namespace Metavision; @@ -95,12 +95,6 @@ struct DummyROI : public I_ROI { std::vector rows_, cols_; }; -struct DummyDataTransfer : public DataTransfer { - DummyDataTransfer() : DataTransfer(1) {} - - virtual void run_impl() override {} -}; - struct DummyFileHWIdentification : public I_HW_Identification { DummyFileHWIdentification(const std::shared_ptr &plugin_sw_info, const RawFileHeader &header) : @@ -110,10 +104,6 @@ struct DummyFileHWIdentification : public I_HW_Identification { return std::string(); } - long get_system_id() const { - return 0; - } - SensorInfo get_sensor_info() const { return SensorInfo({0, 0, "Gen0.0"}); } @@ -462,9 +452,6 @@ class DummyHWIdentification : public I_HW_Identification { return ""; } - virtual long get_system_id() const override { - return 0; - } virtual SensorInfo get_sensor_info() const override { return SensorInfo(); } @@ -654,16 +641,6 @@ struct DummyNFLModule : public I_EventRateActivityFilterModule { return enabled_; } - virtual bool set_event_rate_threshold(uint32_t threshold) override { - threshold_ = threshold; - thresholds_.lower_bound_start = threshold; - return true; - } - - virtual uint32_t get_event_rate_threshold() const override { - return threshold_; - } - virtual thresholds is_thresholds_supported() const override { return {1, 1, 1, 1}; } @@ -697,7 +674,7 @@ struct DummyCameraDiscovery : public CameraDiscovery { return SerialList{"__DummyTest__"}; } SystemList list_available_sources() override final { - return SystemList{PluginCameraDescription{"__DummyTest__", ConnectionType::PROPRIETARY_LINK, 4321}}; + return SystemList{PluginCameraDescription{"__DummyTest__", ConnectionType::PROPRIETARY_LINK}}; } bool discover(DeviceBuilder &device_builder, const std::string &serial, const DeviceConfig &config) override final { device_builder.add_facility(std::make_unique()); @@ -717,7 +694,7 @@ struct DummyCameraDiscovery : public CameraDiscovery { device_builder.add_facility(std::make_unique(device_builder.get_plugin_software_info())); device_builder.add_facility(std::make_unique(640, 480)); device_builder.add_facility(std::make_unique( - std::make_unique(), + std::make_unique(), std::make_unique(device_builder.get_plugin_software_info()))); device_builder.add_facility(make_evt3_decoder(false, 640, 480)); device_builder.add_facility(std::make_unique()); diff --git a/hal/cpp/test/dummy_test_plugin_gtest.cpp b/hal/cpp/test/dummy_test_plugin_gtest.cpp index b7d863568..55e2758f8 100644 --- a/hal/cpp/test/dummy_test_plugin_gtest.cpp +++ b/hal/cpp/test/dummy_test_plugin_gtest.cpp @@ -78,4 +78,44 @@ TEST_F(DummyTestPluginTest, should_have_facilities_multi_version_facility) { EXPECT_THAT(dummy_device->get_facility(), NotNull()); EXPECT_EQ(dummy_device->get_facility(), dummy_device->get_facility()); EXPECT_EQ(dummy_device->get_facility(), dummy_device->get_facility()); -} \ No newline at end of file +} + +TEST_F(DummyTestPluginTest, should_stream) { + // DummyRawDataProducer generates an incrementing pattern + int counter = 0; + auto event_stream = dummy_device->get_facility(); + EXPECT_THAT(event_stream, NotNull()); + + event_stream->start(); + + do { + // DummyRawDataProducer sends 8 buffers of up to 128 bytes + // it is assumed that this test will make DummyRawDataProducer run out of buffers + // (it has a bounded pool and can't drop) + // but this depends on runner's performances + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + auto buffer = event_stream->get_latest_raw_data(); + for (auto &data : buffer) { + EXPECT_EQ(data, counter++); + } + } while (event_stream->poll_buffer() > 0); + + // DummyRawDataProducer sends 255 values + EXPECT_EQ(counter, 255); + event_stream->stop(); +} + +TEST_F(DummyTestPluginTest, can_copy_buffers_outside_of_the_pool) { + auto event_stream = dummy_device->get_facility(); + EXPECT_THAT(event_stream, NotNull()); + + event_stream->start(); + + event_stream->wait_next_buffer(); + auto buffer = event_stream->get_latest_raw_data(); + event_stream->stop(); + + DataTransfer::BufferPtr outsider = buffer.clone(); + // A copy of a buffer shall be equal + EXPECT_EQ(buffer, outsider); +} diff --git a/hal/cpp/test/gtest_utils/event_encoder_impl.h b/hal/cpp/test/gtest_utils/event_encoder_impl.h index b9447f45d..dae32a71b 100644 --- a/hal/cpp/test/gtest_utils/event_encoder_impl.h +++ b/hal/cpp/test/gtest_utils/event_encoder_impl.h @@ -27,8 +27,8 @@ void EventEncoder::encode_event( // Default is Event CD ev_encoded->y = ev_decoded->y; ev_encoded->timestamp = ev_decoded->t; ev_encoded->type = ev_decoded->p ? - static_cast(event_raw_format_traits::EnumType::CD_HIGH) : - static_cast(event_raw_format_traits::EnumType::CD_LOW); + static_cast(event_raw_format_traits::EnumType::CD_ON) : + static_cast(event_raw_format_traits::EnumType::CD_OFF); } template<> diff --git a/hal/cpp/test/i_hw_identification_gtest.cpp b/hal/cpp/test/i_hw_identification_gtest.cpp index cf21681a7..d9464d4fe 100644 --- a/hal/cpp/test/i_hw_identification_gtest.cpp +++ b/hal/cpp/test/i_hw_identification_gtest.cpp @@ -49,13 +49,13 @@ TEST_F_WITH_CAMERA(I_HW_Identification_GTest, hd_get_available_data_encoding_for TEST_F_WITH_CAMERA(I_HW_Identification_GTest, hd_get_available_data_encoding_formats_psee_gen31, camera_params(camera_param().integrator("Prophesee").generation("3.1"))) { ASSERT_EQ(1, hw_id_->get_available_data_encoding_formats().size()); - if (hw_id_->get_system_id() == 0x28) { - ASSERT_EQ("EVT3", hw_id_->get_available_data_encoding_formats()[0]); - ASSERT_EQ("EVT3", hw_id_->get_current_data_encoding_format()); - } else { - ASSERT_EQ("EVT2", hw_id_->get_available_data_encoding_formats()[0]); - ASSERT_EQ("EVT2", hw_id_->get_current_data_encoding_format()); - } + auto available = hw_id_->get_available_data_encoding_formats()[0]; + auto current = hw_id_->get_current_data_encoding_format(); + + // Gen3.1 systems exist with either of these encodings + ASSERT_TRUE((available == "EVT2") || (available == "EVT3")); + ASSERT_TRUE((current == "EVT2") || (current == "EVT3")); + ASSERT_EQ(available, current); } TEST_F_WITH_CAMERA(I_HW_Identification_GTest, hd_get_available_data_encoding_formats_psee_gen4, diff --git a/hal/cpp/test/i_ll_biases_gtest.cpp b/hal/cpp/test/i_ll_biases_gtest.cpp index c7071d73d..71bfa0b00 100644 --- a/hal/cpp/test/i_ll_biases_gtest.cpp +++ b/hal/cpp/test/i_ll_biases_gtest.cpp @@ -9,6 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include #include #include @@ -314,3 +315,295 @@ TEST(Mock_LL_Biases_GTest, set_bypass_bias_range_check_diff_range) { EXPECT_EQ(0, info.get_bias_recommended_range().first); EXPECT_EQ(10, info.get_bias_recommended_range().second); } + +class Dummy_LL_Biases : public Metavision::I_LL_Biases { +public: + Dummy_LL_Biases(const Metavision::DeviceConfig &device_config, const std::map &biases_map) : + Metavision::I_LL_Biases(device_config), biases_map_(biases_map) {} + + ~Dummy_LL_Biases() override {} + + bool set_impl(const std::string &bias_name, int bias_value) override { + biases_map_[bias_name] = bias_value; + return true; + } + + int get_impl(const std::string &bias_name) const override { + return biases_map_.find(bias_name)->second; + } + + std::map get_all_biases() const override { + return biases_map_; + } + + bool get_bias_info_impl(const std::string &bias_name, Metavision::LL_Bias_Info &bias_info) const override { + auto it = biases_map_.find(bias_name); + if (it == biases_map_.end()) { + return false; + } + bias_info = + Metavision::LL_Bias_Info(std::numeric_limits::min(), std::numeric_limits::max(), "", true, ""); + return true; + } + + void set_biases_map(const std::map &biases_map) { + biases_map_ = biases_map; + } + +private: + std::map biases_map_; +}; + +class BiasFile_GTest : public Metavision::GTestWithTmpDir { +public: + void write_file(const std::string &filename, const std::string &contents) { + std::ofstream file_out(filename); + + ASSERT_TRUE(file_out.is_open()); + file_out << contents; + file_out.close(); + } + + void compare_biases(const std::map &expected_biases, const std::map &biases) { + ASSERT_EQ(expected_biases.size(), biases.size()); + for (auto it_exp = expected_biases.begin(), it_exp_end = expected_biases.end(), it = biases.begin(); + it_exp != it_exp_end; ++it_exp, ++it) { + EXPECT_EQ(it_exp->first, it->first); + EXPECT_EQ(it_exp->second, it->second); + } + } + +protected: + virtual void SetUp() override { + std::map biases_map = {{"bias_diff", -1}, {"bias_diff_off", -1}, {"bias_diff_on", -1}, + {"bias_fo", -1}, {"bias_hpf", -1}, {"bias_pr", -1}, + {"bias_refr", -1}}; + i_ll_biases_ = std::make_unique(Metavision::DeviceConfig(), biases_map); + } + + std::unique_ptr i_ll_biases_; +}; + + +TEST_F(BiasFile_GTest, load_from_file_compatible_with_legacy_format) { + // GIVEN a bias file with the legacy format + std::string contents = "% gen 3.1 CD standard biases\n" + "% characterization release 1.4\n" + "% subsystem_ID 2418019330\n" + "% gen 3.1 CD standard biases\n" + "% system_ID 28\n" + "300 % bias_diff % v\n" + "222 % bias_diff_off % v\n" + "385 % bias_diff_on % v\n" + "1480 % bias_fo % i\n" + "1450 % bias_hpf % i\n" + "1250 % bias_pr % i\n" + "1500 % bias_refr % i\n"; + std::string filename = tmpdir_handler_->get_full_path("input.bias"); + write_file(filename, contents); + + // WHEN we set the biases from file + try { + i_ll_biases_->load_from_file(filename); + } catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + ASSERT_NO_THROW(i_ll_biases_->load_from_file(filename)); + + // THEN the biases set in the HAL facility have the values written in the file + std::map biases_set = i_ll_biases_->get_all_biases(); + std::map expected_biases = {{"bias_diff", 300}, {"bias_diff_off", 222}, {"bias_diff_on", 385}, + {"bias_fo", 1480}, {"bias_hpf", 1450}, {"bias_pr", 1250}, + {"bias_refr", 1500}}; + + compare_biases(expected_biases, biases_set); +} + +TEST_F(BiasFile_GTest, load_from_file_with_current_format) { + // GIVEN a bias file like the ones we provide at installation + std::string contents = "299 % bias_diff\n" + "228 % bias_diff_off\n" + "370 % bias_diff_on\n" + "1507 % bias_fo\n" + "1499 % bias_hpf\n" + "1250 % bias_pr\n" + "1500 % bias_refr\n"; + std::string filename = tmpdir_handler_->get_full_path("input.bias"); + write_file(filename, contents); + + // WHEN we set the biases from file + ASSERT_NO_THROW(i_ll_biases_->load_from_file(filename)); + + // THEN the biases set in the HAL facility have the values written in the file + std::map biases_set = i_ll_biases_->get_all_biases(); + std::map expected_biases = {{"bias_diff", 299}, {"bias_diff_off", 228}, {"bias_diff_on", 370}, + {"bias_fo", 1507}, {"bias_hpf", 1499}, {"bias_pr", 1250}, + {"bias_refr", 1500}}; + compare_biases(expected_biases, biases_set); +} + +TEST_F(BiasFile_GTest, load_from_file_exa) { + // GIVEN a bias file with values in hexadecimal + std::string contents = "0x97 % bias_pr\n" + "0x17 % bias_fo\n" + "0x30 % bias_hpf\n" + "0x70 % bias_diff_on\n" + "0x45 % bias_diff\n" + "0x34 % bias_diff_off\n" + "0x2D % bias_refr\n"; + std::string filename = tmpdir_handler_->get_full_path("input.bias"); + write_file(filename, contents); + + // WHEN we set the biases from file + ASSERT_NO_THROW(i_ll_biases_->load_from_file(filename)); + + // THEN the biases set in the HAL facility have the values written in the file + std::map biases_set = i_ll_biases_->get_all_biases(); + std::map expected_biases = {{"bias_pr", 151}, {"bias_fo", 23}, {"bias_hpf", 48}, + {"bias_diff_on", 112}, {"bias_diff", 69}, {"bias_diff_off", 52}, + {"bias_refr", 45}}; + compare_biases(expected_biases, biases_set); +} + +TEST_F(BiasFile_GTest, load_from_file_wrong_extension) { + // GIVEN a bias file with wrong extension + std::string filename = tmpdir_handler_->get_full_path("input.txt"); + write_file(filename, "299 % bias_diff"); + + try { + // WHEN we set the biases from the given file + i_ll_biases_->load_from_file(filename); + FAIL() << "Expected exception Metavision::HalErrorCode::InvalidArgument"; + } catch (const Metavision::HalException &err) { + // THEN it throws an exception + EXPECT_EQ(err.code().value(), Metavision::HalErrorCode::InvalidArgument); + } +} + +TEST_F(BiasFile_GTest, load_from_file_nonexistent_file) { + // GIVEN a bias file that doesn't exist + std::string filename = tmpdir_handler_->get_full_path("nonexistent.bias"); + + try { + // WHEN we set the biases from this nonexistent file + i_ll_biases_->load_from_file(filename); + FAIL() << "Expected exception Metavision::HalErrorCode::InvalidArgument"; + } catch (const Metavision::HalException &err) { + // THEN it throws an exception + EXPECT_EQ(err.code().value(), Metavision::HalErrorCode::InvalidArgument); + } +} + +TEST_F(BiasFile_GTest, load_from_file_wrong_format) { + // GIVEN a bias file with the wrong format + std::string contents = "300 bias_diff\n" + "222 bias_diff_off\n" + "385 bias_diff_on\n" + "1480 bias_fo\n" + "1450 bias_hpf\n" + "1250 bias_pr\n" + "1500 bias_refr\n"; + std::string filename = tmpdir_handler_->get_full_path("input.bias"); + write_file(filename, contents); + + try { + // WHEN we set the biases from file + i_ll_biases_->load_from_file(filename); + FAIL() << "Expected exception Metavision::HalErrorCode::InvalidArgument"; + } catch (const Metavision::HalException &err) { + // THEN it throws an exception + EXPECT_EQ(err.code().value(), Metavision::HalErrorCode::InvalidArgument); + } +} + +TEST_F(BiasFile_GTest, load_from_file_with_incompatible_biases) { + // GIVEN a bias file like the ones we provide at installation + std::string contents = "299 % bias_diff\n" + "228 % bias_diff_off\n" + "370 % bias_diff_on\n" + "1507 % bias_fo_n\n" // this is the incompatible bias + "1499 % bias_hpf\n" + "1250 % bias_pr\n" + "1500 % bias_refr\n"; + std::string filename = tmpdir_handler_->get_full_path("input.bias"); + write_file(filename, contents); + + try { + // WHEN we set the biases from file + i_ll_biases_->load_from_file(filename); + FAIL() << "Expected exception Metavision::HalErrorCode::NonExistingValue"; + } catch (const Metavision::HalException &err) { + // THEN it throws an exception + EXPECT_EQ(err.code().value(), Metavision::HalErrorCode::NonExistingValue); + } +} + +TEST_F(BiasFile_GTest, load_from_file_with_two_different_values_for_same_bias) { + // GIVEN a bias file containing different values for a same bias + std::string contents = "299 % bias_diff\n" + "228 % bias_diff_off\n" + "370 % bias_diff_on\n" + "1507 % bias_fo\n" + "1499 % bias_hpf\n" + "1250 % bias_pr\n" + "1500 % bias_fo\n" + "1500 % bias_refr\n"; + std::string filename = tmpdir_handler_->get_full_path("input.bias"); + write_file(filename, contents); + + try { + // WHEN we set the biases from file + i_ll_biases_->load_from_file(filename); + FAIL() << "Expected exception Metavision::HalErrorCode::InvalidArgument"; + } catch (const Metavision::HalException &err) { + // THEN it throws an exception + EXPECT_EQ(err.code().value(), Metavision::HalErrorCode::InvalidArgument); + } +} + +TEST_F(BiasFile_GTest, save_to_file) { + // GIVEN a Biases instance with given biases + std::map biases_map = {{"bias_diff", 299}, {"bias_diff_off", 228}, {"bias_diff_on", 370}, + {"bias_fo", 1507}, {"bias_hpf", 1499}, {"bias_pr", 1250}, + {"bias_refr", 1500}}; + auto dummy_biases = std::make_unique(Metavision::DeviceConfig(), biases_map); + + // WHEN saving the biases to a file + std::string filename = tmpdir_handler_->get_full_path("output.bias"); + ASSERT_NO_THROW(dummy_biases->save_to_file(filename)); + + // THEN when reading back the file we get the same biases of the original Biases instance + ASSERT_NO_THROW(i_ll_biases_->load_from_file(filename)); + std::map biases_set = i_ll_biases_->get_all_biases(); + compare_biases(biases_map, biases_set); +} + +TEST_F(BiasFile_GTest, save_to_file_wrong_extension) { + // GIVEN an output file with wrong extension + std::string filename = tmpdir_handler_->get_full_path("output.txt"); + + try { + // WHEN saving the biases to a file + i_ll_biases_->save_to_file(filename); + FAIL() << "Expected exception Metavision::HalErrorCode::InvalidArgument"; + } catch (const Metavision::HalException &err) { + // THEN it throws an exception + EXPECT_EQ(err.code().value(), Metavision::HalErrorCode::InvalidArgument); + } +} + +TEST_F(BiasFile_GTest, save_to_file_when_passing_invalid_filename) { + // GIVEN an output file that is invalid + std::string invalid_filename = tmpdir_handler_->get_full_path("output.bias"); + // Invalid because it's an existing directory + ASSERT_TRUE(std::filesystem::create_directory(invalid_filename)); + + try { + // WHEN saving the biases to the provided file + i_ll_biases_->save_to_file(invalid_filename); + FAIL() << "Expected exception Metavision::HalErrorCode::InvalidArgument"; + } catch (const Metavision::HalException &err) { + // THEN it throws an exception + EXPECT_EQ(err.code().value(), Metavision::HalErrorCode::InvalidArgument); + } +} diff --git a/hal/cpp/test/i_roi_gtest.cpp b/hal/cpp/test/i_roi_gtest.cpp index 3f8452863..d33bc2d78 100644 --- a/hal/cpp/test/i_roi_gtest.cpp +++ b/hal/cpp/test/i_roi_gtest.cpp @@ -13,12 +13,9 @@ #include #include #include -#include #include "metavision/sdk/base/events/event_cd.h" -#include "metavision/utils/gtest/gtest_with_tmp_dir.h" #include "metavision/utils/gtest/gtest_custom.h" -#include "metavision/hal/utils/hal_exception.h" #include "metavision/hal/device/device_discovery.h" #include "metavision/hal/device/device.h" #include "metavision/hal/facilities/i_camera_synchronization.h" @@ -116,7 +113,7 @@ TEST_F_WITH_CAMERA(I_ROI_GTest, roi_columns_lines_with_camera) { // Flush first events continue; } - decoder->decode(buffer->data(), buffer->data() + buffer->size()); + decoder->decode(buffer); } } @@ -147,7 +144,6 @@ TEST_F_WITH_CAMERA(I_ROI_GTest, roi_rectangle_with_camera) { FAIL(); } - long n_bytes; auto buffer = es->get_latest_raw_data(); if (std::chrono::duration_cast(std::chrono::system_clock::now() - tnow).count() < @@ -155,7 +151,7 @@ TEST_F_WITH_CAMERA(I_ROI_GTest, roi_rectangle_with_camera) { // Flush first events continue; } - decoder->decode(buffer->data(), buffer->data() + buffer->size()); + decoder->decode(buffer); } } @@ -195,7 +191,6 @@ TEST_F_WITH_CAMERA(I_ROI_GTest, several_roi_rectangle_with_camera) { FAIL(); } - long n_bytes; auto buffer = es->get_latest_raw_data(); if (std::chrono::duration_cast(std::chrono::system_clock::now() - tnow).count() < @@ -203,6 +198,6 @@ TEST_F_WITH_CAMERA(I_ROI_GTest, several_roi_rectangle_with_camera) { // Flush first events continue; } - decoder->decode(buffer->data(), buffer->data() + buffer->size()); + decoder->decode(buffer); } } diff --git a/hal/cpp/test/utils/data_transfer_gtest.cpp b/hal/cpp/test/utils/data_transfer_gtest.cpp new file mode 100644 index 000000000..7df2830b5 --- /dev/null +++ b/hal/cpp/test/utils/data_transfer_gtest.cpp @@ -0,0 +1,146 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/hal/utils/data_transfer.h" +#include "metavision/sdk/base/utils/object_pool.h" + +using namespace Metavision; +using testing::_; + +class MockRawDataProducer : public DataTransfer::RawDataProducer { +public: + MOCK_METHOD(void, start_impl, (), (override)); + MOCK_METHOD(void, run_impl, (const DataTransfer &), (override)); + MOCK_METHOD(void, stop_impl, (), (override)); +}; + +TEST(DataTransfer, should_have_default_data_transfer_constructor) { + auto data_prod = std::make_shared>(); + + DataTransfer data_transfer(data_prod); + + EXPECT_CALL(*data_prod, start_impl()).Times(0); + EXPECT_CALL(*data_prod, run_impl(_)).Times(0); + EXPECT_CALL(*data_prod, stop_impl()).Times(0); +} + +TEST(DataTransfer, should_stop_without_explicit_call_to_stop) { + auto data_prod = std::make_shared(); + DataTransfer data_transfer(data_prod); + + EXPECT_CALL(*data_prod, start_impl()).Times(1); + EXPECT_CALL(*data_prod, run_impl(_)).Times(1); + EXPECT_CALL(*data_prod, stop_impl()).Times(1); + + data_transfer.start(); +} + +TEST(DataTransfer, should_stop_with_explicit_call_to_stop) { + auto data_prod = std::make_shared(); + + DataTransfer data_transfer(data_prod); + + EXPECT_CALL(*data_prod, start_impl()).Times(1); + EXPECT_CALL(*data_prod, run_impl(_)).Times(1); + EXPECT_CALL(*data_prod, stop_impl()).Times(1); + + data_transfer.start(); + data_transfer.stop(); +} + +TEST(DataTransferBufferPtr, should_default_construct) { + DataTransfer::BufferPtr bufferptr; + EXPECT_FALSE(bufferptr); + EXPECT_EQ(bufferptr.data(), nullptr); + EXPECT_EQ(bufferptr.size(), 0); +} + +TEST(DataTransferBufferPtr, buffer_ptr_should_hold_reference_count_from_shared_ptr) { + auto vec_buff = std::make_shared>(); + + EXPECT_EQ(vec_buff.use_count(), 1); + { + DataTransfer::BufferPtr bufferptr = DataTransfer::make_buffer_ptr(vec_buff); + EXPECT_EQ(vec_buff.use_count(), 2); + } + EXPECT_EQ(vec_buff.use_count(), 1); +} + +TEST(DataTransferBufferPtr, should_release_reference_count_on_reset) { + auto vec_buff = std::make_shared>(); + DataTransfer::BufferPtr bufferptr = DataTransfer::make_buffer_ptr(vec_buff); + + EXPECT_EQ(vec_buff.use_count(), 2); + bufferptr.reset(); + EXPECT_EQ(vec_buff.use_count(), 1); +} + +TEST(DataTransferBufferPtr, buffer_ptr_should_have_range_semantic) { + auto vec_buff = std::make_shared>(); + vec_buff->insert(vec_buff->begin(), {1, 2, 3}); + + DataTransfer::BufferPtr buff_ptr = DataTransfer::make_buffer_ptr(vec_buff); + + auto sum = std::reduce(buff_ptr.begin(), buff_ptr.end()); + EXPECT_EQ(sum, 6); + + auto const_data_sum = std::reduce(buff_ptr.cbegin(), buff_ptr.cend()); + EXPECT_EQ(const_data_sum, 6); +} + +TEST(DataTransferBufferPtr, should_construct_BufferPtr_from_pool) { + using StringPool = SharedObjectPool; + using StringBuffer = StringPool::ptr_type; + + StringPool pool = StringPool::make_unbounded(1, "Hello World"); + StringBuffer string_buff = pool.acquire(); + + auto data_prod = std::make_shared(); + DataTransfer data_transfer(data_prod); + + DataTransfer::BufferPtr buffer_ptr; + data_transfer.add_new_buffer_callback([&](auto buff) { buffer_ptr = buff; }); + + data_transfer.transfer_data(string_buff); + + EXPECT_EQ(buffer_ptr.size(), buffer_ptr.size()); + EXPECT_EQ(reinterpret_cast(buffer_ptr.data()), string_buff->data()); + EXPECT_STREQ(reinterpret_cast(buffer_ptr.data()), "Hello World"); +} + +TEST(DataTransferBufferPtr, should_clone_buffer_ptr) { + auto vec_buff = std::make_shared>(); + vec_buff->insert(vec_buff->begin(), {1, 2, 3}); + + DataTransfer::BufferPtr buff_ptr = DataTransfer::make_buffer_ptr(vec_buff); + auto cloned_buff_ptr = buff_ptr.clone(); + + EXPECT_NE(cloned_buff_ptr.data(), buff_ptr.data()) << "Underlying data should differ"; + + auto cloned_vec = cloned_buff_ptr.any_clone_cast(); + EXPECT_THAT(*cloned_vec, testing::ContainerEq(*vec_buff)) << "Items should have been copied"; +} + +TEST(DataTransferBufferPtr, should_throw_on_casting_back_non_cloned_buffer) { + auto vec_of_char = std::make_shared>(); + vec_of_char->insert(vec_of_char->begin(), {'a', 'b', 'c'}); + + DataTransfer::BufferPtr buff_ptr = DataTransfer::make_buffer_ptr(vec_of_char); + EXPECT_THROW(buff_ptr.any_clone_cast(), std::bad_cast); +} diff --git a/hal/cpp/test/utils/device_test.h b/hal/cpp/test/utils/device_test.h index 002d56327..a0fa6e828 100644 --- a/hal/cpp/test/utils/device_test.h +++ b/hal/cpp/test/utils/device_test.h @@ -12,8 +12,6 @@ #ifndef METAVISION_HAL_TEST_UTILS_DEVICE_TEST_H #define METAVISION_HAL_TEST_UTILS_DEVICE_TEST_H -#include - #include #include "metavision/hal/device/device.h" @@ -21,7 +19,6 @@ #include "metavision/hal/facilities/i_event_decoder.h" #include "metavision/hal/facilities/i_events_stream.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" -#include "metavision/hal/facilities/i_facility.h" #include "metavision/hal/utils/hal_exception.h" #include "metavision/utils/gtest/gtest_with_tmp_dir.h" @@ -71,7 +68,7 @@ class DeviceTest : public GTestWithTmpDir { while (nb_buffers_to_process > 0) { if (events_stream->wait_next_buffer()) { auto raw_data = events_stream->get_latest_raw_data(); - events_stream_decoder->decode(raw_data->data(), raw_data->data() + raw_data->size()); + events_stream_decoder->decode(raw_data); nb_buffers_to_process--; } } diff --git a/hal/python/bindings/device_discovery_python.cpp b/hal/python/bindings/device_discovery_python.cpp index 5c61b4344..5e8b3c0e2 100644 --- a/hal/python/bindings/device_discovery_python.cpp +++ b/hal/python/bindings/device_discovery_python.cpp @@ -9,7 +9,9 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include +#include #include "hal_python_binder.h" #include "metavision/hal/device/device_discovery.h" @@ -29,11 +31,12 @@ std::shared_ptr open_with_config_wrapper(const std::string &serial, Devi return std::shared_ptr(DeviceDiscovery::open(serial, config)); } -std::shared_ptr open_raw_file_with_only_filename(const std::string &raw_file) { +std::shared_ptr open_raw_file_with_only_filename(const std::filesystem::path &raw_file) { return std::shared_ptr(DeviceDiscovery::open_raw_file(raw_file)); } -std::shared_ptr open_raw_file_with_config_wrapper(const std::string &raw_file, RawFileConfig &file_config) { +std::shared_ptr open_raw_file_with_config_wrapper(const std::filesystem::path &raw_file, + const RawFileConfig &file_config) { return std::shared_ptr(DeviceDiscovery::open_raw_file(raw_file, file_config)); } @@ -50,8 +53,7 @@ static HALGenericPythonBinder bind_connection_type([](auto &module) { static HALClassPythonBinder bind_plugin_camera_desc( [](auto &module, auto &class_binding) { class_binding.def_readonly("serial", &PluginCameraDescription::serial_) - .def_readonly("connection", &PluginCameraDescription::connection_) - .def_readonly("system_id", &PluginCameraDescription::system_id_); + .def_readonly("connection", &PluginCameraDescription::connection_); }, "PluginCameraDescription"); @@ -73,13 +75,17 @@ static HALGenericPythonBinder bind([](auto &module) { py::arg("config"), pybind_doc_hal ["Metavision::DeviceDiscovery::open(const std::string &serial, const DeviceConfig &config)"]) - .def_static("open_raw_file", &open_raw_file_with_only_filename, py::return_value_policy::take_ownership, - py::arg("raw_file"), - pybind_doc_hal["Metavision::DeviceDiscovery::open_raw_file(const std::string &raw_file)"]) - .def_static("open_raw_file", &open_raw_file_with_config_wrapper, py::return_value_policy::take_ownership, - py::arg("raw_file"), py::arg("file_config"), - pybind_doc_hal["Metavision::DeviceDiscovery::open_raw_file(const std::string &raw_file, " - "const RawFileConfig &file_config)"]) + .def_static( + "open_raw_file", py::overload_cast(&open_raw_file_with_only_filename), + py::return_value_policy::take_ownership, py::arg("raw_file"), + pybind_doc_hal["Metavision::DeviceDiscovery::open_raw_file(const std::filesystem::path &raw_file)"]) + .def_static( + "open_raw_file", + py::overload_cast( + &open_raw_file_with_config_wrapper), + py::return_value_policy::take_ownership, py::arg("raw_file"), py::arg("file_config"), + pybind_doc_hal["Metavision::DeviceDiscovery::open_raw_file(const std::filesystem::path &raw_file, " + "const RawFileConfig &file_config)"]) .def_static( "list", +[]() { diff --git a/hal/python/bindings/i_event_frame_decoder_python.cpp b/hal/python/bindings/i_event_frame_decoder_python.cpp index 634761f33..afc094623 100644 --- a/hal/python/bindings/i_event_frame_decoder_python.cpp +++ b/hal/python/bindings/i_event_frame_decoder_python.cpp @@ -9,8 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include +#include "metavision/hal/utils/data_transfer.h" #include "metavision/utils/pybind/deprecation_warning_exception.h" #include "hal_python_binder.h" @@ -26,23 +28,12 @@ namespace Metavision { namespace { -void decode_wrapper_diff(I_EventFrameDecoder *decoder, py::array_t *array) { - py::buffer_info buf = array->request(); - if (buf.ndim != 1) { - throw std::runtime_error("Decoder needs a 1 dimensional buffer of RawData. Received a " + - std::to_string(buf.ndim) + " dimensional array instead"); - } - decoder->decode((I_EventsStream::RawData *)buf.ptr, (I_EventsStream::RawData *)buf.ptr + buf.size); +void decode_wrapper_diff(I_EventFrameDecoder *decoder, py::object &raw_buffer) { + decoder->decode(py::cast(raw_buffer)); } -void decode_wrapper_histo(I_EventFrameDecoder *decoder, - py::array_t *array) { - py::buffer_info buf = array->request(); - if (buf.ndim != 1) { - throw std::runtime_error("Decoder needs a 1 dimensional buffer of RawData. Reeived a " + - std::to_string(buf.ndim) + " dimensional array instead"); - } - decoder->decode((I_EventsStream::RawData *)buf.ptr, (I_EventsStream::RawData *)buf.ptr + buf.size); +void decode_wrapper_histo(I_EventFrameDecoder *decoder, py::object &raw_buffer) { + decoder->decode(py::cast(raw_buffer)); } } /* anonymous namespace */ diff --git a/hal/python/bindings/i_event_rate_activity_filter_module_python.cpp b/hal/python/bindings/i_event_rate_activity_filter_module_python.cpp index ddda2ca9a..5e91b6a51 100644 --- a/hal/python/bindings/i_event_rate_activity_filter_module_python.cpp +++ b/hal/python/bindings/i_event_rate_activity_filter_module_python.cpp @@ -11,7 +11,6 @@ #include "hal_python_binder.h" #include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" -#include "metavision/hal/utils/detail/warning_supression.h" #include "pb_doc_hal.h" namespace Metavision { @@ -24,17 +23,7 @@ static HALFacilityPythonBinder bind( .def("enable", &I_EventRateActivityFilterModule::enable, py::arg("enable_filter"), pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::enable"]) .def("is_enabled", &I_EventRateActivityFilterModule::is_enabled, - pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::is_enabled"]); - - SUPRESS_DEPRECATION_WARNING( - class_binding - .def("set_event_rate_threshold", &I_EventRateActivityFilterModule::set_event_rate_threshold, - py::arg("threshold_Kev_s"), - pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::set_event_rate_threshold"]) - .def("get_event_rate_threshold", &I_EventRateActivityFilterModule::get_event_rate_threshold, - pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::get_event_rate_threshold"]);); - - class_binding + pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::is_enabled"]) .def("get_thresholds", &I_EventRateActivityFilterModule::get_thresholds, pybind_doc_hal["Metavision::I_EventRateActivityFilterModule::get_thresholds"]) diff --git a/hal/python/bindings/i_event_trail_filter_module_python.cpp b/hal/python/bindings/i_event_trail_filter_module_python.cpp index 5def933c1..73a14f463 100644 --- a/hal/python/bindings/i_event_trail_filter_module_python.cpp +++ b/hal/python/bindings/i_event_trail_filter_module_python.cpp @@ -15,35 +15,6 @@ namespace Metavision { -namespace { -bool set_stc_cut_trail_filter_wrapper(I_EventTrailFilterModule &self) { - auto warnings = pybind11::module::import("warnings"); - warnings.attr("warn")("set_stc_cut_trail_filter() is deprecated since v4.2.0, use " - "set_type(metavision_hal.I_EventTrailFilterModule.STC_CUT_TRAIL) instead."); - - if (self.get_available_types().count(I_EventTrailFilterModule::Type::STC_CUT_TRAIL) <= 0) - return false; - - self.set_type(I_EventTrailFilterModule::Type::STC_CUT_TRAIL); - return true; -} - -bool set_trail_filter_wrapper(I_EventTrailFilterModule &self) { - auto warnings = pybind11::module::import("warnings"); - warnings.attr("warn")("set_trail_filter() is deprecated since v4.2.0, use " - "set_type(metavision_hal.I_EventTrailFilterModule.TRAIL) instead."); - - if (self.get_available_types().count(I_EventTrailFilterModule::Type::TRAIL) <= 0) - return false; - self.set_type(I_EventTrailFilterModule::Type::TRAIL); - return true; -} -} // namespace - -// TODO : remove before next major release -// Add depreciation message for get_i_eventrail_fiter_module typo -> get_i_event_trail_filter_module -static DeprecatedDeviceFacilityGetter getter_("get_i_eventrailfilter_module", - "get_i_event_trail_filter_module", "4.0.1"); static DeviceFacilityGetter getter("get_i_event_trail_filter_module"); static HALFacilityPythonBinder bind( @@ -58,18 +29,6 @@ static HALFacilityPythonBinder bind( pybind_doc_hal["Metavision::I_EventTrailFilterModule::enable"]) .def("is_enabled", &I_EventTrailFilterModule::is_enabled, pybind_doc_hal["Metavision::I_EventTrailFilterModule::is_enabled"]) - // TODO : remove before next major release - .def("set_stc_cut_trail_filter", set_stc_cut_trail_filter_wrapper, - "Sets the EventTrailFilterModule filter mode to STC_CUT_TRAIL\n" - "\n" - "This filter keeps the second event within a burst of events with the same polarity\n" - "Returns true on success, false if filter type is not supported\n") - // TODO : remove before next major release - .def("set_trail_filter", set_trail_filter_wrapper, - "Sets the EventTrailFilterModule filter mode to TRAIL\n" - "\n" - "This filter keeps the first event within a burst of events with the same polarity\n" - "Returns true on success, false if filter type is not supported\n") .def("get_available_types", &I_EventTrailFilterModule::get_available_types, pybind_doc_hal["Metavision::I_EventTrailFilterModule::get_available_types"]) .def("get_type", &I_EventTrailFilterModule::get_type, diff --git a/hal/python/bindings/i_events_stream_decoder_python.cpp b/hal/python/bindings/i_events_stream_decoder_python.cpp index a32d12774..c6839468a 100644 --- a/hal/python/bindings/i_events_stream_decoder_python.cpp +++ b/hal/python/bindings/i_events_stream_decoder_python.cpp @@ -25,13 +25,8 @@ namespace Metavision { namespace { -void decode_wrapper(I_EventsStreamDecoder *decoder, py::array_t *array) { - py::buffer_info buf = array->request(); - if (buf.ndim != 1) { - throw std::runtime_error("Decoder need a array of events the provided buffer as " + std::to_string(buf.ndim) + - " dimensions"); - } - decoder->decode((I_EventsStream::RawData *)buf.ptr, (I_EventsStream::RawData *)buf.ptr + buf.size); +void decode_wrapper(I_EventsStreamDecoder *decoder, py::object &raw_buffer) { + decoder->decode(raw_buffer.cast()); } // Provide this overload to avoid having to convert opaque vectors to py::array_t @@ -48,7 +43,7 @@ static HALFacilityPythonBinder bind( class_binding .def("get_last_timestamp", &I_EventsStreamDecoder::get_last_timestamp, pybind_doc_hal["Metavision::I_EventsStreamDecoder::get_last_timestamp"]) - .def("decode", &decode_wrapper, py::arg("RawData"), + .def("decode", &decode_wrapper, "Decodes raw data. Identifies the events in the buffer and dispatches it to the instance " "Event Decoder corresponding to each event type\n" "\n" diff --git a/hal/python/bindings/i_events_stream_python.cpp b/hal/python/bindings/i_events_stream_python.cpp index 9e01a1911..e5fbed7df 100644 --- a/hal/python/bindings/i_events_stream_python.cpp +++ b/hal/python/bindings/i_events_stream_python.cpp @@ -15,33 +15,19 @@ #include "hal_python_binder.h" #include "metavision/hal/facilities/i_events_stream.h" -#include "metavision/utils/pybind/deprecation_warning_exception.h" #include "pb_doc_hal.h" -// Needed to avoid copies of vectors of RawData -PYBIND11_MAKE_OPAQUE(Metavision::DataTransfer::Buffer); - namespace Metavision { - namespace { - std::shared_ptr get_latest_raw_data_wrapper(I_EventsStream *ies) { - auto data = ies->get_latest_raw_data(); - // If we return nullptr, python doesn't know the type of the objects and considers it "None". - // This causes issues when trying to call decode on an empty buffer which has been possible so far. - // So return a shared pointer to an empty vector not to break user scripts - if (!data) { - return std::make_shared(); - } - return data; - } +auto get_latest_raw_data_wrapper(I_EventsStream &ies) { + return ies.get_latest_raw_data(); } +} // namespace static DeviceFacilityGetter getter("get_i_events_stream"); static HALFacilityPythonBinder bind( [](auto &module, auto &class_binding) { - - py::bind_vector(module, "RawDataBuffer"); class_binding.def("start", &I_EventsStream::start, pybind_doc_hal["Metavision::I_EventsStream::start"]) .def("stop", &I_EventsStream::stop, pybind_doc_hal["Metavision::I_EventsStream::stop"]) .def("poll_buffer", &I_EventsStream::poll_buffer, pybind_doc_hal["Metavision::I_EventsStream::poll_buffer"]) @@ -56,4 +42,11 @@ static HALFacilityPythonBinder bind( }, "I_EventsStream", pybind_doc_hal["Metavision::I_EventsStream"]); +static HALFacilityPythonBinder bind_buffer_ptr( + [](auto &module, auto &class_binding) { + class_binding.def("size", &DataTransfer::BufferPtr::size, + pybind_doc_hal["Metavision::DataTransfer::BufferPtr::size"]); + }, + "RawBuffer", pybind_doc_hal["Metavision::DataTransfer::BufferPtr"]); + } // namespace Metavision diff --git a/hal/python/bindings/i_hw_identification_python.cpp b/hal/python/bindings/i_hw_identification_python.cpp index 0b0be4c7b..4b0775354 100644 --- a/hal/python/bindings/i_hw_identification_python.cpp +++ b/hal/python/bindings/i_hw_identification_python.cpp @@ -34,8 +34,6 @@ static HALFacilityPythonBinder bind( class_binding .def("get_serial", &I_HW_Identification::get_serial, pybind_doc_hal["Metavision::I_HW_Identification::get_serial"]) - .def("get_system_id", &I_HW_Identification::get_system_id, - pybind_doc_hal["Metavision::I_HW_Identification::get_system_id"]) .def("get_sensor_info", &I_HW_Identification::get_sensor_info, pybind_doc_hal["Metavision::I_HW_Identification::get_sensor_info"]) .def("get_available_data_encoding_formats", &I_HW_Identification::get_available_data_encoding_formats, diff --git a/hal/python/bindings/i_roi_python.cpp b/hal/python/bindings/i_roi_python.cpp index d1677529e..7436384a2 100644 --- a/hal/python/bindings/i_roi_python.cpp +++ b/hal/python/bindings/i_roi_python.cpp @@ -19,9 +19,9 @@ namespace { void set_windows_wrapper(I_ROI &i_roi, py::list &windows_list) { std::vector windows; - const ssize_t n_roi = py::len(windows_list); + const py::ssize_t n_roi = py::len(windows_list); - for (ssize_t i = 0; i < n_roi; ++i) { + for (py::ssize_t i = 0; i < n_roi; ++i) { windows.push_back((windows_list[i]).cast()); } @@ -31,14 +31,14 @@ void set_windows_wrapper(I_ROI &i_roi, py::list &windows_list) { void set_lines_wrapper(I_ROI &i_roi, py::list &cols, py::list &rows) { std::vector cols_vec; std::vector rows_vec; - const ssize_t n_cols = py::len(cols); - const ssize_t n_rows = py::len(rows); + const py::ssize_t n_cols = py::len(cols); + const py::ssize_t n_rows = py::len(rows); - for (ssize_t idx = 0; idx < n_cols; ++idx) { + for (py::ssize_t idx = 0; idx < n_cols; ++idx) { cols_vec.push_back((cols[idx]).cast()); } - for (ssize_t idx = 0; idx < n_rows; ++idx) { + for (py::ssize_t idx = 0; idx < n_rows; ++idx) { rows_vec.push_back((rows[idx]).cast()); } diff --git a/hal/python/bindings/i_trigger_in_python.cpp b/hal/python/bindings/i_trigger_in_python.cpp index e0b6593f3..4bdc95810 100644 --- a/hal/python/bindings/i_trigger_in_python.cpp +++ b/hal/python/bindings/i_trigger_in_python.cpp @@ -19,22 +19,6 @@ static DeviceFacilityGetter getter("get_i_trigger_in"); static HALFacilityPythonBinder bind( [](auto &module, auto &class_binding) { - // TODO : remove before next major release - // Add depreciation for metavision_hal.Channel that was wrongly introduced in the wrong - // scope, it should have been in metavision_hal.I_TriggerIn.Channel from the beginning - class DeprecatedChannel {}; - py::class_ c(module, "Channel"); - for (auto &&p : - {std::make_pair("MAIN", I_TriggerIn::Channel::Main), std::make_pair("AUX", I_TriggerIn::Channel::Aux), - std::make_pair("LOOPBACK", I_TriggerIn::Channel::Loopback)}) { - c.def_property_readonly_static(p.first, [p](const py::object &) { - auto warnings = pybind11::module::import("warnings"); - warnings.attr("warn")("metavision_hal.Channel is deprecated since v4.0.1, use " - "metavision_hal.I_TriggerIn.Channel instead."); - return p.second; - }); - } - py::enum_(class_binding, "Channel", py::arithmetic()) .value("MAIN", I_TriggerIn::Channel::Main) .value("AUX", I_TriggerIn::Channel::Aux) diff --git a/hal/python/tests/hal_event_trail_filter_module_pytest.py b/hal/python/tests/hal_event_trail_filter_module_pytest.py index 712c36ef0..2066d94b0 100644 --- a/hal/python/tests/hal_event_trail_filter_module_pytest.py +++ b/hal/python/tests/hal_event_trail_filter_module_pytest.py @@ -27,11 +27,6 @@ def pytestcase_metavision_hal_has_event_trail_filter_interface(): assert "get_available_types" in event_trail_filter_module_member_names assert "get_type" in event_trail_filter_module_member_names assert "set_type" in event_trail_filter_module_member_names - # TODO : remove before next major release - assert "set_stc_cut_trail_filter" in event_trail_filter_module_member_names - # TODO : remove before next major release - assert "set_stc_cut_trail_filter" in event_trail_filter_module_member_names - assert "set_trail_filter" in event_trail_filter_module_member_names assert "set_threshold" in event_trail_filter_module_member_names assert "get_threshold" in event_trail_filter_module_member_names assert "get_min_supported_threshold" in event_trail_filter_module_member_names @@ -91,15 +86,6 @@ def pytestcase_event_trail_filter_module_should_set_type(i_event_trail_filter_mo assert i_event_trail_filter_module.get_type() == metavision_hal.I_EventTrailFilterModule.Type.TRAIL -def pytestcase_event_trail_filter_module_should_set_type_using_deprecated_wrappers(i_event_trail_filter_module): - with pytest.warns(UserWarning): - assert i_event_trail_filter_module.set_stc_cut_trail_filter() - assert i_event_trail_filter_module.get_type() == metavision_hal.I_EventTrailFilterModule.Type.STC_CUT_TRAIL - with pytest.warns(UserWarning): - assert i_event_trail_filter_module.set_trail_filter() - assert i_event_trail_filter_module.get_type() == metavision_hal.I_EventTrailFilterModule.Type.TRAIL - - def pytestcase_event_trail_filter_module_should_have_correct_threshold_by_default(i_event_trail_filter_module): assert i_event_trail_filter_module.get_threshold() == 1 diff --git a/hal_psee_plugins/CMakeLists.txt b/hal_psee_plugins/CMakeLists.txt index 6af920305..04b0f3355 100644 --- a/hal_psee_plugins/CMakeLists.txt +++ b/hal_psee_plugins/CMakeLists.txt @@ -7,6 +7,10 @@ # 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. +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/internal") + set(BUILD_INTERNAL_PLUGINS TRUE) + set(metavision_hal_psee_internal_plugins_include_dir "${CMAKE_CURRENT_SOURCE_DIR}/internal/include") +endif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/internal") find_file(v4l2_headers videodev2.h PATH_SUFFIXES linux) message(STATUS "Found V4l2 header : ${v4l2_headers}") @@ -32,6 +36,11 @@ add_subdirectory(lib) # Add sources plugins add_subdirectory(src) +# Add internal sources plugins +if(BUILD_INTERNAL_PLUGINS) + add_subdirectory(internal) +endif(BUILD_INTERNAL_PLUGINS) + # Resources add_subdirectory(resources) @@ -41,6 +50,11 @@ add_subdirectory(apps) # Samples add_subdirectory(samples) +# Python +if(COMPILE_PYTHON3_BINDINGS) + add_subdirectory(python) +endif(COMPILE_PYTHON3_BINDINGS) + # Tests if (BUILD_TESTING) add_subdirectory(test) diff --git a/hal_psee_plugins/include/boards/fx3/fx3_hw_identification.h b/hal_psee_plugins/include/boards/fx3/fx3_hw_identification.h index 3a4b6a7aa..2187161f7 100644 --- a/hal_psee_plugins/include/boards/fx3/fx3_hw_identification.h +++ b/hal_psee_plugins/include/boards/fx3/fx3_hw_identification.h @@ -38,13 +38,6 @@ class Fx3HWIdentification : public Metavision::I_HW_Identification { /// @return Serial number as a string virtual std::string get_serial() const override; - /// @brief Returns the serial number of the camera - /// - /// @return The system id as a integer - /// - /// @note this number can be used to check the compatibility of biases file for example - virtual long get_system_id() const override; - /// @brief Returns the detail about the sensor available /// /// @return The sensor information diff --git a/hal_psee_plugins/include/boards/v4l2/dma_buf_heap.h b/hal_psee_plugins/include/boards/v4l2/dma_buf_heap.h index 4bd9c1c0b..1d8ff470f 100644 --- a/hal_psee_plugins/include/boards/v4l2/dma_buf_heap.h +++ b/hal_psee_plugins/include/boards/v4l2/dma_buf_heap.h @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/hal_psee_plugins/include/boards/v4l2/v4l2_data_transfer.h b/hal_psee_plugins/include/boards/v4l2/v4l2_data_transfer.h index 8a2f0440d..c8ec10ebb 100644 --- a/hal_psee_plugins/include/boards/v4l2/v4l2_data_transfer.h +++ b/hal_psee_plugins/include/boards/v4l2/v4l2_data_transfer.h @@ -13,24 +13,120 @@ #define METAVISION_HAL_PSEE_PLUGINS_V4L2_DATA_TRANSFER_H #include "metavision/hal/utils/data_transfer.h" +#include "metavision/sdk/base/utils/object_pool.h" + +#include +#include +#include +#include +#include + +#include namespace Metavision { +using V4l2Buffer = struct v4l2_buffer; +using V4l2RequestBuffers = struct v4l2_requestbuffers; -class V4L2DeviceControl; -class V4l2DeviceUserPtr; // @TODO Replace with a V4l2 Buffer class interface +class DmaBufHeap; -class V4l2DataTransfer : public DataTransfer { +class V4l2DataTransfer : public DataTransfer::RawDataProducer { public: - V4l2DataTransfer(std::shared_ptr device, uint32_t raw_event_size_bytes); + // Constructor using MMAP buffers + V4l2DataTransfer(int fd, uint32_t raw_event_size_bytes); + + // Constructor using DMABUF buffers + V4l2DataTransfer(int fd, uint32_t raw_event_size_bytes, const std::string &heap_path, const std::string &heap_name); + ~V4l2DataTransfer(); private: - std::shared_ptr device_; - std::unique_ptr buffers; + static constexpr int device_buffer_number = 32; + + // The memory type currently in use + const enum v4l2_memory memtype_; + + const int fd_; - void start_impl(BufferPtr buffer) override final; - void run_impl() override final; + V4l2RequestBuffers request_buffers(uint32_t nb_buffers); + + void start_impl() override final; + void run_impl(const DataTransfer &data_transfer) override final; void stop_impl() override final; + + class V4l2Allocator : public std::pmr::memory_resource { + size_t buffer_byte_size_{0}; + + protected: + V4l2Allocator(int videodev_fd); + + public: + size_t max_byte_size() const noexcept { + return buffer_byte_size_; + } + // Get a descriptor usable with V4L2 API from a data pointer + virtual void fill_v4l2_buffer(void *, V4l2Buffer &) const = 0; + virtual void begin_cpu_access(void *) const {} + virtual void end_cpu_access(void *) const {} + }; + + class V4l2MmapAllocator : public V4l2Allocator { + // MemoryResource interface + void *do_allocate(std::size_t bytes, std::size_t alignment) override; + void do_deallocate(void *p, std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) override; + bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override; + + // V4l2Allocator interface + void fill_v4l2_buffer(void *, V4l2Buffer &) const override; + + public: + V4l2MmapAllocator(int fd); + ~V4l2MmapAllocator() override; + + private: + V4l2RequestBuffers request_buffers(uint32_t nb_buffers); + // The mapping between buffer indices and their memory mapping + std::vector mapping_; + const int fd_; + }; + + class DmabufAllocator : public V4l2Allocator { + // MemoryResource interface + void *do_allocate(std::size_t bytes, std::size_t alignment) override; + void do_deallocate(void *p, std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) override; + bool do_is_equal(const std::pmr::memory_resource &other) const noexcept override; + + // V4l2Allocator interface + void fill_v4l2_buffer(void *, V4l2Buffer &) const override; + void begin_cpu_access(void *) const override; + void end_cpu_access(void *) const override; + + public: + DmabufAllocator(int fd, std::unique_ptr &&); + ~DmabufAllocator() override; + + private: + // The mapping between buffer fds and their memory mapping + std::map mapping_; + // Dmabuf heap where the memory is allocated + std::unique_ptr dmabuf_heap_; + // A helper to get the fd from a pointer + int fd(void *) const; + }; + + std::unique_ptr v4l2_allocator_; + using ObjectPool = Metavision::SharedObjectPool>; + using BufferPtr = ObjectPool::ptr_type; + using Allocator = ObjectPool::value_type::allocator_type; + ObjectPool pool_; + + // List of queued buffers to prevent them from going back to the ObjectPool + BufferPtr queued_buffers_[device_buffer_number]; + + // A helper to get the right allocator, and calls to its methods + V4l2Allocator &v4l2_alloc(BufferPtr &) const; + void fill_v4l2_buffer(BufferPtr &, V4l2Buffer &) const; + void begin_cpu_access(BufferPtr &) const; + void end_cpu_access(BufferPtr &) const; }; } // namespace Metavision diff --git a/hal_psee_plugins/include/boards/v4l2/v4l2_device.h b/hal_psee_plugins/include/boards/v4l2/v4l2_device.h index b9867802d..96f46b242 100644 --- a/hal_psee_plugins/include/boards/v4l2/v4l2_device.h +++ b/hal_psee_plugins/include/boards/v4l2/v4l2_device.h @@ -26,26 +26,19 @@ namespace Metavision { void raise_error(const std::string &str); -using V4l2Capability = struct v4l2_capability; -using V4l2Buffer = struct v4l2_buffer; -using V4l2RequestBuffers = struct v4l2_requestbuffers; +using V4l2Capability = struct v4l2_capability; class V4L2DeviceControl : public DeviceControl { V4l2Capability cap_; int fd_ = -1; public: - template - static typename std::vector::const_iterator iterator_cast(Data *ptr) { - return typename std::vector::const_iterator(reinterpret_cast(ptr)); - } - /* Count the number of bytes received in the buffer. The complexity is log(n) */ template static std::size_t nb_not_null_data(const Data *const buf_beg_addr, std::size_t length_in_bytes) { auto is_not_null = [](const auto &d) { return d != 0; }; - auto beg = iterator_cast(buf_beg_addr); - auto end = beg + length_in_bytes / sizeof(*beg); + auto beg = reinterpret_cast(buf_beg_addr); + auto end = beg + length_in_bytes / sizeof(uint64_t); auto it_pp = std::partition_point(beg, end, is_not_null); return std::distance(beg, it_pp) * sizeof(*beg); @@ -56,10 +49,6 @@ class V4L2DeviceControl : public DeviceControl { V4l2Capability get_capability() const; - V4l2RequestBuffers request_buffers(v4l2_memory memory, uint32_t nb_buffers); - V4l2Buffer query_buffer(v4l2_memory memory_type, uint32_t buf_index); - int queue_buffer(V4l2Buffer &buffer); - int dequeue_buffer(V4l2Buffer *buffer); int get_fd() const { return fd_; } diff --git a/hal_psee_plugins/include/boards/v4l2/v4l2_hardware_identification.h b/hal_psee_plugins/include/boards/v4l2/v4l2_hardware_identification.h index c26f00788..6d795eee9 100644 --- a/hal_psee_plugins/include/boards/v4l2/v4l2_hardware_identification.h +++ b/hal_psee_plugins/include/boards/v4l2/v4l2_hardware_identification.h @@ -12,7 +12,6 @@ class V4l2HwIdentification : public I_HW_Identification { public: V4l2HwIdentification(const V4l2Capability cap, const std::shared_ptr &plugin_sw_info, const SensorDescriptor &sensor_descriptor); - virtual long get_system_id() const override; virtual SensorInfo get_sensor_info() const override; virtual std::vector get_available_data_encoding_formats() const override; virtual std::string get_current_data_encoding_format() const override; diff --git a/hal_psee_plugins/include/boards/v4l2/v4l2_user_ptr_data.h b/hal_psee_plugins/include/boards/v4l2/v4l2_user_ptr_data.h deleted file mode 100644 index 2be16fd98..000000000 --- a/hal_psee_plugins/include/boards/v4l2/v4l2_user_ptr_data.h +++ /dev/null @@ -1,66 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_HAL_PSEE_PLUGINS_V4L2_USER_PTR_DATA_H -#define METAVISION_HAL_PSEE_PLUGINS_V4L2_USER_PTR_DATA_H - -#include -#include -#include - -namespace Metavision { - -/** Manage buffer manipulation through the V4L2 interface. - * In this implementation, buffers are allocated in user space using a dma_buf allocator. This allocator allocates - * continuous buffers in physical memory which is necessary as buffers are used by DMA without gather/scatter - * facility. - */ -class DmaBufHeap; -class V4L2DeviceControl; - -class V4l2DeviceUserPtr { -public: - V4l2DeviceUserPtr(std::shared_ptr device, const std::string &heap_path, const std::string &heap_name, - std::size_t length = 8 * 1024 * 1024, unsigned int nb_buffers = 32); - - virtual ~V4l2DeviceUserPtr(); - - /** Poll a MIPI frame buffer through the V4L2 interface. - * Return the buffer index. - * */ - int poll_buffer() const; - - /** Queue the buffer designed by the index to the driver. */ - void release_buffer(int idx) const; - - unsigned int get_nb_buffers() const; - - /** Return the buffer address and size (in bytes) designed by the index. */ - std::pair get_buffer_desc(int idx) const; - - void free_buffers(); - -private: - struct BufferDesc { - void *start; - unsigned int dmabuf_fd; - }; - - std::shared_ptr device_; - std::unique_ptr dma_buf_heap_; - std::size_t length_; - std::vector buffers_desc_; - - void allocate_buffers(unsigned int nb_buffers); -}; -} // namespace Metavision - -#endif // METAVISION_HAL_PSEE_PLUGINS_V4L2_USER_PTR_DATA_H diff --git a/hal_psee_plugins/include/devices/gen41/gen41_evk2_tz_device.h b/hal_psee_plugins/include/devices/gen41/gen41_evk2_tz_device.h index 40295220a..3c8cc5143 100644 --- a/hal_psee_plugins/include/devices/gen41/gen41_evk2_tz_device.h +++ b/hal_psee_plugins/include/devices/gen41/gen41_evk2_tz_device.h @@ -48,6 +48,9 @@ class TzEvk2Gen41 : public TzPseeVideo, public TzIssdDevice, public TemperatureP protected: virtual void spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config); + static std::string ROOT_PREFIX; + static std::string SENSOR_PREFIX; + private: void temperature_init(); void lifo_control(bool enable, bool out_en, bool cnt_en); diff --git a/hal_psee_plugins/include/devices/gen41/gen41_tz_device.h b/hal_psee_plugins/include/devices/gen41/gen41_tz_device.h index 2ef301c4a..a3af9a327 100644 --- a/hal_psee_plugins/include/devices/gen41/gen41_tz_device.h +++ b/hal_psee_plugins/include/devices/gen41/gen41_tz_device.h @@ -47,6 +47,9 @@ class TzGen41 : public TzIssdDevice, public IlluminationProvider, public TzMainD protected: virtual void spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &config); + static std::string ROOT_PREFIX; + static std::string SENSOR_PREFIX; + private: void time_base_config(bool external, bool master); void lifo_control(bool enable, bool out_en, bool cnt_en); diff --git a/hal_psee_plugins/include/devices/imx636/imx636_evk2_esp_tz_device.h b/hal_psee_plugins/include/devices/imx636/imx636_evk2_esp_tz_device.h new file mode 100644 index 000000000..4d9329266 --- /dev/null +++ b/hal_psee_plugins/include/devices/imx636/imx636_evk2_esp_tz_device.h @@ -0,0 +1,68 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_IMX636_EVK2_TZ_DEVICE_H +#define METAVISION_HAL_IMX636_EVK2_TZ_DEVICE_H + +#include "metavision/psee_hw_layer/devices/psee-video/tz_psee_video.h" +#include "devices/treuzell/tz_issd_device.h" +#include "metavision/psee_hw_layer/devices/treuzell/tz_regmap_device.h" +#include "metavision/psee_hw_layer/facilities/tz_monitoring.h" +#include "metavision/psee_hw_layer/devices/treuzell/tz_main_device.h" +#include "devices/common/evk2_system_control.h" + +namespace Metavision { + +class TzEvk2Imx636Esp : public TzPseeVideo, + public TzIssdDevice, + public TemperatureProvider, + public IlluminationProvider { +public: + TzEvk2Imx636Esp(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent); + virtual ~TzEvk2Imx636Esp(); + static std::shared_ptr build(std::shared_ptr cmd, uint32_t dev_id, + std::shared_ptr parent); + static bool can_build(std::shared_ptr, uint32_t dev_id); + + virtual void start(); + virtual void stop(); + virtual std::list get_supported_formats() const override; + StreamFormat get_output_format() const override; + virtual long get_system_id(); + virtual bool set_mode_standalone(); + virtual bool set_mode_master(); + virtual bool set_mode_slave(); + virtual I_CameraSynchronization::SyncMode get_mode() const; + virtual I_HW_Identification::SensorInfo get_sensor_info() { + return {4, 2, "IMX636"}; + } + long long get_sensor_id(); + virtual int get_illumination(); + virtual int get_temperature(); + +protected: + virtual void spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config); + + static std::string ROOT_PREFIX; + static std::string SENSOR_PREFIX; + +private: + void temperature_init(); + void lifo_control(bool enable, bool out_en, bool cnt_en); + void iph_mirror_control(bool enable); + + Evk2SystemControl sys_ctrl_; + I_CameraSynchronization::SyncMode sync_mode_; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_IMX636_EVK2_TZ_DEVICE_H diff --git a/hal_psee_plugins/include/devices/imx636/imx636_evk2_tz_device.h b/hal_psee_plugins/include/devices/imx636/imx636_evk2_tz_device.h index 516ba2e9f..a86c58794 100644 --- a/hal_psee_plugins/include/devices/imx636/imx636_evk2_tz_device.h +++ b/hal_psee_plugins/include/devices/imx636/imx636_evk2_tz_device.h @@ -48,6 +48,9 @@ class TzEvk2Imx636 : public TzPseeVideo, public TzIssdDevice, public Temperature protected: virtual void spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config); + static std::string ROOT_PREFIX; + static std::string SENSOR_PREFIX; + private: void temperature_init(); void lifo_control(bool enable, bool out_en, bool cnt_en); diff --git a/hal_psee_plugins/include/devices/imx636/imx636_tz_device.h b/hal_psee_plugins/include/devices/imx636/imx636_tz_device.h index d988b1790..b721e6abe 100644 --- a/hal_psee_plugins/include/devices/imx636/imx636_tz_device.h +++ b/hal_psee_plugins/include/devices/imx636/imx636_tz_device.h @@ -54,6 +54,9 @@ class TzImx636 : public TzIssdDevice, protected: virtual void spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config); + static std::string ROOT_PREFIX; + static std::string SENSOR_PREFIX; + private: void temperature_init(); void time_base_config(bool external, bool master); diff --git a/hal_psee_plugins/include/devices/imx636/register_maps/README.txt b/hal_psee_plugins/include/devices/imx636/register_maps/README.txt new file mode 100644 index 000000000..b30931e9c --- /dev/null +++ b/hal_psee_plugins/include/devices/imx636/register_maps/README.txt @@ -0,0 +1,2 @@ +To generate imx636_evk2_esp_registermap.h: +psee_regmap_header --regmap_name PseeEvk2Imx636RegisterMap --array_name 'PseeEvk2Imx636RegisterMap' --sensor_version '2.0' --header_file imx636_evk2_esp_registermap.h \ No newline at end of file diff --git a/hal_psee_plugins/include/devices/imx636/register_maps/imx636_evk2_esp_registermap.h b/hal_psee_plugins/include/devices/imx636/register_maps/imx636_evk2_esp_registermap.h new file mode 100644 index 000000000..e283aa01d --- /dev/null +++ b/hal_psee_plugins/include/devices/imx636/register_maps/imx636_evk2_esp_registermap.h @@ -0,0 +1,9458 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_IMX636_EVK2_ESP_REGISTERMAP_H +#define METAVISION_HAL_IMX636_EVK2_ESP_REGISTERMAP_H + +#include "metavision/psee_hw_layer/utils/regmap_data.h" + +static RegmapElement Imx636Evk2EspRegisterMap[] = { + // clang-format off + + {R, {"SYSTEM_CONTROL/GLOBAL_CONTROL", 0x0000}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"FORMAT", 2, 2, 0x2}}, + {A, {"raw", 0x0}}, + {A, {"2.0", 0x2}}, + {A, {"3.0", 0x3}}, + {F, {"CCAM_ID", 4, 2, 0x0}}, + {F, {"OUTPUT_FORMAT", 6, 2, 0x2}}, + {A, {"raw", 0x0}}, + {A, {"2.0", 0x2}}, + {A, {"3.0", 0x3}}, + + {R, {"SYSTEM_CONTROL/CLK_CONTROL", 0x0004}}, + {F, {"CORE_EN", 0, 1, 0x0}}, + {F, {"CORE_SOFT_RST", 1, 1, 0x0}}, + {F, {"CORE_REG_BANK_RST", 2, 1, 0x0}}, + {F, {"SENSOR_IF_EN", 4, 1, 0x0}}, + {F, {"SENSOR_IF_SOFT_RST", 5, 1, 0x0}}, + {F, {"SENSOR_IF_REG_BANK_RST", 6, 1, 0x0}}, + {F, {"HOST_IF_EN", 8, 1, 0x0}}, + {F, {"HOST_IF_SOFT_RST", 9, 1, 0x0}}, + {F, {"HOST_IF_REG_BANK_RST", 10, 1, 0x0}}, + {F, {"GLOBAL_RST", 16, 1, 0x0}}, + + {R, {"SYSTEM_CONTROL/TIME_BASE_CONTROL", 0x0008}}, + {F, {"ENABLE", 0, 1, 0x0}}, + {F, {"EXT_SYNC_MODE", 1, 1, 0x0}}, + {F, {"EXT_SYNC_ENABLE", 2, 1, 0x0}}, + {F, {"EXT_SYNC_MASTER", 3, 1, 0x0}}, + {F, {"EXT_SYNC_MASTER_SEL", 4, 1, 0x0}}, + {F, {"ENABLE_EXT_SYNC", 5, 1, 0x0}}, + {F, {"ENABLE_CAM_SYNC", 6, 1, 0x0}}, + + {R, {"SYSTEM_CONTROL/TIME_BASE_RESOLUTION", 0x000C}}, + {F, {"CLKS", 0, 16, 0x64}}, + + {R, {"SYSTEM_CONTROL/IMU_CONTROL", 0x0010}}, + {F, {"ENABLE", 0, 1, 0x0}}, + + {R, {"SYSTEM_CONTROL/EVT_DATA_FORMATTER_CONTROL", 0x0014}}, + {F, {"ENABLE", 0, 1, 0x0}}, + {F, {"BYPASS", 1, 1, 0x0}}, + + {R, {"SYSTEM_CONTROL/EVT_MERGE_CONTROL", 0x0018}}, + {F, {"ENABLE", 0, 1, 0x0}}, + {F, {"BYPASS", 1, 1, 0x0}}, + {F, {"SOURCE", 2, 1, 0x0}}, + + {R, {"SYSTEM_CONTROL/TH_RECOVERY_CONTROL", 0x0044}}, + {F, {"ENABLE", 0, 1, 0x0}}, + {F, {"BYPASS", 1, 1, 0x0}}, + + {R, {"SYSTEM_CONTROL/TS_CHECKER_CONTROL", 0x0048}}, + {F, {"BYPASS", 0, 1, 0x0}}, + {F, {"THRESHOLD", 1, 24, 0x186A0}}, + + {R, {"SYSTEM_CONTROL/TS_CHECKER_EVT_UI_CNT", 0x004C}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"SYSTEM_CONTROL/TS_CHECKER_EVT_BROKEN_CNT", 0x0050}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"SYSTEM_CONTROL/TS_CHECKER_EVT_UK_ERR_CNT", 0x0054}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"SYSTEM_CONTROL/BOARD_CONTROL_STATUS", 0x0058}}, + {F, {"ENET_PWDN", 0, 1, 0x0}}, + {F, {"PAV_15W", 1, 1, 0x0}}, + {F, {"PAV_4P5W", 2, 1, 0x0}}, + {F, {"PAV_7P5W", 3, 1, 0x0}}, + {F, {"USB_EN_READ_PAV", 4, 1, 0x0}}, + {F, {"USB3_EN_REF_CLK", 5, 1, 0x1}}, + {F, {"USBCC_MUX_EN_N", 6, 1, 0x0}}, + {F, {"VMON_ALERT", 7, 1, 0x0}}, + {F, {"VMON_I2C_EN_LVLSHFT", 8, 1, 0x0}}, + {F, {"VERSION", 10, 2, 0x0}}, + {F, {"USB2PHY_RESETB", 12, 1, 0x1}}, + {F, {"ENET_RESET_N", 13, 1, 0x0}}, + {F, {"LDO_2V5_1V0_EN", 14, 1, 0x0}}, + {F, {"VMON_PU_TO_1V8", 15, 1, 0x0}}, + {F, {"USB_C_OUT1", 16, 1, 0x0}}, + {F, {"USB_C_OUT2", 17, 1, 0x0}}, + + {R, {"SYSTEM_CONTROL/IO_CONTROL", 0x005C}}, + {F, {"SYNC_IN", 0, 1, 0x0}}, + {F, {"TRIG_IN", 1, 1, 0x0}}, + {F, {"SYNC_OUT_EN_FLT_CHK", 4, 1, 0x0}}, + {F, {"SYNC_OUT_EN_HSIDE", 5, 1, 0x0}}, + {F, {"SYNC_OUT_FAULT_ALERT", 6, 1, 0x0}}, + {F, {"SYNC_OUT", 7, 1, 0x0}}, + {F, {"SYNC_OUT_MODE", 8, 4, 0x0}}, + + {R, {"SYSTEM_CONTROL/OUT_TH_RECOVERY_CONTROL", 0x0060}}, + {F, {"ENABLE", 0, 1, 0x1}}, + {F, {"BYPASS", 1, 1, 0x1}}, + + {R, {"SYSTEM_CONTROL/OUT_TS_CHECKER_CONTROL", 0x0064}}, + {F, {"BYPASS", 0, 1, 0x1}}, + {F, {"THRESHOLD", 1, 24, 0x186A0}}, + + {R, {"SYSTEM_CONTROL/OUT_TS_CHECKER_EVT_UI_CNT", 0x0068}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"SYSTEM_CONTROL/OUT_TS_CHECKER_EVT_BROKEN_CNT", 0x006C}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"SYSTEM_CONTROL/OUT_TS_CHECKER_EVT_UK_ERR_CNT", 0x0070}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/TEMP", 0x0200}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VCC_INT", 0x0202}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VCC_AUX", 0x0204}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VP_VN", 0x0206}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VREFP", 0x0208}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VREFN", 0x020A}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VCC_BRAM", 0x020C}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SUPPLY_OFFSET", 0x0210}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/OFFSET", 0x0212}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/GAIN_ERROR", 0x0214}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX0", 0x0220}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX1", 0x0222}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX2", 0x0224}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX3", 0x0226}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX4", 0x0228}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX5", 0x022A}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX6", 0x022C}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX7", 0x022E}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX8", 0x0230}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX9", 0x0232}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX10", 0x0234}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX11", 0x0236}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX12", 0x0238}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX13", 0x023A}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX14", 0x023C}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/VAUX15", 0x023E}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MAX_TEMP", 0x0240}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MAX_VCC_INT", 0x0242}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MAX_VCC_AUX", 0x0244}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MAX_VCC_BRAM", 0x0246}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MIN_TEMP", 0x0248}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MIN_VCC_INT", 0x024A}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MIN_VCC_AUX", 0x024C}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/MIN_VCC_BRAM", 0x024E}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/FLAGS", 0x027E}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/CONF_REG0", 0x0280}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/CONF_REG1", 0x0282}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/CONF_REG2", 0x0284}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG0", 0x0290}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG1", 0x0292}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG2", 0x0294}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG3", 0x0296}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG4", 0x0298}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG5", 0x029A}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG6", 0x029C}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/SEQ_REG7", 0x029E}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG0", 0x02A0}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG1", 0x02A2}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG2", 0x02A4}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG3", 0x02A6}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG4", 0x02A8}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG5", 0x02AA}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG6", 0x02AC}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG7", 0x02AE}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG8", 0x02B0}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG9", 0x02B2}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG10", 0x02B4}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG11", 0x02B6}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG12", 0x02B8}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG13", 0x02BA}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG14", 0x02BC}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR_XADC/ALARM_THR_REG15", 0x02BE}}, + {F, {"VALUE", 0, 16, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR/EVT_ENABLE", 0x0300}}, + {F, {"ALL_EVT", 0, 1, 0x0}}, + {F, {"TEMP_EVT", 1, 1, 0x0}}, + {F, {"VCC_INT_EVT", 2, 1, 0x0}}, + {F, {"VCC_AUX_EVT", 3, 1, 0x0}}, + {F, {"VCC_BRAM_EVT", 4, 1, 0x0}}, + {F, {"ALL_ALARM", 8, 1, 0x0}}, + {F, {"OVER_TEMP_ALARM", 9, 1, 0x0}}, + {F, {"USER_TEMP_ALARM", 10, 1, 0x0}}, + {F, {"VCC_INT_ALARM", 11, 1, 0x0}}, + {F, {"VCC_AUX_ALARM", 12, 1, 0x0}}, + {F, {"VCC_BRAM_ALARM", 13, 1, 0x0}}, + {F, {"SYSTEM_POWER_DOWN", 16, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR/EVT_PERIOD", 0x0304}}, + {F, {"VALUE", 0, 24, 0x186A0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR/EXT_TEMP_CONTROL", 0x0308}}, + {F, {"STATUS_SYS_POWER_DOWN", 0, 1, 0x0}}, + {F, {"EXT_TEMP_MONITOR_EN", 1, 1, 0x0}}, + {F, {"EXT_TEMP_MONITOR_SPI_EN", 2, 1, 0x0}}, + {F, {"REMOTE_TEMP_MONITOR_EN", 3, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR/EVK_EXT_TEMP_VALUE", 0x030C}}, + {F, {"VALUE", 0, 22, 0x0}}, + + {R, {"SYSTEM_MONITOR/TEMP_VCC_MONITOR/REMOTE_TEMP_ADDR", 0x0310}}, + {F, {"VALUE", 0, 24, 0x2030C}}, + + {R, {"SYSTEM_MONITOR/ATIS_IF_MONITOR/CFG_ENABLE", 0x0340}}, + {F, {"ALL_EVT", 0, 1, 0x0}}, + {F, {"TD_IDLE_TIME_EVT", 1, 1, 0x0}}, + {F, {"TD_IDLE_TIMEOUT_EVT", 2, 1, 0x0}}, + {F, {"APS_IDLE_TIME_EVT", 3, 1, 0x0}}, + {F, {"APS_IDLE_TIMEOUT_EVT", 4, 1, 0x0}}, + {F, {"GLOBAL_ILLUMINATION_EVT", 5, 1, 0x0}}, + {F, {"EM_TRIGGER_SEQ_EVT", 6, 1, 0x0}}, + {F, {"REFRACTORY_CLOCK_EVT", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/ATIS_IF_MONITOR/CFG_IDLE_TIME_THR", 0x0344}}, + {F, {"VALUE", 0, 26, 0x2710}}, + + {R, {"SYSTEM_MONITOR/ATIS_IF_MONITOR/CFG_IDLE_TIMEOUT_THR", 0x0348}}, + {F, {"VALUE", 0, 26, 0x2710}}, + + {R, {"SYSTEM_MONITOR/ATIS_IF_MONITOR/STAT_GLOBAL_ILLUMINATION", 0x034C}}, + {F, {"DATA", 0, 26, 0x0}}, + {F, {"VALID", 31, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/ATIS_IF_MONITOR/STAT_REFRACTORY_CLOCK", 0x0350}}, + {F, {"DATA", 0, 24, 0x0}}, + + {R, {"SYSTEM_MONITOR/EXT_TRIGGERS/ENABLE", 0x0360}}, + {F, {"TRIGGER_0", 0, 1, 0x0}}, + {F, {"TRIGGER_1", 1, 1, 0x0}}, + {F, {"TRIGGER_2", 2, 1, 0x0}}, + {F, {"TRIGGER_3", 3, 1, 0x0}}, + {F, {"TRIGGER_4", 4, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/EXT_TRIGGERS/OUT_ENABLE", 0x0364}}, + {F, {"VALUE", 0, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/EXT_TRIGGERS/OUT_PULSE_PERIOD", 0x0368}}, + {F, {"", 0, 32, 0x64}}, + + {R, {"SYSTEM_MONITOR/EXT_TRIGGERS/OUT_PULSE_WIDTH", 0x036C}}, + {F, {"", 0, 32, 0x1}}, + + {R, {"SYSTEM_MONITOR/EXT_TRIGGERS/OUT_REGISTER_MODE", 0x0370}}, + {F, {"ENABLE", 0, 1, 0x0}}, + {F, {"VALUE", 1, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/WHO_AM_I", 0x0400}}, + {F, {"VALUE", 0, 8, 0xEA}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_SMPLRT_DIV", 0x0400}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_MST_ODR_CONFIG", 0x0400}}, + {F, {"I2C_MST_ODR_CONFIG", 0, 4, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_CONFIG_1", 0x0404}}, + {F, {"GYRO_FCHOICE", 0, 1, 0x1}}, + {F, {"GYRO_FS_SEL", 1, 2, 0x0}}, + {F, {"GYRO_DLPFCFG", 3, 3, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_MST_CTRL", 0x0404}}, + {F, {"I2C_MST_CLK", 0, 4, 0x0}}, + {F, {"I2C_MST_P_NSR", 4, 1, 0x0}}, + {F, {"MULT_MST_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/SELF_TEST_X_GYRO", 0x0408}}, + {F, {"XG_ST_DATA", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_CONFIG_2", 0x0408}}, + {F, {"GYRO_AVGCFG", 0, 3, 0x0}}, + {F, {"ZGYRO_CTEN", 3, 1, 0x0}}, + {F, {"YGYRO_CTEN", 4, 1, 0x0}}, + {F, {"XGYRO_CTEN", 5, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_MST_DELAY_CTRL", 0x0408}}, + {F, {"I2C_SLV0_DELAY_EN", 0, 1, 0x0}}, + {F, {"I2C_SLV1_DELAY_EN", 1, 1, 0x0}}, + {F, {"I2C_SLV2_DELAY_EN", 2, 1, 0x0}}, + {F, {"I2C_SLV3_DELAY_EN", 3, 1, 0x0}}, + {F, {"I2C_SLV4_DELAY_EN", 4, 1, 0x0}}, + {F, {"DELAY_ES_SHADOW", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/USER_CTRL", 0x040C}}, + {F, {"I2C_MST_RST", 1, 1, 0x0}}, + {F, {"SRAM_RST", 2, 1, 0x0}}, + {F, {"DMP_RST", 3, 1, 0x0}}, + {F, {"I2C_IF_DIS", 4, 1, 0x0}}, + {F, {"I2C_MST_EN", 5, 1, 0x0}}, + {F, {"FIFO_EN", 6, 1, 0x0}}, + {F, {"DMP_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/SELF_TEST_Y_GYRO", 0x040C}}, + {F, {"YG_ST_DATA", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/XG_OFFS_USRH", 0x040C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV0_ADDR", 0x040C}}, + {F, {"I2C_ID_0", 0, 7, 0x0}}, + {F, {"I2C_SLV0_RNW", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/SELF_TEST_Z_GYRO", 0x0410}}, + {F, {"ZG_ST_DATA", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/XG_OFFS_USRL", 0x0410}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV0_REG", 0x0410}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/LP_CONFIG", 0x0414}}, + {F, {"GYRO_CYCLE", 4, 1, 0x0}}, + {F, {"ACCEL_CYCLE", 5, 1, 0x0}}, + {F, {"I2C_MST_CYCLE", 6, 1, 0x1}}, + + {R, {"SYSTEM_MONITOR/IMU/YG_OFFS_USRH", 0x0414}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV0_CTRL", 0x0414}}, + {F, {"I2C_SLV0_LENG", 0, 4, 0x0}}, + {F, {"I2C_SLV0_GRP", 4, 1, 0x0}}, + {F, {"I2C_SLV0_REG_DIS", 5, 1, 0x0}}, + {F, {"I2C_SLV0_BYTE_SW", 6, 1, 0x0}}, + {F, {"I2C_SLV0_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/PWR_MGMT_1", 0x0418}}, + {F, {"CLKSEL", 0, 3, 0x0}}, + {F, {"TEMP_DIS", 3, 1, 0x0}}, + {F, {"LP_EN", 5, 1, 0x0}}, + {F, {"SLEEP", 6, 1, 0x0}}, + {F, {"DEVICE_RESET", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/YG_OFFS_USRL", 0x0418}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV0_DO", 0x0418}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/PWR_MGMT_2", 0x041C}}, + {F, {"DISABLE_GYRO", 0, 3, 0x6}}, + {F, {"DISABLE_ACCEL", 3, 3, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ZG_OFFS_USRH", 0x041C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV1_ADDR", 0x041C}}, + {F, {"I2C_ID_1", 0, 7, 0x0}}, + {F, {"I2C_SLV1_RNW", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ZG_OFFS_USRL", 0x0420}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV1_REG", 0x0420}}, + {F, {"I2C_SLV1_REG", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ODR_ALIGN_EN", 0x0424}}, + {F, {"ODR_ALIGN_EN", 0, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV1_CTRL", 0x0424}}, + {F, {"I2C_SLV1_LENG", 0, 4, 0x0}}, + {F, {"I2C_SLV1_GRP", 4, 1, 0x0}}, + {F, {"I2C_SLV1_REG_DIS", 5, 1, 0x0}}, + {F, {"I2C_SLV1_BYTE_SW", 6, 1, 0x0}}, + {F, {"I2C_SLV1_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV1_DO", 0x0428}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV2_ADDR", 0x042C}}, + {F, {"I2C_ID_2", 0, 7, 0x0}}, + {F, {"I2C_SLV2_RNW", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV2_REG", 0x0430}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV2_CTRL", 0x0434}}, + {F, {"I2C_SLV2_LENG", 0, 4, 0x0}}, + {F, {"I2C_SLV2_GRP", 4, 1, 0x0}}, + {F, {"I2C_SLV2_REG_DIS", 5, 1, 0x0}}, + {F, {"I2C_SLV2_BYTE_SW", 6, 1, 0x0}}, + {F, {"I2C_SLV2_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/SELF_TEST_X_ACCEL", 0x0438}}, + {F, {"XA_ST_DATA", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV2_DO", 0x0438}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_PIN_CFG", 0x043C}}, + {F, {"BYPASS_EN", 1, 1, 0x0}}, + {F, {"FSYNC_INT_MODE_EN", 2, 1, 0x0}}, + {F, {"ACTL_FSYNC", 3, 1, 0x0}}, + {F, {"INT_ANYRD_2CLEAR", 4, 1, 0x0}}, + {F, {"INT1_LATCH_INT_EN", 5, 1, 0x0}}, + {F, {"INT1_OPEN", 6, 1, 0x0}}, + {F, {"INT1_ACTL", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/SELF_TEST_Y_ACCEL", 0x043C}}, + {F, {"YA_ST_DATA", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV3_ADDR", 0x043C}}, + {F, {"I2C_ID_3", 0, 7, 0x0}}, + {F, {"I2C_SLV3_RNW", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_ENABLE", 0x0440}}, + {F, {"I2C_MST_INT_EN", 0, 1, 0x0}}, + {F, {"DMP_INT1_EN", 1, 1, 0x0}}, + {F, {"PLL_RDY_EN", 2, 1, 0x0}}, + {F, {"WOM_INT_EN", 3, 1, 0x0}}, + {F, {"REG_WOF_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/SELF_TEST_Z_ACCEL", 0x0440}}, + {F, {"ZA_ST_DATA", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_SMPLRT_DIV_1", 0x0440}}, + {F, {"VALUE", 0, 4, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV3_REG", 0x0440}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_ENABLE_1", 0x0444}}, + {F, {"RAW_DATA_0_RDY_EN", 0, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_SMPLRT_DIV_2", 0x0444}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV3_CTRL", 0x0444}}, + {F, {"I2C_SLV3_LENG", 0, 4, 0x0}}, + {F, {"I2C_SLV3_GRP", 4, 1, 0x0}}, + {F, {"I2C_SLV3_REG_DIS", 5, 1, 0x0}}, + {F, {"I2C_SLV3_BYTE_SW", 6, 1, 0x0}}, + {F, {"I2C_SLV3_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_ENABLE_2", 0x0448}}, + {F, {"FIFO_OVERFLOW_EN", 0, 5, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_INTEL_CTRL", 0x0448}}, + {F, {"ACCEL_INTEL_MODE_INT", 0, 1, 0x0}}, + {F, {"ACCEL_INTEL_EN", 1, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV3_DO", 0x0448}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_ENABLE_3", 0x044C}}, + {F, {"FIFO_WM_EN", 0, 5, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_WOM_THR", 0x044C}}, + {F, {"WOM_THRESHOLD", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV4_ADDR", 0x044C}}, + {F, {"I2C_ID_4", 0, 7, 0x0}}, + {F, {"I2C_SLV4_RNW", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/XA_OFFS_H", 0x0450}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_CONFIG", 0x0450}}, + {F, {"ACCEL_FCHOICE", 0, 1, 0x1}}, + {F, {"ACCEL_FS_SEL", 1, 2, 0x0}}, + {F, {"ACCEL_DLPFCFG", 3, 3, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV4_REG", 0x0450}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/XA_OFFS_L", 0x0454}}, + {F, {"VALUE", 1, 7, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_CONFIG_2", 0x0454}}, + {F, {"DEC3_CFG", 0, 2, 0x0}}, + {F, {"AZ_ST_EN_REG", 2, 1, 0x0}}, + {F, {"AY_ST_EN_REG", 3, 1, 0x0}}, + {F, {"AX_ST_EN_REG", 4, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV4_CTRL", 0x0454}}, + {F, {"I2C_SLV4_DLY", 0, 5, 0x0}}, + {F, {"I2C_SLV4_REG_DIS", 5, 1, 0x0}}, + {F, {"I2C_SLV4_BYTE_SW", 6, 1, 0x0}}, + {F, {"I2C_SLV4_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV4_DO", 0x0458}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_MST_STATUS", 0x045C}}, + {F, {"I2C_SLV0_NACK", 0, 1, 0x0}}, + {F, {"I2C_SLV1_NACK", 1, 1, 0x0}}, + {F, {"I2C_SLV2_NACK", 2, 1, 0x0}}, + {F, {"I2C_SLV3_NACK", 3, 1, 0x0}}, + {F, {"I2C_SLV4_NACK", 4, 1, 0x0}}, + {F, {"I2C_LOST_ARB", 5, 1, 0x0}}, + {F, {"I2C_SLV4_DONE", 6, 1, 0x0}}, + {F, {"PASS_THROUGH", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/YA_OFFS_H", 0x045C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/I2C_SLV4_DI", 0x045C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/YA_OFFS_L", 0x0460}}, + {F, {"VALUE", 1, 7, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_STATUS", 0x0464}}, + {F, {"I2C_MST_INT", 0, 1, 0x0}}, + {F, {"DMP_INT1", 1, 1, 0x0}}, + {F, {"PLL_RDY_INT", 2, 1, 0x0}}, + {F, {"WOM_INT", 3, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_STATUS_1", 0x0468}}, + {F, {"RAW_DATA_0_RDY_INT", 0, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ZA_OFFS_H", 0x0468}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_STATUS_2", 0x046C}}, + {F, {"FIFO_OVERFLOW_INT", 0, 5, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ZA_OFFS_L", 0x046C}}, + {F, {"VALUE", 1, 7, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/INT_STATUS_3", 0x0470}}, + {F, {"FIFO_WM_INT", 0, 5, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/DELAY_TIMEH", 0x04A0}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/TIMEBASE_CORRECTION_PLL", 0x04A0}}, + {F, {"TBC_PLL", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/DELAY_TIMEL", 0x04A4}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_XOUT_H", 0x04B4}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_XOUT_L", 0x04B8}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_YOUT_H", 0x04BC}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_YOUT_L", 0x04C0}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_ZOUT_H", 0x04C4}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/ACCEL_ZOUT_L", 0x04C8}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_XOUT_H", 0x04CC}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_XOUT_L", 0x04D0}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_YOUT_H", 0x04D4}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_YOUT_L", 0x04D8}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_ZOUT_H", 0x04DC}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/GYRO_ZOUT_L", 0x04E0}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/TEMP_OUT_H", 0x04E4}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/TEMP_OUT_L", 0x04E8}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_00", 0x04EC}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_01", 0x04F0}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_02", 0x04F4}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_03", 0x04F8}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_04", 0x04FC}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_05", 0x0500}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_06", 0x0504}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_07", 0x0508}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_08", 0x050C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_09", 0x0510}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_10", 0x0514}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_11", 0x0518}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_12", 0x051C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_13", 0x0520}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_14", 0x0524}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_15", 0x0528}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_16", 0x052C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_17", 0x0530}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_18", 0x0534}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_19", 0x0538}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_20", 0x053C}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_21", 0x0540}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_22", 0x0544}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/EXT_SLV_SENS_DATA_23", 0x0548}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FSYNC_CONFIG", 0x0548}}, + {F, {"EXT_SYNC_SET", 0, 4, 0x0}}, + {F, {"WOF_EDGE_INT", 4, 1, 0x0}}, + {F, {"WOF_DEGLITCH_EN", 5, 1, 0x0}}, + {F, {"DELAY_TIME_EN", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/TEMP_CONFIG", 0x054C}}, + {F, {"TEMP_DLPFCFG", 0, 3, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/MOD_CTRL_USR", 0x0550}}, + {F, {"REG_LP_DMP_EN", 0, 1, 0x1}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_EN_1", 0x0598}}, + {F, {"SLV_0_FIFO_EN", 0, 1, 0x0}}, + {F, {"SLV_1_FIFO_EN", 1, 1, 0x0}}, + {F, {"SLV_2_FIFO_EN", 2, 1, 0x0}}, + {F, {"SLV_3_FIFO_EN", 3, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_EN_2", 0x059C}}, + {F, {"TEMP_FIFO_EN", 0, 1, 0x0}}, + {F, {"GYRO_X_FIFO_EN", 1, 1, 0x0}}, + {F, {"GYRO_Y_FIFO_EN", 2, 1, 0x0}}, + {F, {"GYRO_Z_FIFO_EN", 3, 1, 0x0}}, + {F, {"ACCEL_FIFO_EN", 4, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_RST", 0x05A0}}, + {F, {"FIFO_RESET", 0, 5, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_MODE", 0x05A4}}, + {F, {"FIFO_MODE", 0, 5, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_COUNTH", 0x05C0}}, + {F, {"FIFO_CNT", 0, 5, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_COUNTL", 0x05C4}}, + {F, {"FIFO_CNT", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_R_W", 0x05C8}}, + {F, {"VALUE", 0, 8, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/DATA_RDY_STATUS", 0x05D0}}, + {F, {"RAW_DATA_RDY", 0, 4, 0x0}}, + {F, {"WOF_STATUS", 7, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/FIFO_CFG", 0x05D8}}, + {F, {"FIFO_CFG", 0, 1, 0x0}}, + + {R, {"SYSTEM_MONITOR/IMU/REG_BANK_SEL", 0x05FC}}, + {F, {"USER_BANK", 4, 2, 0x0}}, + + {R, {"SYSTEM_MONITOR/CONTROL/EVT_MERGE_CONTROL", 0x0600}}, + {F, {"ENABLE", 0, 1, 0x1}}, + {F, {"BYPASS", 1, 1, 0x0}}, + {F, {"SOURCE", 2, 2, 0x0}}, + + {R, {"SYSTEM_CONFIG/ID", 0x0800}}, + {F, {"VALUE", 0, 8, 0x32}}, + + {R, {"SYSTEM_CONFIG/VERSION", 0x0804}}, + {F, {"MICRO", 0, 8, 0x0}}, + {F, {"MINOR", 8, 8, 0x0}}, + {F, {"MAJOR", 16, 8, 0x0}}, + + {R, {"SYSTEM_CONFIG/BUILD_DATE", 0x0808}}, + {F, {"VALUE", 0, 32, 0x0}}, + + {R, {"SYSTEM_CONFIG/VERSION_CONTROL_ID", 0x080C}}, + {F, {"VALUE", 0, 32, 0x0}}, + + {R, {"ESP/CONTROL/CONTROL", 0x1000}}, + {F, {"BYPASS", 0, 1, 0x1}}, + {F, {"AFK_TIME_BASE_EN", 1, 1, 0x0}}, + {F, {"STC_TIME_BASE_EN", 2, 1, 0x0}}, + + {R, {"ESP/CONTROL/SPLITTER", 0x1004}}, + {F, {"BYPASS", 0, 1, 0x1}}, + + {R, {"ESP/CONTROL/IN_EDF", 0x1008}}, + {F, {"BYPASS", 0, 1, 0x0}}, + {F, {"ENABLE", 1, 1, 0x0}}, + + {R, {"ESP/CONTROL/AFK_FEATURE", 0x100C}}, + {F, {"VERSION", 0, 8, 0x0}}, + {F, {"PRESENT", 8, 1, 0x0}}, + + {R, {"ESP/CONTROL/STC_FEATURE", 0x1010}}, + {F, {"VERSION", 0, 8, 0x0}}, + {F, {"PRESENT", 8, 1, 0x0}}, + + {R, {"ESP/CONTROL/ERC_FEATURE", 0x1014}}, + {F, {"VERSION", 0, 8, 0x0}}, + {F, {"PRESENT", 8, 1, 0x0}}, + + {R, {"ESP/CONTROL/GPAFK_FEATURE", 0x1018}}, + {F, {"VERSION_MICRO", 0, 8, 0x0}}, + {F, {"VERSION_MINOR", 8, 8, 0x0}}, + {F, {"VERSION_MAJOR", 16, 8, 0x0}}, + {F, {"PRESENT", 24, 1, 0x0}}, + + {R, {"ESP/CONTROL/OUT_GEN_LAST_CONTROL", 0x1020}}, + {F, {"BYPASS", 0, 1, 0x0}}, + {F, {"ENABLE", 1, 1, 0x1}}, + {F, {"GEN_LAST", 2, 1, 0x1}}, + + {R, {"ESP/CONTROL/OUT_TH_RECOVERY_CONTROL", 0x1024}}, + {F, {"ENABLE", 0, 1, 0x1}}, + {F, {"BYPASS", 1, 1, 0x1}}, + + {R, {"ESP/CONTROL/OUT_TS_CHECKER_CONTROL", 0x1028}}, + {F, {"BYPASS", 0, 1, 0x1}}, + {F, {"THRESHOLD", 1, 24, 0x186A0}}, + + {R, {"ESP/CONTROL/OUT_TS_CHECKER_EVT_UI_CNT", 0x102C}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"ESP/CONTROL/OUT_TS_CHECKER_EVT_BROKEN_CNT", 0x1030}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"ESP/CONTROL/OUT_TS_CHECKER_EVT_UK_ERR_CNT", 0x1034}}, + {F, {"TIME_LOW", 0, 16, 0x0}}, + {F, {"TIME_HIGH", 16, 16, 0x0}}, + + {R, {"ESP/AFK/pipeline_control", 0x1100}}, + {F, {"enable", 0, 1, 0x0}}, + {F, {"drop_nbackpressure", 1, 1, 0x0}}, + {F, {"bypass", 2, 1, 0x0}}, + + {R, {"ESP/AFK/afk_param", 0x1104}}, + {F, {"counter_low", 0, 3, 0x4}}, + {F, {"counter_high", 3, 3, 0x6}}, + {F, {"invert", 6, 1, 0x0}}, + {F, {"drop_disable", 7, 1, 0x0}}, + + {R, {"ESP/AFK/filter_period", 0x1108}}, + {F, {"min_cutoff_period", 0, 8, 0xF}}, + {F, {"max_cutoff_period", 8, 8, 0x9C}}, + {F, {"inverted_duty_cycle", 16, 4, 0x8}}, + + {R, {"ESP/AFK/invalidation", 0x11C0}}, + {F, {"dt_fifo_wait_time", 0, 12, 0x5A0}}, + {F, {"dt_fifo_timeout", 12, 12, 0x5A}}, + {F, {"in_parallel", 24, 4, 0xA}}, + {F, {"flag_inv_busy", 28, 1, 0x0}}, + + {R, {"ESP/AFK/initialisation", 0x11C4}}, + {F, {"req_init", 0, 1, 0x0}}, + {F, {"flag_init_busy", 1, 1, 0x0}}, + {F, {"flag_init_done", 2, 1, 0x0}}, + + {R, {"ESP/AFK/icn_sram_ctrl", 0x11C8}}, + {F, {"req_trigger", 0, 1, 0x0}}, + {F, {"req_type", 1, 1, 0x0}}, + {F, {"data_sel", 2, 3, 0x0}}, + + {R, {"ESP/AFK/icn_sram_address", 0x11CC}}, + {F, {"x_addr", 0, 11, 0x0}}, + {F, {"y_addr", 16, 11, 0x0}}, + + {R, {"ESP/AFK/icn_sram_data", 0x11D0}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/AFK/shadow_ctrl", 0x11D4}}, + {F, {"timer_en", 0, 1, 0x0}}, + {F, {"irq_sw_override", 1, 1, 0x0}}, + {F, {"reset_on_copy", 2, 1, 0x1}}, + + {R, {"ESP/AFK/shadow_timer_threshold", 0x11D8}}, + {F, {"timer_threshold", 0, 32, 0x3E8}}, + + {R, {"ESP/AFK/shadow_status", 0x11DC}}, + {F, {"shadow_valid", 0, 1, 0x0}}, + {F, {"shadow_overrun", 1, 1, 0x0}}, + + {R, {"ESP/AFK/total_evt_cnt", 0x11E0}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/AFK/flicker_evt_cnt", 0x11E4}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/AFK/output_vector_cnt", 0x11E8}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/AFK/chicken0_bits", 0x12C0}}, + {F, {"powerdown_enable", 0, 1, 0x1}}, + {F, {"inv_powerdown_enable", 1, 1, 0x1}}, + {F, {"sram_powerdown_enable", 2, 1, 0x0}}, + {F, {"sram_clk_gating_enable", 3, 1, 0x1}}, + {F, {"enable_inv_abs_timebase", 4, 1, 0x1}}, + + {R, {"ESP/AFK/chicken1_bits", 0x12C4}}, + {F, {"enable_inv_alr_last_ts", 0, 1, 0x1}}, + {F, {"enable_inv_alr_last_burst", 1, 1, 0x1}}, + {F, {"sram_read_margin_set", 2, 2, 0x1}}, + {F, {"sram_write_margin_set", 4, 2, 0x1}}, + {F, {"enable_inv_abs_threshold", 16, 12, 0x80}}, + + {R, {"ESP/AFK/chicken2_bits", 0x12C8}}, + {F, {"alr_sram_powerdown_enable", 0, 10, 0x0}}, + {F, {"str_sram0_powerdown_enable", 10, 10, 0x0}}, + {F, {"str_sram1_powerdown_enable", 20, 10, 0x0}}, + + {R, {"ESP/STC/pipeline_control", 0x1300}}, + {F, {"enable", 0, 1, 0x0}}, + {F, {"drop_nbackpressure", 1, 1, 0x0}}, + {F, {"bypass", 2, 1, 0x0}}, + + {R, {"ESP/STC/stc_param", 0x1304}}, + {F, {"enable", 0, 1, 0x0}}, + {F, {"threshold", 1, 19, 0x2710}}, + {F, {"disable_stc_cut_trail", 24, 1, 0x0}}, + + {R, {"ESP/STC/trail_param", 0x1308}}, + {F, {"enable", 0, 1, 0x0}}, + {F, {"threshold", 1, 19, 0x186A0}}, + + {R, {"ESP/STC/timestamping", 0x130C}}, + {F, {"prescaler", 0, 5, 0xD}}, + {F, {"multiplier", 5, 4, 0x1}}, + {F, {"enable_rightshift_round", 9, 1, 0x1}}, + {F, {"enable_last_ts_update_at_every_event", 16, 1, 0x0}}, + + {R, {"ESP/STC/invalidation", 0x13C0}}, + {F, {"dt_fifo_wait_time", 0, 12, 0x4}}, + {F, {"dt_fifo_timeout", 12, 12, 0x118}}, + {F, {"in_parallel", 24, 4, 0xA}}, + {F, {"flag_inv_busy", 28, 1, 0x0}}, + + {R, {"ESP/STC/initialisation", 0x13C4}}, + {F, {"req_init", 0, 1, 0x0}}, + {F, {"flag_init_busy", 1, 1, 0x0}}, + {F, {"flag_init_done", 2, 1, 0x0}}, + + {R, {"ESP/STC/icn_sram_ctrl", 0x13C8}}, + {F, {"req_trigger", 0, 1, 0x0}}, + {F, {"req_type", 1, 1, 0x0}}, + {F, {"data_sel", 2, 1, 0x0}}, + + {R, {"ESP/STC/icn_sram_address", 0x13CC}}, + {F, {"x_addr", 0, 11, 0x0}}, + {F, {"y_addr", 16, 11, 0x0}}, + + {R, {"ESP/STC/icn_sram_data", 0x13D0}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/STC/shadow_ctrl", 0x13D4}}, + {F, {"timer_en", 0, 1, 0x0}}, + {F, {"irq_sw_override", 1, 1, 0x0}}, + {F, {"reset_on_copy", 2, 1, 0x1}}, + + {R, {"ESP/STC/shadow_timer_threshold", 0x13D8}}, + {F, {"timer_threshold", 0, 32, 0x3E8}}, + + {R, {"ESP/STC/shadow_status", 0x13DC}}, + {F, {"shadow_valid", 0, 1, 0x0}}, + {F, {"shadow_overrun", 1, 1, 0x0}}, + + {R, {"ESP/STC/total_evt_cnt", 0x13E0}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/STC/stc_evt_cnt", 0x13E4}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/STC/trail_evt_cnt", 0x13E8}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/STC/output_vector_cnt", 0x13EC}}, + {F, {"val", 0, 32, 0x0}}, + + {R, {"ESP/STC/chicken0_bits", 0x14C0}}, + {F, {"powerdown_enable", 0, 1, 0x1}}, + {F, {"inv_powerdown_enable", 1, 1, 0x1}}, + {F, {"sram_powerdown_enable", 2, 1, 0x0}}, + {F, {"sram_clk_gating_enable", 3, 1, 0x1}}, + {F, {"enable_inv_abs_timebase", 4, 1, 0x1}}, + + {R, {"ESP/STC/chicken1_bits", 0x14C4}}, + {F, {"enable_inv_alr_last_ts", 0, 1, 0x1}}, + {F, {"unused0", 1, 15, 0x0}}, + {F, {"enable_inv_abs_threshold", 16, 12, 0x10}}, + + {R, {"ESP/STC/chicken2_bits", 0x14C8}}, + {F, {"alr_sram_powerdown_enable", 0, 10, 0x0}}, + + {R, {"ESP/OUT_EDF/pipeline_control", 0x1500}}, + {F, {"enable", 0, 1, 0x1}}, + {F, {"bypass", 1, 1, 0x0}}, + {F, {"preserve_last", 2, 1, 0x1}}, + {F, {"bypass_mem", 3, 2, 0x0}}, + {F, {"timeout", 16, 16, 0xFFFF}}, + + {R, {"ESP/OUT_EDF/event_type_en", 0x1504}}, + {F, {"en_left_td_low", 0, 1, 0x1}}, + {F, {"en_left_td_high", 1, 1, 0x1}}, + {F, {"en_left_aps_low", 2, 1, 0x1}}, + {F, {"en_left_aps_high", 3, 1, 0x1}}, + {F, {"en_right_td_low", 4, 1, 0x1}}, + {F, {"en_right_td_high", 5, 1, 0x1}}, + {F, {"en_right_aps_low", 6, 1, 0x1}}, + {F, {"en_right_aps_high", 7, 1, 0x1}}, + {F, {"en_time_high", 8, 1, 0x1}}, + {F, {"en_stereo_disp", 9, 1, 0x0}}, + {F, {"en_ext_trigger", 10, 1, 0x1}}, + {F, {"en_gray_level", 11, 1, 0x0}}, + {F, {"en_opt_flow", 12, 1, 0x0}}, + {F, {"en_orientation", 13, 1, 0x0}}, + {F, {"en_others", 14, 1, 0x1}}, + {F, {"en_continued", 15, 1, 0x1}}, + + {R, {"ESP/OUT_EDF/control", 0x1508}}, + {F, {"format", 0, 1, 0x0}}, + + {R, {"ESP/OUT_EDF/dfifo0_v_ecc", 0x150C}}, + {F, {"ecc_fifo0_err0", 0, 1, 0x0}}, + {F, {"ecc_fifo0_err1", 1, 1, 0x0}}, + + {R, {"ESP/OUT_EDF/dfifo0_d_ecc", 0x1510}}, + {F, {"ecc_fifo0_err0_addr", 0, 16, 0x0}}, + {F, {"ecc_fifo0_err1_addr", 16, 16, 0x0}}, + + {R, {"ESP/OUT_EDF/dfifo1_v_ecc", 0x1514}}, + {F, {"ecc_fifo1_err0", 0, 1, 0x0}}, + {F, {"ecc_fifo1_err1", 1, 1, 0x0}}, + + {R, {"ESP/OUT_EDF/dfifo1_d_ecc", 0x1518}}, + {F, {"ecc_fifo1_err0_addr", 0, 16, 0x0}}, + {F, {"ecc_fifo1_err1_addr", 16, 16, 0x0}}, + + {R, {"PS_HOST_IF/AXI_DMA_PACKETIZER/CONTROL", 0x2000}}, + {F, {"BYPASS", 0, 1, 0x0}}, + {F, {"ENABLE_COUNTER_PATTERN", 1, 1, 0x0}}, + + {R, {"PS_HOST_IF/AXI_DMA_PACKETIZER/PACKET_LENGTH", 0x2004}}, + {F, {"VALUE", 0, 32, 0x400}}, + + {R, {"PS_HOST_IF/AXIL_BRIDGE/CONTROL", 0x2100}}, + {F, {"BUS_ERROR_EN", 0, 1, 0x0}}, + + {R, {"PS_HOST_IF/AXIL_BRIDGE/ERROR_STATUS", 0x2104}}, + {F, {"CODE", 0, 16, 0x0}}, + {F, {"COUNT", 16, 16, 0x0}}, + + {R, {"ESP_BIS/ERC/pipeline_control", 0x3000}}, + {F, {"enable", 0, 1, 0x0}}, + {F, {"bypass", 1, 1, 0x0}}, + {F, {"fifo0_bypass", 2, 1, 0x0}}, + {F, {"fifo1_bypass", 3, 1, 0x0}}, + {F, {"fifo2_bypass", 4, 1, 0x0}}, + {F, {"delay_fifo_pd", 5, 2, 0x0}}, + {F, {"drop_grid_pd", 7, 2, 0x0}}, + {F, {"t_drop_pd", 9, 1, 0x0}}, + {F, {"drop_grid0_wtsel", 10, 2, 0x1}}, + {F, {"drop_grid0_rtsel", 12, 2, 0x1}}, + {F, {"drop_grid1_wtsel", 14, 2, 0x1}}, + {F, {"drop_grid1_rtsel", 16, 2, 0x1}}, + {F, {"tdrop_wtsel", 18, 2, 0x1}}, + {F, {"tdrop_rtsel", 20, 2, 0x1}}, + {F, {"drop_en", 22, 1, 0x0}}, + {F, {"drop_on_full_en", 23, 1, 0x0}}, + + {R, {"ESP_BIS/ERC/in_drop_rate_control", 0x3004}}, + {F, {"cfg_event_delay_fifo_en", 0, 1, 0x0}}, + {F, {"cfg_in_manual_drop_rate_en", 1, 1, 0x0}}, + {F, {"cfg_in_manual_TD_drop_rate_value", 2, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/reference_period", 0x3008}}, + {F, {"val", 0, 10, 0x80}}, + + {R, {"ESP_BIS/ERC/td_target_event_rate", 0x300C}}, + {F, {"val", 0, 22, 0x80}}, + + {R, {"ESP_BIS/ERC/delay_fifo_status", 0x3014}}, + {F, {"error", 0, 1, 0x0}}, + + {R, {"ESP_BIS/ERC/td_actual_in_event_rate", 0x3018}}, + {F, {"val", 0, 22, 0x0}}, + + {R, {"ESP_BIS/ERC/td_actual_in_drop_rate", 0x3020}}, + {F, {"val", 0, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/refine_drop_rate", 0x3028}}, + {F, {"cfg_in_drop_rate_TD_en", 0, 1, 0x0}}, + {F, {"cfg_drop_interest_level_TD_en", 1, 1, 0x0}}, + {F, {"cfg_out_drop_rate_fb_TD_en", 2, 1, 0x0}}, + + {R, {"ESP_BIS/ERC/select_pong_grid_mem", 0x302C}}, + {F, {"val", 0, 1, 0x0}}, + {F, {"status", 1, 1, 0x0}}, + + {R, {"ESP_BIS/ERC/td_actual_out_event_rate", 0x3034}}, + {F, {"val", 0, 22, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_control", 0x3050}}, + {F, {"en", 0, 1, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_control", 0x3060}}, + {F, {"en", 0, 1, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_control", 0x3070}}, + {F, {"en", 0, 1, 0x0}}, + + {R, {"ESP_BIS/ERC/evt_dropped", 0x307C}}, + {F, {"evt_dropped_cnt", 0, 32, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_00", 0x3080}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_01", 0x3084}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_02", 0x3088}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_03", 0x308C}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_04", 0x3090}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_05", 0x3094}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_06", 0x3098}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/h_dropping_lut_07", 0x309C}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_00", 0x30C0}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_01", 0x30C4}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_02", 0x30C8}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_03", 0x30CC}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_04", 0x30D0}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_05", 0x30D4}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_06", 0x30D8}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/v_dropping_lut_07", 0x30DC}}, + {F, {"v0", 0, 5, 0x0}}, + {F, {"v1", 8, 5, 0x0}}, + {F, {"v2", 16, 5, 0x0}}, + {F, {"v3", 24, 5, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_00", 0x3400}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_01", 0x3404}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_02", 0x3408}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_03", 0x340C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_04", 0x3410}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_05", 0x3414}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_06", 0x3418}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_07", 0x341C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_08", 0x3420}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_09", 0x3424}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_10", 0x3428}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_11", 0x342C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_12", 0x3430}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_13", 0x3434}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_14", 0x3438}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_15", 0x343C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_16", 0x3440}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_17", 0x3444}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_18", 0x3448}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_19", 0x344C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_20", 0x3450}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_21", 0x3454}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_22", 0x3458}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_23", 0x345C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_24", 0x3460}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_25", 0x3464}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_26", 0x3468}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_27", 0x346C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_28", 0x3470}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_29", 0x3474}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_30", 0x3478}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_31", 0x347C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_32", 0x3480}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_33", 0x3484}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_34", 0x3488}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_35", 0x348C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_36", 0x3490}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_37", 0x3494}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_38", 0x3498}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_39", 0x349C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_40", 0x34A0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_41", 0x34A4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_42", 0x34A8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_43", 0x34AC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_44", 0x34B0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_45", 0x34B4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_46", 0x34B8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_47", 0x34BC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_48", 0x34C0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_49", 0x34C4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_50", 0x34C8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_51", 0x34CC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_52", 0x34D0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_53", 0x34D4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_54", 0x34D8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_55", 0x34DC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_56", 0x34E0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_57", 0x34E4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_58", 0x34E8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_59", 0x34EC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_60", 0x34F0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_61", 0x34F4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_62", 0x34F8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_63", 0x34FC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_64", 0x3500}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_65", 0x3504}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_66", 0x3508}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_67", 0x350C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_68", 0x3510}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_69", 0x3514}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_70", 0x3518}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_71", 0x351C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_72", 0x3520}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_73", 0x3524}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_74", 0x3528}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_75", 0x352C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_76", 0x3530}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_77", 0x3534}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_78", 0x3538}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_79", 0x353C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_80", 0x3540}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_81", 0x3544}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_82", 0x3548}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_83", 0x354C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_84", 0x3550}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_85", 0x3554}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_86", 0x3558}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_87", 0x355C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_88", 0x3560}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_89", 0x3564}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_90", 0x3568}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_91", 0x356C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_92", 0x3570}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_93", 0x3574}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_94", 0x3578}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_95", 0x357C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_96", 0x3580}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_97", 0x3584}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_98", 0x3588}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_99", 0x358C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_100", 0x3590}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_101", 0x3594}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_102", 0x3598}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_103", 0x359C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_104", 0x35A0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_105", 0x35A4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_106", 0x35A8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_107", 0x35AC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_108", 0x35B0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_109", 0x35B4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_110", 0x35B8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_111", 0x35BC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_112", 0x35C0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_113", 0x35C4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_114", 0x35C8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_115", 0x35CC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_116", 0x35D0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_117", 0x35D4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_118", 0x35D8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_119", 0x35DC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_120", 0x35E0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_121", 0x35E4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_122", 0x35E8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_123", 0x35EC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_124", 0x35F0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_125", 0x35F4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_126", 0x35F8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_127", 0x35FC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_128", 0x3600}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_129", 0x3604}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_130", 0x3608}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_131", 0x360C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_132", 0x3610}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_133", 0x3614}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_134", 0x3618}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_135", 0x361C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_136", 0x3620}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_137", 0x3624}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_138", 0x3628}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_139", 0x362C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_140", 0x3630}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_141", 0x3634}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_142", 0x3638}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_143", 0x363C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_144", 0x3640}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_145", 0x3644}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_146", 0x3648}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_147", 0x364C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_148", 0x3650}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_149", 0x3654}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_150", 0x3658}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_151", 0x365C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_152", 0x3660}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_153", 0x3664}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_154", 0x3668}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_155", 0x366C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_156", 0x3670}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_157", 0x3674}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_158", 0x3678}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_159", 0x367C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_160", 0x3680}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_161", 0x3684}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_162", 0x3688}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_163", 0x368C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_164", 0x3690}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_165", 0x3694}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_166", 0x3698}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_167", 0x369C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_168", 0x36A0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_169", 0x36A4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_170", 0x36A8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_171", 0x36AC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_172", 0x36B0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_173", 0x36B4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_174", 0x36B8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_175", 0x36BC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_176", 0x36C0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_177", 0x36C4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_178", 0x36C8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_179", 0x36CC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_180", 0x36D0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_181", 0x36D4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_182", 0x36D8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_183", 0x36DC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_184", 0x36E0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_185", 0x36E4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_186", 0x36E8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_187", 0x36EC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_188", 0x36F0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_189", 0x36F4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_190", 0x36F8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_191", 0x36FC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_192", 0x3700}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_193", 0x3704}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_194", 0x3708}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_195", 0x370C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_196", 0x3710}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_197", 0x3714}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_198", 0x3718}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_199", 0x371C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_200", 0x3720}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_201", 0x3724}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_202", 0x3728}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_203", 0x372C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_204", 0x3730}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_205", 0x3734}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_206", 0x3738}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_207", 0x373C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_208", 0x3740}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_209", 0x3744}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_210", 0x3748}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_211", 0x374C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_212", 0x3750}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_213", 0x3754}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_214", 0x3758}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_215", 0x375C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_216", 0x3760}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_217", 0x3764}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_218", 0x3768}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_219", 0x376C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_220", 0x3770}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_221", 0x3774}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_222", 0x3778}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_223", 0x377C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_224", 0x3780}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_225", 0x3784}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_226", 0x3788}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_227", 0x378C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_228", 0x3790}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_229", 0x3794}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_230", 0x3798}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_231", 0x379C}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_232", 0x37A0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_233", 0x37A4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_234", 0x37A8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_235", 0x37AC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_236", 0x37B0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_237", 0x37B4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_238", 0x37B8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_239", 0x37BC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_240", 0x37C0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_241", 0x37C4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_242", 0x37C8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_243", 0x37CC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_244", 0x37D0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_245", 0x37D4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_246", 0x37D8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_247", 0x37DC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_248", 0x37E0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_249", 0x37E4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_250", 0x37E8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_251", 0x37EC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_252", 0x37F0}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_253", 0x37F4}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_254", 0x37F8}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/t_dropping_lut_255", 0x37FC}}, + {F, {"v0", 0, 9, 0x0}}, + {F, {"v1", 16, 9, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_000", 0x3800}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_000", 0x3800}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_001", 0x3804}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_001", 0x3804}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_002", 0x3808}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_002", 0x3808}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_003", 0x380C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_003", 0x380C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_004", 0x3810}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_004", 0x3810}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_005", 0x3814}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_005", 0x3814}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_006", 0x3818}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_006", 0x3818}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_007", 0x381C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_007", 0x381C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_008", 0x3820}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_008", 0x3820}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_009", 0x3824}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_009", 0x3824}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_010", 0x3828}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_010", 0x3828}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_011", 0x382C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_011", 0x382C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_012", 0x3830}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_012", 0x3830}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_013", 0x3834}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_013", 0x3834}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_014", 0x3838}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_014", 0x3838}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_015", 0x383C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_015", 0x383C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_016", 0x3840}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_016", 0x3840}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_017", 0x3844}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_017", 0x3844}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_018", 0x3848}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_018", 0x3848}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_019", 0x384C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_019", 0x384C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_020", 0x3850}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_020", 0x3850}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_021", 0x3854}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_021", 0x3854}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_022", 0x3858}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_022", 0x3858}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_023", 0x385C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_023", 0x385C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_024", 0x3860}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_024", 0x3860}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_025", 0x3864}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_025", 0x3864}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_026", 0x3868}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_026", 0x3868}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_027", 0x386C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_027", 0x386C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_028", 0x3870}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_028", 0x3870}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_029", 0x3874}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_029", 0x3874}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_030", 0x3878}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_030", 0x3878}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_031", 0x387C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_031", 0x387C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_032", 0x3880}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_032", 0x3880}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_033", 0x3884}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_033", 0x3884}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_034", 0x3888}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_034", 0x3888}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_035", 0x388C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_035", 0x388C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_036", 0x3890}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_036", 0x3890}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_037", 0x3894}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_037", 0x3894}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_038", 0x3898}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_038", 0x3898}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_039", 0x389C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_039", 0x389C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_040", 0x38A0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_040", 0x38A0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_041", 0x38A4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_041", 0x38A4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_042", 0x38A8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_042", 0x38A8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_043", 0x38AC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_043", 0x38AC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_044", 0x38B0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_044", 0x38B0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_045", 0x38B4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_045", 0x38B4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_046", 0x38B8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_046", 0x38B8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_047", 0x38BC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_047", 0x38BC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_048", 0x38C0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_048", 0x38C0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_049", 0x38C4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_049", 0x38C4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_050", 0x38C8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_050", 0x38C8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_051", 0x38CC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_051", 0x38CC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_052", 0x38D0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_052", 0x38D0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_053", 0x38D4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_053", 0x38D4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_054", 0x38D8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_054", 0x38D8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_055", 0x38DC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_055", 0x38DC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_056", 0x38E0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_056", 0x38E0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_057", 0x38E4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_057", 0x38E4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_058", 0x38E8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_058", 0x38E8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_059", 0x38EC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_059", 0x38EC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_060", 0x38F0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_060", 0x38F0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_061", 0x38F4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_061", 0x38F4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_062", 0x38F8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_062", 0x38F8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_063", 0x38FC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_063", 0x38FC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_064", 0x3900}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_064", 0x3900}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_065", 0x3904}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_065", 0x3904}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_066", 0x3908}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_066", 0x3908}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_067", 0x390C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_067", 0x390C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_068", 0x3910}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_068", 0x3910}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_069", 0x3914}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_069", 0x3914}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_070", 0x3918}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_070", 0x3918}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_071", 0x391C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_071", 0x391C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_072", 0x3920}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_072", 0x3920}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_073", 0x3924}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_073", 0x3924}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_074", 0x3928}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_074", 0x3928}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_075", 0x392C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_075", 0x392C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_076", 0x3930}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_076", 0x3930}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_077", 0x3934}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_077", 0x3934}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_078", 0x3938}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_078", 0x3938}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_079", 0x393C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_079", 0x393C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_080", 0x3940}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_080", 0x3940}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_081", 0x3944}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_081", 0x3944}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_082", 0x3948}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_082", 0x3948}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_083", 0x394C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_083", 0x394C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_084", 0x3950}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_084", 0x3950}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_085", 0x3954}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_085", 0x3954}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_086", 0x3958}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_086", 0x3958}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_087", 0x395C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_087", 0x395C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_088", 0x3960}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_088", 0x3960}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_089", 0x3964}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_089", 0x3964}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_090", 0x3968}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_090", 0x3968}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_091", 0x396C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_091", 0x396C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_092", 0x3970}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_092", 0x3970}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_093", 0x3974}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_093", 0x3974}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_094", 0x3978}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_094", 0x3978}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_095", 0x397C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_095", 0x397C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_096", 0x3980}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_096", 0x3980}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_097", 0x3984}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_097", 0x3984}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_098", 0x3988}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_098", 0x3988}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_099", 0x398C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_099", 0x398C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_100", 0x3990}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_100", 0x3990}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_101", 0x3994}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_101", 0x3994}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_102", 0x3998}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_102", 0x3998}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_103", 0x399C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_103", 0x399C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_104", 0x39A0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_104", 0x39A0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_105", 0x39A4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_105", 0x39A4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_106", 0x39A8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_106", 0x39A8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_107", 0x39AC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_107", 0x39AC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_108", 0x39B0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_108", 0x39B0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_109", 0x39B4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_109", 0x39B4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_110", 0x39B8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_110", 0x39B8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_111", 0x39BC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_111", 0x39BC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_112", 0x39C0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_112", 0x39C0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_113", 0x39C4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_113", 0x39C4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_114", 0x39C8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_114", 0x39C8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_115", 0x39CC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_115", 0x39CC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_116", 0x39D0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_116", 0x39D0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_117", 0x39D4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_117", 0x39D4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_118", 0x39D8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_118", 0x39D8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_119", 0x39DC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_119", 0x39DC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_120", 0x39E0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_120", 0x39E0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_121", 0x39E4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_121", 0x39E4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_122", 0x39E8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_122", 0x39E8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_123", 0x39EC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_123", 0x39EC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_124", 0x39F0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_124", 0x39F0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_125", 0x39F4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_125", 0x39F4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_126", 0x39F8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_126", 0x39F8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_127", 0x39FC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_127", 0x39FC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_128", 0x3A00}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_128", 0x3A00}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_129", 0x3A04}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_129", 0x3A04}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_130", 0x3A08}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_130", 0x3A08}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_131", 0x3A0C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_131", 0x3A0C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_132", 0x3A10}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_132", 0x3A10}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_133", 0x3A14}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_133", 0x3A14}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_134", 0x3A18}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_134", 0x3A18}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_135", 0x3A1C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_135", 0x3A1C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_136", 0x3A20}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_136", 0x3A20}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_137", 0x3A24}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_137", 0x3A24}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_138", 0x3A28}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_138", 0x3A28}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_139", 0x3A2C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_139", 0x3A2C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_140", 0x3A30}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_140", 0x3A30}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_141", 0x3A34}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_141", 0x3A34}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_142", 0x3A38}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_142", 0x3A38}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_143", 0x3A3C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_143", 0x3A3C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_144", 0x3A40}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_144", 0x3A40}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_145", 0x3A44}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_145", 0x3A44}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_146", 0x3A48}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_146", 0x3A48}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_147", 0x3A4C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_147", 0x3A4C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_148", 0x3A50}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_148", 0x3A50}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_149", 0x3A54}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_149", 0x3A54}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_150", 0x3A58}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_150", 0x3A58}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_151", 0x3A5C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_151", 0x3A5C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_152", 0x3A60}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_152", 0x3A60}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_153", 0x3A64}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_153", 0x3A64}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_154", 0x3A68}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_154", 0x3A68}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_155", 0x3A6C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_155", 0x3A6C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_156", 0x3A70}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_156", 0x3A70}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_157", 0x3A74}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_157", 0x3A74}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_158", 0x3A78}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_158", 0x3A78}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_159", 0x3A7C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_159", 0x3A7C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_160", 0x3A80}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_160", 0x3A80}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_161", 0x3A84}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_161", 0x3A84}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_162", 0x3A88}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_162", 0x3A88}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_163", 0x3A8C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_163", 0x3A8C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_164", 0x3A90}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_164", 0x3A90}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_165", 0x3A94}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_165", 0x3A94}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_166", 0x3A98}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_166", 0x3A98}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_167", 0x3A9C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_167", 0x3A9C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_168", 0x3AA0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_168", 0x3AA0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_169", 0x3AA4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_169", 0x3AA4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_170", 0x3AA8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_170", 0x3AA8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_171", 0x3AAC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_171", 0x3AAC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_172", 0x3AB0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_172", 0x3AB0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_173", 0x3AB4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_173", 0x3AB4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_174", 0x3AB8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_174", 0x3AB8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_175", 0x3ABC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_175", 0x3ABC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_176", 0x3AC0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_176", 0x3AC0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_177", 0x3AC4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_177", 0x3AC4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_178", 0x3AC8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_178", 0x3AC8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_179", 0x3ACC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_179", 0x3ACC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_180", 0x3AD0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_180", 0x3AD0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_181", 0x3AD4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_181", 0x3AD4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_182", 0x3AD8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_182", 0x3AD8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_183", 0x3ADC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_183", 0x3ADC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_184", 0x3AE0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_184", 0x3AE0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_185", 0x3AE4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_185", 0x3AE4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_186", 0x3AE8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_186", 0x3AE8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_187", 0x3AEC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_187", 0x3AEC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_188", 0x3AF0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_188", 0x3AF0}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_189", 0x3AF4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_189", 0x3AF4}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_190", 0x3AF8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_190", 0x3AF8}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_191", 0x3AFC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_191", 0x3AFC}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_192", 0x3B00}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_192", 0x3B00}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_193", 0x3B04}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_193", 0x3B04}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_194", 0x3B08}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_194", 0x3B08}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_195", 0x3B0C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_195", 0x3B0C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_196", 0x3B10}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_196", 0x3B10}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_197", 0x3B14}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_197", 0x3B14}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_198", 0x3B18}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_198", 0x3B18}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_199", 0x3B1C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_199", 0x3B1C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_200", 0x3B20}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_200", 0x3B20}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_201", 0x3B24}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_201", 0x3B24}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_202", 0x3B28}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_202", 0x3B28}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_203", 0x3B2C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_203", 0x3B2C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_204", 0x3B30}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_204", 0x3B30}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_205", 0x3B34}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_205", 0x3B34}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_206", 0x3B38}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_206", 0x3B38}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_207", 0x3B3C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_207", 0x3B3C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_208", 0x3B40}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_208", 0x3B40}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_209", 0x3B44}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_209", 0x3B44}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_210", 0x3B48}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_210", 0x3B48}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_211", 0x3B4C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_211", 0x3B4C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_212", 0x3B50}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_212", 0x3B50}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_213", 0x3B54}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_213", 0x3B54}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_214", 0x3B58}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_214", 0x3B58}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_215", 0x3B5C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_215", 0x3B5C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_216", 0x3B60}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_216", 0x3B60}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_217", 0x3B64}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_217", 0x3B64}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_218", 0x3B68}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_218", 0x3B68}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_219", 0x3B6C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_219", 0x3B6C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_220", 0x3B70}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_220", 0x3B70}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_221", 0x3B74}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_221", 0x3B74}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_222", 0x3B78}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_222", 0x3B78}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_223", 0x3B7C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_223", 0x3B7C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_224", 0x3B80}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_224", 0x3B80}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_225", 0x3B84}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_225", 0x3B84}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_226", 0x3B88}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_226", 0x3B88}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_227", 0x3B8C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_227", 0x3B8C}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_228", 0x3B90}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_228", 0x3B90}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/ping_drop_interest_level_229", 0x3B94}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/ERC/pong_drop_interest_level_229", 0x3B94}}, + {F, {"v0", 0, 6, 0x0}}, + {F, {"v1", 8, 6, 0x0}}, + {F, {"v2", 16, 6, 0x0}}, + {F, {"v3", 24, 6, 0x0}}, + + {R, {"ESP_BIS/GPAFK/pipeline_control", 0x4000}}, + {F, {"enable", 0, 1, 0x1}}, + {F, {"drop_nbackpressure", 1, 1, 0x0}}, + {F, {"bypass", 2, 1, 0x1}}, + + {R, {"ESP_BIS/GPAFK/pipeline_status", 0x4004}}, + {F, {"empty", 0, 1, 0x1}}, + {F, {"busy", 1, 1, 0x0}}, + {F, {"deep_low_power_seen", 2, 1, 0x0}}, + + {R, {"ESP_BIS/GPAFK/control", 0x4020}}, + {F, {"invert", 0, 1, 0x0}}, + {F, {"drop_disable", 1, 1, 0x0}}, + {F, {"drop_mark", 2, 1, 0x0}}, + {F, {"enable_stats", 3, 1, 0x0}}, + {F, {"sample_stats", 4, 1, 0x0}}, + {F, {"id", 5, 2, 0x0}}, + + {R, {"ESP_BIS/GPAFK/version", 0x4024}}, + {F, {"micro", 0, 8, 0x0}}, + {F, {"minor", 8, 8, 0x1}}, + {F, {"major", 16, 8, 0x1}}, + + {R, {"ESP_BIS/GPAFK/monitor", 0x4028}}, + {F, {"period_en", 0, 1, 0x0}}, + {F, {"timespan_en", 1, 1, 0x0}}, + {F, {"in_td_evt_count_en", 2, 1, 0x0}}, + {F, {"filtered_td_evt_count_en", 3, 1, 0x0}}, + + {R, {"ESP_BIS/GPAFK/min_period", 0x402C}}, + {F, {"value", 0, 16, 0x595}}, + + {R, {"ESP_BIS/GPAFK/max_period", 0x4030}}, + {F, {"value", 0, 16, 0x4E20}}, + + {R, {"ESP_BIS/GPAFK/sync_period", 0x4034}}, + {F, {"value", 0, 16, 0x3E8}}, + + {R, {"ESP_BIS/GPAFK/num_in_events_th_cd_off", 0x4038}}, + {F, {"value", 0, 27, 0x3E8}}, + + {R, {"ESP_BIS/GPAFK/num_in_events_th_cd_on", 0x403C}}, + {F, {"value", 0, 27, 0x3E8}}, + + {R, {"ESP_BIS/GPAFK/silence_depth_th", 0x4040}}, + {F, {"cd_off", 0, 8, 0x1A}}, + {F, {"cd_on", 8, 8, 0x1A}}, + + {R, {"ESP_BIS/GPAFK/loop_gain", 0x4044}}, + {F, {"sync_cd_off", 0, 5, 0x10}}, + {F, {"sync_cd_on", 8, 5, 0x10}}, + {F, {"locked_cd_off", 16, 5, 0x8}}, + {F, {"locked_cd_on", 24, 5, 0x8}}, + + {R, {"ESP_BIS/GPAFK/dt_factor", 0x4048}}, + {F, {"sync_cd_off", 0, 7, 0x40}}, + {F, {"sync_cd_on", 8, 7, 0x40}}, + {F, {"locked_cd_off", 16, 7, 0x2A}}, + {F, {"locked_cd_on", 24, 7, 0x2A}}, + + {R, {"ESP_BIS/GPAFK/lock_counter", 0x404C}}, + {F, {"low", 0, 3, 0x4}}, + {F, {"high", 4, 3, 0x6}}, + {F, {"max", 8, 3, 0x7}}, + + {R, {"ESP_BIS/GPAFK/timespan_control", 0x4050}}, + {F, {"static_mode_cd_off", 0, 1, 0x0}}, + {F, {"static_mode_cd_on", 1, 1, 0x0}}, + {F, {"dynamic_factor_cd_off", 4, 11, 0x100}}, + {F, {"dynamic_factor_cd_on", 16, 11, 0x100}}, + + {R, {"ESP_BIS/GPAFK/timespan_static", 0x4054}}, + {F, {"value_cd_off", 0, 16, 0x5DC}}, + {F, {"value_cd_on", 16, 16, 0x5DC}}, + + {R, {"ESP_BIS/GPAFK/smooth_shift_control", 0x4058}}, + {F, {"timespan_dynamic", 0, 4, 0x6}}, + {F, {"period_stat", 8, 4, 0x6}}, + {F, {"timespan_stat", 16, 4, 0x6}}, + {F, {"events_num_stat", 24, 4, 0x6}}, + + {R, {"ESP_BIS/GPAFK/ts_offset_reset", 0x405C}}, + {F, {"thr", 0, 17, 0x186A0}}, + {F, {"enable", 31, 1, 0x1}}, + + {R, {"ESP_BIS/GPAFK/shadow_control", 0x4080}}, + {F, {"timer_en", 0, 1, 0x0}}, + {F, {"irq_sw_override", 1, 1, 0x0}}, + {F, {"reset_on_copy", 2, 1, 0x0}}, + + {R, {"ESP_BIS/GPAFK/shadow_timer_threshold", 0x4084}}, + {F, {"value", 0, 32, 0x3E8}}, + + {R, {"ESP_BIS/GPAFK/shadow_status", 0x4088}}, + {F, {"shadow_valid", 0, 1, 0x0}}, + {F, {"shadow_overrun", 1, 1, 0x0}}, + + {R, {"ESP_BIS/GPAFK/num_locked_stat", 0x408C}}, + {F, {"cd_off", 0, 1, 0x0}}, + {F, {"cd_on", 1, 1, 0x0}}, + + {R, {"ESP_BIS/GPAFK/timespan_stat", 0x4090}}, + {F, {"cd_off", 0, 15, 0x0}}, + {F, {"cd_on", 16, 15, 0x0}}, + + {R, {"ESP_BIS/GPAFK/period_stat", 0x4094}}, + {F, {"cd_off", 0, 16, 0x0}}, + {F, {"cd_on", 16, 16, 0x0}}, + + {R, {"ESP_BIS/GPAFK/in_events_stat_locked_cd_off", 0x4098}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"ESP_BIS/GPAFK/in_events_stat_locked_cd_on", 0x409C}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"ESP_BIS/GPAFK/in_events_stat_sync_cd_off", 0x40A0}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"ESP_BIS/GPAFK/in_events_stat_sync_cd_on", 0x40A4}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"ESP_BIS/GPAFK/out_events_stat_locked_cd_off", 0x40A8}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"ESP_BIS/GPAFK/out_events_stat_locked_cd_on", 0x40AC}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"ESP_BIS/GPAFK/out_events_stat_sync_cd_off", 0x40B0}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"ESP_BIS/GPAFK/out_events_stat_sync_cd_on", 0x40B4}}, + {F, {"value", 0, 27, 0x0}}, + + {R, {"SENSOR_IF/IMX636/roi_ctrl", 0x100004}}, + {F, {"roi_td_en", 1, 1, 0x0}}, + {F, {"roi_td_shadow_trigger", 5, 1, 0x0}}, + {F, {"td_roi_roni_n_en", 6, 1, 0x1}}, + {F, {"Reserved_8", 8, 1, 0x0}}, + {F, {"px_td_rstn", 10, 1, 0x0}}, + {F, {"Reserved_17_11", 11, 7, 0xA}}, + {F, {"Reserved_25", 25, 1, 0x0}}, + {F, {"Reserved_29_28", 28, 2, 0x3}}, + {F, {"Reserved_31_30", 30, 2, 0x3}}, + + {R, {"SENSOR_IF/IMX636/lifo_ctrl", 0x10000C}}, + {F, {"lifo_en", 0, 1, 0x0}}, + {F, {"lifo_out_en", 1, 1, 0x0}}, + {F, {"lifo_cnt_en", 2, 1, 0x0}}, + {F, {"Reserved_31_3", 3, 29, 0x0}}, + + {R, {"SENSOR_IF/IMX636/lifo_status", 0x100010}}, + {F, {"lifo_ton", 0, 29, 0x0}}, + {F, {"lifo_ton_valid", 29, 1, 0x0}}, + {F, {"Reserved_30", 30, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/Reserved_0014", 0x100014}}, + {F, {"Reserved_31_0", 0, 32, 0xA0401806}}, + + {R, {"SENSOR_IF/IMX636/spare0", 0x100018}}, + {F, {"Reserved_19_0", 0, 20, 0x0}}, + {F, {"gcd_rstn", 20, 1, 0x0}}, + {F, {"Reserved_31_21", 21, 11, 0x0}}, + + {R, {"SENSOR_IF/IMX636/refractory_ctrl", 0x100020}}, + {F, {"refr_counter", 0, 28, 0x0}}, + {F, {"refr_valid", 28, 1, 0x0}}, + {F, {"Reserved_29", 29, 1, 0x0}}, + {F, {"refr_cnt_en", 30, 1, 0x0}}, + {F, {"refr_en", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/roi_win_ctrl", 0x100034}}, + {F, {"roi_master_en", 0, 1, 0x0}}, + {F, {"roi_win_done", 1, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/roi_win_start_addr", 0x100038}}, + {F, {"roi_win_start_x", 0, 11, 0x0}}, + {F, {"roi_win_start_y", 16, 10, 0x0}}, + + {R, {"SENSOR_IF/IMX636/roi_win_end_addr", 0x10003C}}, + {F, {"roi_win_end_x", 0, 11, 0x4FF}}, + {F, {"roi_win_end_y", 16, 10, 0x2CF}}, + + {R, {"SENSOR_IF/IMX636/dig_pad2_ctrl", 0x100044}}, + {F, {"Reserved_15_0", 0, 16, 0xFCCF}}, + {F, {"pad_sync", 16, 4, 0xF}}, + {F, {"Reserved_31_20", 20, 12, 0xCCF}}, + + {R, {"SENSOR_IF/IMX636/adc_control", 0x10004C}}, + {F, {"adc_en", 0, 1, 0x0}}, + {F, {"adc_clk_en", 1, 1, 0x0}}, + {F, {"adc_start", 2, 1, 0x0}}, + {F, {"Reserved_31_3", 3, 29, 0xEC8}}, + + {R, {"SENSOR_IF/IMX636/adc_status", 0x100050}}, + {F, {"adc_dac_dyn", 0, 10, 0x0}}, + {F, {"Reserved_10", 10, 1, 0x0}}, + {F, {"adc_done_dyn", 11, 1, 0x0}}, + {F, {"Reserved_31_12", 12, 20, 0x0}}, + + {R, {"SENSOR_IF/IMX636/adc_misc_ctrl", 0x100054}}, + {F, {"Reserved_0", 0, 1, 0x0}}, + {F, {"adc_buf_cal_en", 1, 1, 0x0}}, + {F, {"Reserved_9_2", 2, 8, 0x84}}, + {F, {"adc_rng", 10, 2, 0x0}}, + {F, {"adc_temp", 12, 1, 0x0}}, + {F, {"Reserved_14_13", 13, 2, 0x0}}, + + {R, {"SENSOR_IF/IMX636/temp_ctrl", 0x10005C}}, + {F, {"temp_buf_cal_en", 0, 1, 0x0}}, + {F, {"temp_buf_en", 1, 1, 0x0}}, + {F, {"Reserved_31_2", 2, 30, 0x20}}, + + {R, {"SENSOR_IF/IMX636/iph_mirr_ctrl", 0x100074}}, + {F, {"iph_mirr_en", 0, 1, 0x0}}, + {F, {"iph_mirr_amp_en", 1, 1, 0x1}}, + {F, {"Reserved_31_2", 2, 30, 0x0}}, + + {R, {"SENSOR_IF/IMX636/gcd_ctrl1", 0x100078}}, + {F, {"gcd_en", 0, 1, 0x0}}, + {F, {"gcd_diffamp_en", 1, 1, 0x0}}, + {F, {"gcd_lpf_en", 2, 1, 0x0}}, + {F, {"Reserved_31_3", 3, 29, 0x8003BE9}}, + + {R, {"SENSOR_IF/IMX636/reqy_qmon_ctrl", 0x100088}}, + {F, {"reqy_qmon_en", 0, 1, 0x0}}, + {F, {"reqy_qmon_rstn", 1, 1, 0x0}}, + {F, {"Reserved_3_2", 2, 2, 0x0}}, + {F, {"reqy_qmon_interrupt_en", 4, 1, 0x0}}, + {F, {"reqy_qmon_trip_ctl", 10, 10, 0x0}}, + {F, {"Reserved_31_16", 20, 12, 0x0}}, + + {R, {"SENSOR_IF/IMX636/reqy_qmon_status", 0x10008C}}, + {F, {"Reserved_15_0", 0, 16, 0x0}}, + {F, {"reqy_qmon_sum_irq", 16, 10, 0x0}}, + {F, {"reqy_qmon_trip_irq", 26, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/gcd_shadow_ctrl", 0x100090}}, + {F, {"Reserved_0", 0, 1, 0x0}}, + {F, {"gcd_irq_sw_override", 1, 1, 0x0}}, + {F, {"gcd_reset_on_copy", 2, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/gcd_shadow_status", 0x100094}}, + {F, {"gcd_shadow_valid", 0, 1, 0x0}}, + {F, {"Reserved_31_1", 1, 31, 0x0}}, + + {R, {"SENSOR_IF/IMX636/gcd_shadow_counter", 0x100098}}, + {F, {"gcd_shadow_cnt_off", 0, 16, 0x0}}, + {F, {"gcd_shadow_cnt_on", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stop_sequence_control", 0x1000C8}}, + {F, {"stop_sequence_start", 0, 1, 0x0}}, + {F, {"Reserved_15_8", 8, 8, 0x1}}, + + {R, {"SENSOR_IF/IMX636/bias/bias_fo", 0x101004}}, + {F, {"idac_ctl", 0, 8, 0x0}}, + {F, {"Reserved_27_8", 8, 20, 0x3A1E8}}, + {F, {"single_transfer", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/bias/bias_hpf", 0x10100C}}, + {F, {"idac_ctl", 0, 8, 0x0}}, + {F, {"Reserved_27_8", 8, 20, 0x3A1FF}}, + {F, {"single_transfer", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/bias/bias_diff_on", 0x101010}}, + {F, {"idac_ctl", 0, 8, 0x0}}, + {F, {"Reserved_27_8", 8, 20, 0x1A163}}, + {F, {"single_transfer", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/bias/bias_diff", 0x101014}}, + {F, {"idac_ctl", 0, 8, 0x4D}}, + {F, {"Reserved_27_8", 8, 20, 0x1A150}}, + {F, {"single_transfer", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/bias/bias_diff_off", 0x101018}}, + {F, {"idac_ctl", 0, 8, 0x0}}, + {F, {"Reserved_27_8", 8, 20, 0x1A137}}, + {F, {"single_transfer", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/bias/bias_refr", 0x101020}}, + {F, {"idac_ctl", 0, 8, 0x14}}, + {F, {"Reserved_27_8", 8, 20, 0x38296}}, + {F, {"single_transfer", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/bias/bgen_ctrl", 0x101100}}, + {F, {"burst_transfer", 0, 1, 0x0}}, + {F, {"Reserved_2_1", 1, 2, 0x0}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x00", 0x102000}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x01", 0x102004}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x02", 0x102008}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x03", 0x10200C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x04", 0x102010}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x05", 0x102014}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x06", 0x102018}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x07", 0x10201C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x08", 0x102020}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x09", 0x102024}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x10", 0x102028}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x11", 0x10202C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x12", 0x102030}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x13", 0x102034}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x14", 0x102038}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x15", 0x10203C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x16", 0x102040}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x17", 0x102044}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x18", 0x102048}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x19", 0x10204C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x20", 0x102050}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x21", 0x102054}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x22", 0x102058}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x23", 0x10205C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x24", 0x102060}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x25", 0x102064}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x26", 0x102068}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x27", 0x10206C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x28", 0x102070}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x29", 0x102074}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x30", 0x102078}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x31", 0x10207C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x32", 0x102080}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x33", 0x102084}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x34", 0x102088}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x35", 0x10208C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x36", 0x102090}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x37", 0x102094}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x38", 0x102098}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_x39", 0x10209C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y00", 0x104000}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y01", 0x104004}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y02", 0x104008}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y03", 0x10400C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y04", 0x104010}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y05", 0x104014}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y06", 0x104018}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y07", 0x10401C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y08", 0x104020}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y09", 0x104024}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y10", 0x104028}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y11", 0x10402C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y12", 0x104030}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y13", 0x104034}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y14", 0x104038}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y15", 0x10403C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y16", 0x104040}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y17", 0x104044}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y18", 0x104048}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y19", 0x10404C}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y20", 0x104050}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y21", 0x104054}}, + {F, {"effective", 0, 32, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFFFFFF}}, + + {R, {"SENSOR_IF/IMX636/roi/td_roi_y22", 0x104058}}, + {F, {"effective", 0, 16, 0x0}}, + {A, {"enable", 0x0}}, + {A, {"disable", 0xFFFF}}, + {F, {"Reserved_16", 16, 1, 0x1}}, + {F, {"Reserved_17", 17, 1, 0x1}}, + {F, {"Reserved_19_18", 18, 2, 0x3}}, + {F, {"Reserved_21_20", 20, 2, 0x3}}, + {F, {"Reserved_22", 22, 1, 0x1}}, + {F, {"Reserved_23", 23, 1, 0x1}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6000", 0x106000}}, + {F, {"Reserved_1_0", 0, 2, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/in_drop_rate_control", 0x106004}}, + {F, {"cfg_event_delay_fifo_en", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"Reserved_10_2", 2, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/reference_period", 0x106008}}, + {F, {"erc_reference_period", 0, 10, 0x80}}, + + {R, {"SENSOR_IF/IMX636/erc/td_target_event_rate", 0x10600C}}, + {F, {"target_event_rate", 0, 22, 0x80}}, + + {R, {"SENSOR_IF/IMX636/erc/erc_enable", 0x106028}}, + {F, {"erc_en", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"Reserved_2", 2, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_602C", 0x10602C}}, + {F, {"Reserved_0", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_dropping_control", 0x106050}}, + {F, {"t_dropping_en", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_dropping_control", 0x106060}}, + {F, {"h_dropping_en", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_dropping_control", 0x106070}}, + {F, {"v_dropping_en", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_00", 0x106080}}, + {F, {"hlut00", 0, 5, 0x0}}, + {F, {"hlut01", 8, 5, 0x0}}, + {F, {"hlut02", 16, 5, 0x0}}, + {F, {"hlut03", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_01", 0x106084}}, + {F, {"hlut04", 0, 5, 0x0}}, + {F, {"hlut05", 8, 5, 0x0}}, + {F, {"hlut06", 16, 5, 0x0}}, + {F, {"hlut07", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_02", 0x106088}}, + {F, {"hlut08", 0, 5, 0x0}}, + {F, {"hlut09", 8, 5, 0x0}}, + {F, {"hlut10", 16, 5, 0x0}}, + {F, {"hlut11", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_03", 0x10608C}}, + {F, {"hlut12", 0, 5, 0x0}}, + {F, {"hlut13", 8, 5, 0x0}}, + {F, {"hlut14", 16, 5, 0x0}}, + {F, {"hlut15", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_04", 0x106090}}, + {F, {"hlut16", 0, 5, 0x0}}, + {F, {"hlut17", 8, 5, 0x0}}, + {F, {"hlut18", 16, 5, 0x0}}, + {F, {"hlut19", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_05", 0x106094}}, + {F, {"hlut20", 0, 5, 0x0}}, + {F, {"hlut21", 8, 5, 0x0}}, + {F, {"hlut22", 16, 5, 0x0}}, + {F, {"hlut23", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_06", 0x106098}}, + {F, {"hlut24", 0, 5, 0x0}}, + {F, {"hlut25", 8, 5, 0x0}}, + {F, {"hlut26", 16, 5, 0x0}}, + {F, {"hlut27", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/h_drop_lut_07", 0x10609C}}, + {F, {"hlut28", 0, 5, 0x0}}, + {F, {"hlut29", 8, 5, 0x0}}, + {F, {"hlut30", 16, 5, 0x0}}, + {F, {"hlut31", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_00", 0x1060C0}}, + {F, {"vlut00", 0, 5, 0x0}}, + {F, {"vlut01", 8, 5, 0x0}}, + {F, {"vlut02", 16, 5, 0x0}}, + {F, {"vlut03", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_01", 0x1060C4}}, + {F, {"vlut04", 0, 5, 0x0}}, + {F, {"vlut05", 8, 5, 0x0}}, + {F, {"vlut06", 16, 5, 0x0}}, + {F, {"vlut07", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_02", 0x1060C8}}, + {F, {"vlut08", 0, 5, 0x0}}, + {F, {"vlut09", 8, 5, 0x0}}, + {F, {"vlut10", 16, 5, 0x0}}, + {F, {"vlut11", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_03", 0x1060CC}}, + {F, {"vlut12", 0, 5, 0x0}}, + {F, {"vlut13", 8, 5, 0x0}}, + {F, {"vlut14", 16, 5, 0x0}}, + {F, {"vlut15", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_04", 0x1060D0}}, + {F, {"vlut16", 0, 5, 0x0}}, + {F, {"vlut17", 8, 5, 0x0}}, + {F, {"vlut18", 16, 5, 0x0}}, + {F, {"vlut19", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_05", 0x1060D4}}, + {F, {"vlut20", 0, 5, 0x0}}, + {F, {"vlut21", 8, 5, 0x0}}, + {F, {"vlut22", 16, 5, 0x0}}, + {F, {"vlut23", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_06", 0x1060D8}}, + {F, {"vlut24", 0, 5, 0x0}}, + {F, {"vlut25", 8, 5, 0x0}}, + {F, {"vlut26", 16, 5, 0x0}}, + {F, {"vlut27", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/v_drop_lut_07", 0x1060DC}}, + {F, {"vlut28", 0, 5, 0x0}}, + {F, {"vlut29", 8, 5, 0x0}}, + {F, {"vlut30", 16, 5, 0x0}}, + {F, {"vlut31", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_00", 0x106400}}, + {F, {"tlut000", 0, 9, 0x0}}, + {F, {"tlut001", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_01", 0x106404}}, + {F, {"tlut002", 0, 9, 0x0}}, + {F, {"tlut003", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_02", 0x106408}}, + {F, {"tlut004", 0, 9, 0x0}}, + {F, {"tlut005", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_03", 0x10640C}}, + {F, {"tlut006", 0, 9, 0x0}}, + {F, {"tlut007", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_04", 0x106410}}, + {F, {"tlut008", 0, 9, 0x0}}, + {F, {"tlut009", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_05", 0x106414}}, + {F, {"tlut010", 0, 9, 0x0}}, + {F, {"tlut011", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_06", 0x106418}}, + {F, {"tlut012", 0, 9, 0x0}}, + {F, {"tlut013", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_07", 0x10641C}}, + {F, {"tlut014", 0, 9, 0x0}}, + {F, {"tlut015", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_08", 0x106420}}, + {F, {"tlut016", 0, 9, 0x0}}, + {F, {"tlut017", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_09", 0x106424}}, + {F, {"tlut018", 0, 9, 0x0}}, + {F, {"tlut019", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_10", 0x106428}}, + {F, {"tlut020", 0, 9, 0x0}}, + {F, {"tlut021", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_11", 0x10642C}}, + {F, {"tlut022", 0, 9, 0x0}}, + {F, {"tlut023", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_12", 0x106430}}, + {F, {"tlut024", 0, 9, 0x0}}, + {F, {"tlut025", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_13", 0x106434}}, + {F, {"tlut026", 0, 9, 0x0}}, + {F, {"tlut027", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_14", 0x106438}}, + {F, {"tlut028", 0, 9, 0x0}}, + {F, {"tlut029", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_15", 0x10643C}}, + {F, {"tlut030", 0, 9, 0x0}}, + {F, {"tlut031", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_16", 0x106440}}, + {F, {"tlut032", 0, 9, 0x0}}, + {F, {"tlut033", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_17", 0x106444}}, + {F, {"tlut034", 0, 9, 0x0}}, + {F, {"tlut035", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_18", 0x106448}}, + {F, {"tlut036", 0, 9, 0x0}}, + {F, {"tlut037", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_19", 0x10644C}}, + {F, {"tlut038", 0, 9, 0x0}}, + {F, {"tlut039", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_20", 0x106450}}, + {F, {"tlut040", 0, 9, 0x0}}, + {F, {"tlut041", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_21", 0x106454}}, + {F, {"tlut042", 0, 9, 0x0}}, + {F, {"tlut043", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_22", 0x106458}}, + {F, {"tlut044", 0, 9, 0x0}}, + {F, {"tlut045", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_23", 0x10645C}}, + {F, {"tlut046", 0, 9, 0x0}}, + {F, {"tlut047", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_24", 0x106460}}, + {F, {"tlut048", 0, 9, 0x0}}, + {F, {"tlut049", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_25", 0x106464}}, + {F, {"tlut050", 0, 9, 0x0}}, + {F, {"tlut051", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_26", 0x106468}}, + {F, {"tlut052", 0, 9, 0x0}}, + {F, {"tlut053", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_27", 0x10646C}}, + {F, {"tlut054", 0, 9, 0x0}}, + {F, {"tlut055", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_28", 0x106470}}, + {F, {"tlut056", 0, 9, 0x0}}, + {F, {"tlut057", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_29", 0x106474}}, + {F, {"tlut058", 0, 9, 0x0}}, + {F, {"tlut059", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_30", 0x106478}}, + {F, {"tlut060", 0, 9, 0x0}}, + {F, {"tlut061", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_31", 0x10647C}}, + {F, {"tlut062", 0, 9, 0x0}}, + {F, {"tlut063", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_32", 0x106480}}, + {F, {"tlut064", 0, 9, 0x0}}, + {F, {"tlut065", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_33", 0x106484}}, + {F, {"tlut066", 0, 9, 0x0}}, + {F, {"tlut067", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_34", 0x106488}}, + {F, {"tlut068", 0, 9, 0x0}}, + {F, {"tlut069", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_35", 0x10648C}}, + {F, {"tlut070", 0, 9, 0x0}}, + {F, {"tlut071", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_36", 0x106490}}, + {F, {"tlut072", 0, 9, 0x0}}, + {F, {"tlut073", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_37", 0x106494}}, + {F, {"tlut074", 0, 9, 0x0}}, + {F, {"tlut075", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_38", 0x106498}}, + {F, {"tlut076", 0, 9, 0x0}}, + {F, {"tlut077", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_39", 0x10649C}}, + {F, {"tlut078", 0, 9, 0x0}}, + {F, {"tlut079", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_40", 0x1064A0}}, + {F, {"tlut080", 0, 9, 0x0}}, + {F, {"tlut081", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_41", 0x1064A4}}, + {F, {"tlut082", 0, 9, 0x0}}, + {F, {"tlut083", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_42", 0x1064A8}}, + {F, {"tlut084", 0, 9, 0x0}}, + {F, {"tlut085", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_43", 0x1064AC}}, + {F, {"tlut086", 0, 9, 0x0}}, + {F, {"tlut087", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_44", 0x1064B0}}, + {F, {"tlut088", 0, 9, 0x0}}, + {F, {"tlut089", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_45", 0x1064B4}}, + {F, {"tlut090", 0, 9, 0x0}}, + {F, {"tlut091", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_46", 0x1064B8}}, + {F, {"tlut092", 0, 9, 0x0}}, + {F, {"tlut093", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_47", 0x1064BC}}, + {F, {"tlut094", 0, 9, 0x0}}, + {F, {"tlut095", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_48", 0x1064C0}}, + {F, {"tlut096", 0, 9, 0x0}}, + {F, {"tlut097", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_49", 0x1064C4}}, + {F, {"tlut098", 0, 9, 0x0}}, + {F, {"tlut099", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_50", 0x1064C8}}, + {F, {"tlut100", 0, 9, 0x0}}, + {F, {"tlut101", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_51", 0x1064CC}}, + {F, {"tlut102", 0, 9, 0x0}}, + {F, {"tlut103", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_52", 0x1064D0}}, + {F, {"tlut104", 0, 9, 0x0}}, + {F, {"tlut105", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_53", 0x1064D4}}, + {F, {"tlut106", 0, 9, 0x0}}, + {F, {"tlut107", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_54", 0x1064D8}}, + {F, {"tlut108", 0, 9, 0x0}}, + {F, {"tlut109", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_55", 0x1064DC}}, + {F, {"tlut110", 0, 9, 0x0}}, + {F, {"tlut111", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_56", 0x1064E0}}, + {F, {"tlut112", 0, 9, 0x0}}, + {F, {"tlut113", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_57", 0x1064E4}}, + {F, {"tlut114", 0, 9, 0x0}}, + {F, {"tlut115", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_58", 0x1064E8}}, + {F, {"tlut116", 0, 9, 0x0}}, + {F, {"tlut117", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_59", 0x1064EC}}, + {F, {"tlut118", 0, 9, 0x0}}, + {F, {"tlut119", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_60", 0x1064F0}}, + {F, {"tlut120", 0, 9, 0x0}}, + {F, {"tlut121", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_61", 0x1064F4}}, + {F, {"tlut122", 0, 9, 0x0}}, + {F, {"tlut123", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_62", 0x1064F8}}, + {F, {"tlut124", 0, 9, 0x0}}, + {F, {"tlut125", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_63", 0x1064FC}}, + {F, {"tlut126", 0, 9, 0x0}}, + {F, {"tlut127", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_64", 0x106500}}, + {F, {"tlut128", 0, 9, 0x0}}, + {F, {"tlut129", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_65", 0x106504}}, + {F, {"tlut130", 0, 9, 0x0}}, + {F, {"tlut131", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_66", 0x106508}}, + {F, {"tlut132", 0, 9, 0x0}}, + {F, {"tlut133", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_67", 0x10650C}}, + {F, {"tlut134", 0, 9, 0x0}}, + {F, {"tlut135", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_68", 0x106510}}, + {F, {"tlut136", 0, 9, 0x0}}, + {F, {"tlut137", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_69", 0x106514}}, + {F, {"tlut138", 0, 9, 0x0}}, + {F, {"tlut139", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_70", 0x106518}}, + {F, {"tlut140", 0, 9, 0x0}}, + {F, {"tlut141", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_71", 0x10651C}}, + {F, {"tlut142", 0, 9, 0x0}}, + {F, {"tlut143", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_72", 0x106520}}, + {F, {"tlut144", 0, 9, 0x0}}, + {F, {"tlut145", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_73", 0x106524}}, + {F, {"tlut146", 0, 9, 0x0}}, + {F, {"tlut147", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_74", 0x106528}}, + {F, {"tlut148", 0, 9, 0x0}}, + {F, {"tlut149", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_75", 0x10652C}}, + {F, {"tlut150", 0, 9, 0x0}}, + {F, {"tlut151", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_76", 0x106530}}, + {F, {"tlut152", 0, 9, 0x0}}, + {F, {"tlut153", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_77", 0x106534}}, + {F, {"tlut154", 0, 9, 0x0}}, + {F, {"tlut155", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_78", 0x106538}}, + {F, {"tlut156", 0, 9, 0x0}}, + {F, {"tlut157", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_79", 0x10653C}}, + {F, {"tlut158", 0, 9, 0x0}}, + {F, {"tlut159", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_80", 0x106540}}, + {F, {"tlut160", 0, 9, 0x0}}, + {F, {"tlut161", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_81", 0x106544}}, + {F, {"tlut162", 0, 9, 0x0}}, + {F, {"tlut163", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_82", 0x106548}}, + {F, {"tlut164", 0, 9, 0x0}}, + {F, {"tlut165", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_83", 0x10654C}}, + {F, {"tlut166", 0, 9, 0x0}}, + {F, {"tlut167", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_84", 0x106550}}, + {F, {"tlut168", 0, 9, 0x0}}, + {F, {"tlut169", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_85", 0x106554}}, + {F, {"tlut170", 0, 9, 0x0}}, + {F, {"tlut171", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_86", 0x106558}}, + {F, {"tlut172", 0, 9, 0x0}}, + {F, {"tlut173", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_87", 0x10655C}}, + {F, {"tlut174", 0, 9, 0x0}}, + {F, {"tlut175", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_88", 0x106560}}, + {F, {"tlut176", 0, 9, 0x0}}, + {F, {"tlut177", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_89", 0x106564}}, + {F, {"tlut178", 0, 9, 0x0}}, + {F, {"tlut179", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_90", 0x106568}}, + {F, {"tlut180", 0, 9, 0x0}}, + {F, {"tlut181", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_91", 0x10656C}}, + {F, {"tlut182", 0, 9, 0x0}}, + {F, {"tlut183", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_92", 0x106570}}, + {F, {"tlut184", 0, 9, 0x0}}, + {F, {"tlut185", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_93", 0x106574}}, + {F, {"tlut186", 0, 9, 0x0}}, + {F, {"tlut187", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_94", 0x106578}}, + {F, {"tlut188", 0, 9, 0x0}}, + {F, {"tlut189", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_95", 0x10657C}}, + {F, {"tlut190", 0, 9, 0x0}}, + {F, {"tlut191", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_96", 0x106580}}, + {F, {"tlut192", 0, 9, 0x0}}, + {F, {"tlut193", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_97", 0x106584}}, + {F, {"tlut194", 0, 9, 0x0}}, + {F, {"tlut195", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_98", 0x106588}}, + {F, {"tlut196", 0, 9, 0x0}}, + {F, {"tlut197", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_99", 0x10658C}}, + {F, {"tlut198", 0, 9, 0x0}}, + {F, {"tlut199", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_100", 0x106590}}, + {F, {"tlut200", 0, 9, 0x0}}, + {F, {"tlut201", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_101", 0x106594}}, + {F, {"tlut202", 0, 9, 0x0}}, + {F, {"tlut203", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_102", 0x106598}}, + {F, {"tlut204", 0, 9, 0x0}}, + {F, {"tlut205", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_103", 0x10659C}}, + {F, {"tlut206", 0, 9, 0x0}}, + {F, {"tlut207", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_104", 0x1065A0}}, + {F, {"tlut208", 0, 9, 0x0}}, + {F, {"tlut209", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_105", 0x1065A4}}, + {F, {"tlut210", 0, 9, 0x0}}, + {F, {"tlut211", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_106", 0x1065A8}}, + {F, {"tlut212", 0, 9, 0x0}}, + {F, {"tlut213", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_107", 0x1065AC}}, + {F, {"tlut214", 0, 9, 0x0}}, + {F, {"tlut215", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_108", 0x1065B0}}, + {F, {"tlut216", 0, 9, 0x0}}, + {F, {"tlut217", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_109", 0x1065B4}}, + {F, {"tlut218", 0, 9, 0x0}}, + {F, {"tlut219", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_110", 0x1065B8}}, + {F, {"tlut220", 0, 9, 0x0}}, + {F, {"tlut221", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_111", 0x1065BC}}, + {F, {"tlut222", 0, 9, 0x0}}, + {F, {"tlut223", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_112", 0x1065C0}}, + {F, {"tlut224", 0, 9, 0x0}}, + {F, {"tlut225", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_113", 0x1065C4}}, + {F, {"tlut226", 0, 9, 0x0}}, + {F, {"tlut227", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_114", 0x1065C8}}, + {F, {"tlut228", 0, 9, 0x0}}, + {F, {"tlut229", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_115", 0x1065CC}}, + {F, {"tlut230", 0, 9, 0x0}}, + {F, {"tlut231", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_116", 0x1065D0}}, + {F, {"tlut232", 0, 9, 0x0}}, + {F, {"tlut233", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_117", 0x1065D4}}, + {F, {"tlut234", 0, 9, 0x0}}, + {F, {"tlut235", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_118", 0x1065D8}}, + {F, {"tlut236", 0, 9, 0x0}}, + {F, {"tlut237", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_119", 0x1065DC}}, + {F, {"tlut238", 0, 9, 0x0}}, + {F, {"tlut239", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_120", 0x1065E0}}, + {F, {"tlut240", 0, 9, 0x0}}, + {F, {"tlut241", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_121", 0x1065E4}}, + {F, {"tlut242", 0, 9, 0x0}}, + {F, {"tlut243", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_122", 0x1065E8}}, + {F, {"tlut244", 0, 9, 0x0}}, + {F, {"tlut245", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_123", 0x1065EC}}, + {F, {"tlut246", 0, 9, 0x0}}, + {F, {"tlut247", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_124", 0x1065F0}}, + {F, {"tlut248", 0, 9, 0x0}}, + {F, {"tlut249", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_125", 0x1065F4}}, + {F, {"tlut250", 0, 9, 0x0}}, + {F, {"tlut251", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_126", 0x1065F8}}, + {F, {"tlut252", 0, 9, 0x0}}, + {F, {"tlut253", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_127", 0x1065FC}}, + {F, {"tlut254", 0, 9, 0x0}}, + {F, {"tlut255", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_128", 0x106600}}, + {F, {"tlut256", 0, 9, 0x0}}, + {F, {"tlut257", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_129", 0x106604}}, + {F, {"tlut258", 0, 9, 0x0}}, + {F, {"tlut259", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_130", 0x106608}}, + {F, {"tlut260", 0, 9, 0x0}}, + {F, {"tlut261", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_131", 0x10660C}}, + {F, {"tlut262", 0, 9, 0x0}}, + {F, {"tlut263", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_132", 0x106610}}, + {F, {"tlut264", 0, 9, 0x0}}, + {F, {"tlut265", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_133", 0x106614}}, + {F, {"tlut266", 0, 9, 0x0}}, + {F, {"tlut267", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_134", 0x106618}}, + {F, {"tlut268", 0, 9, 0x0}}, + {F, {"tlut269", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_135", 0x10661C}}, + {F, {"tlut270", 0, 9, 0x0}}, + {F, {"tlut271", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_136", 0x106620}}, + {F, {"tlut272", 0, 9, 0x0}}, + {F, {"tlut273", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_137", 0x106624}}, + {F, {"tlut274", 0, 9, 0x0}}, + {F, {"tlut275", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_138", 0x106628}}, + {F, {"tlut276", 0, 9, 0x0}}, + {F, {"tlut277", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_139", 0x10662C}}, + {F, {"tlut278", 0, 9, 0x0}}, + {F, {"tlut279", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_140", 0x106630}}, + {F, {"tlut280", 0, 9, 0x0}}, + {F, {"tlut281", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_141", 0x106634}}, + {F, {"tlut282", 0, 9, 0x0}}, + {F, {"tlut283", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_142", 0x106638}}, + {F, {"tlut284", 0, 9, 0x0}}, + {F, {"tlut285", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_143", 0x10663C}}, + {F, {"tlut286", 0, 9, 0x0}}, + {F, {"tlut287", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_144", 0x106640}}, + {F, {"tlut288", 0, 9, 0x0}}, + {F, {"tlut289", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_145", 0x106644}}, + {F, {"tlut290", 0, 9, 0x0}}, + {F, {"tlut291", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_146", 0x106648}}, + {F, {"tlut292", 0, 9, 0x0}}, + {F, {"tlut293", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_147", 0x10664C}}, + {F, {"tlut294", 0, 9, 0x0}}, + {F, {"tlut295", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_148", 0x106650}}, + {F, {"tlut296", 0, 9, 0x0}}, + {F, {"tlut297", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_149", 0x106654}}, + {F, {"tlut298", 0, 9, 0x0}}, + {F, {"tlut299", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_150", 0x106658}}, + {F, {"tlut300", 0, 9, 0x0}}, + {F, {"tlut301", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_151", 0x10665C}}, + {F, {"tlut302", 0, 9, 0x0}}, + {F, {"tlut303", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_152", 0x106660}}, + {F, {"tlut304", 0, 9, 0x0}}, + {F, {"tlut305", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_153", 0x106664}}, + {F, {"tlut306", 0, 9, 0x0}}, + {F, {"tlut307", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_154", 0x106668}}, + {F, {"tlut308", 0, 9, 0x0}}, + {F, {"tlut309", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_155", 0x10666C}}, + {F, {"tlut310", 0, 9, 0x0}}, + {F, {"tlut311", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_156", 0x106670}}, + {F, {"tlut312", 0, 9, 0x0}}, + {F, {"tlut313", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_157", 0x106674}}, + {F, {"tlut314", 0, 9, 0x0}}, + {F, {"tlut315", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_158", 0x106678}}, + {F, {"tlut316", 0, 9, 0x0}}, + {F, {"tlut317", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_159", 0x10667C}}, + {F, {"tlut318", 0, 9, 0x0}}, + {F, {"tlut319", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_160", 0x106680}}, + {F, {"tlut320", 0, 9, 0x0}}, + {F, {"tlut321", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_161", 0x106684}}, + {F, {"tlut322", 0, 9, 0x0}}, + {F, {"tlut323", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_162", 0x106688}}, + {F, {"tlut324", 0, 9, 0x0}}, + {F, {"tlut325", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_163", 0x10668C}}, + {F, {"tlut326", 0, 9, 0x0}}, + {F, {"tlut327", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_164", 0x106690}}, + {F, {"tlut328", 0, 9, 0x0}}, + {F, {"tlut329", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_165", 0x106694}}, + {F, {"tlut330", 0, 9, 0x0}}, + {F, {"tlut331", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_166", 0x106698}}, + {F, {"tlut332", 0, 9, 0x0}}, + {F, {"tlut333", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_167", 0x10669C}}, + {F, {"tlut334", 0, 9, 0x0}}, + {F, {"tlut335", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_168", 0x1066A0}}, + {F, {"tlut336", 0, 9, 0x0}}, + {F, {"tlut337", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_169", 0x1066A4}}, + {F, {"tlut338", 0, 9, 0x0}}, + {F, {"tlut339", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_170", 0x1066A8}}, + {F, {"tlut340", 0, 9, 0x0}}, + {F, {"tlut341", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_171", 0x1066AC}}, + {F, {"tlut342", 0, 9, 0x0}}, + {F, {"tlut343", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_172", 0x1066B0}}, + {F, {"tlut344", 0, 9, 0x0}}, + {F, {"tlut345", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_173", 0x1066B4}}, + {F, {"tlut346", 0, 9, 0x0}}, + {F, {"tlut347", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_174", 0x1066B8}}, + {F, {"tlut348", 0, 9, 0x0}}, + {F, {"tlut349", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_175", 0x1066BC}}, + {F, {"tlut350", 0, 9, 0x0}}, + {F, {"tlut351", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_176", 0x1066C0}}, + {F, {"tlut352", 0, 9, 0x0}}, + {F, {"tlut353", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_177", 0x1066C4}}, + {F, {"tlut354", 0, 9, 0x0}}, + {F, {"tlut355", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_178", 0x1066C8}}, + {F, {"tlut356", 0, 9, 0x0}}, + {F, {"tlut357", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_179", 0x1066CC}}, + {F, {"tlut358", 0, 9, 0x0}}, + {F, {"tlut359", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_180", 0x1066D0}}, + {F, {"tlut360", 0, 9, 0x0}}, + {F, {"tlut361", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_181", 0x1066D4}}, + {F, {"tlut362", 0, 9, 0x0}}, + {F, {"tlut363", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_182", 0x1066D8}}, + {F, {"tlut364", 0, 9, 0x0}}, + {F, {"tlut365", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_183", 0x1066DC}}, + {F, {"tlut366", 0, 9, 0x0}}, + {F, {"tlut367", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_184", 0x1066E0}}, + {F, {"tlut368", 0, 9, 0x0}}, + {F, {"tlut369", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_185", 0x1066E4}}, + {F, {"tlut370", 0, 9, 0x0}}, + {F, {"tlut371", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_186", 0x1066E8}}, + {F, {"tlut372", 0, 9, 0x0}}, + {F, {"tlut373", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_187", 0x1066EC}}, + {F, {"tlut374", 0, 9, 0x0}}, + {F, {"tlut375", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_188", 0x1066F0}}, + {F, {"tlut376", 0, 9, 0x0}}, + {F, {"tlut377", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_189", 0x1066F4}}, + {F, {"tlut378", 0, 9, 0x0}}, + {F, {"tlut379", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_190", 0x1066F8}}, + {F, {"tlut380", 0, 9, 0x0}}, + {F, {"tlut381", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_191", 0x1066FC}}, + {F, {"tlut382", 0, 9, 0x0}}, + {F, {"tlut383", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_192", 0x106700}}, + {F, {"tlut384", 0, 9, 0x0}}, + {F, {"tlut385", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_193", 0x106704}}, + {F, {"tlut386", 0, 9, 0x0}}, + {F, {"tlut387", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_194", 0x106708}}, + {F, {"tlut388", 0, 9, 0x0}}, + {F, {"tlut389", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_195", 0x10670C}}, + {F, {"tlut390", 0, 9, 0x0}}, + {F, {"tlut391", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_196", 0x106710}}, + {F, {"tlut392", 0, 9, 0x0}}, + {F, {"tlut393", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_197", 0x106714}}, + {F, {"tlut394", 0, 9, 0x0}}, + {F, {"tlut395", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_198", 0x106718}}, + {F, {"tlut396", 0, 9, 0x0}}, + {F, {"tlut397", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_199", 0x10671C}}, + {F, {"tlut398", 0, 9, 0x0}}, + {F, {"tlut399", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_200", 0x106720}}, + {F, {"tlut400", 0, 9, 0x0}}, + {F, {"tlut401", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_201", 0x106724}}, + {F, {"tlut402", 0, 9, 0x0}}, + {F, {"tlut403", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_202", 0x106728}}, + {F, {"tlut404", 0, 9, 0x0}}, + {F, {"tlut405", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_203", 0x10672C}}, + {F, {"tlut406", 0, 9, 0x0}}, + {F, {"tlut407", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_204", 0x106730}}, + {F, {"tlut408", 0, 9, 0x0}}, + {F, {"tlut409", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_205", 0x106734}}, + {F, {"tlut410", 0, 9, 0x0}}, + {F, {"tlut411", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_206", 0x106738}}, + {F, {"tlut412", 0, 9, 0x0}}, + {F, {"tlut413", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_207", 0x10673C}}, + {F, {"tlut414", 0, 9, 0x0}}, + {F, {"tlut415", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_208", 0x106740}}, + {F, {"tlut416", 0, 9, 0x0}}, + {F, {"tlut417", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_209", 0x106744}}, + {F, {"tlut418", 0, 9, 0x0}}, + {F, {"tlut419", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_210", 0x106748}}, + {F, {"tlut420", 0, 9, 0x0}}, + {F, {"tlut421", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_211", 0x10674C}}, + {F, {"tlut422", 0, 9, 0x0}}, + {F, {"tlut423", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_212", 0x106750}}, + {F, {"tlut424", 0, 9, 0x0}}, + {F, {"tlut425", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_213", 0x106754}}, + {F, {"tlut426", 0, 9, 0x0}}, + {F, {"tlut427", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_214", 0x106758}}, + {F, {"tlut428", 0, 9, 0x0}}, + {F, {"tlut429", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_215", 0x10675C}}, + {F, {"tlut430", 0, 9, 0x0}}, + {F, {"tlut431", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_216", 0x106760}}, + {F, {"tlut432", 0, 9, 0x0}}, + {F, {"tlut433", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_217", 0x106764}}, + {F, {"tlut434", 0, 9, 0x0}}, + {F, {"tlut435", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_218", 0x106768}}, + {F, {"tlut436", 0, 9, 0x0}}, + {F, {"tlut437", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_219", 0x10676C}}, + {F, {"tlut438", 0, 9, 0x0}}, + {F, {"tlut439", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_220", 0x106770}}, + {F, {"tlut440", 0, 9, 0x0}}, + {F, {"tlut441", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_221", 0x106774}}, + {F, {"tlut442", 0, 9, 0x0}}, + {F, {"tlut443", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_222", 0x106778}}, + {F, {"tlut444", 0, 9, 0x0}}, + {F, {"tlut445", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_223", 0x10677C}}, + {F, {"tlut446", 0, 9, 0x0}}, + {F, {"tlut447", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_224", 0x106780}}, + {F, {"tlut448", 0, 9, 0x0}}, + {F, {"tlut449", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_225", 0x106784}}, + {F, {"tlut450", 0, 9, 0x0}}, + {F, {"tlut451", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_226", 0x106788}}, + {F, {"tlut452", 0, 9, 0x0}}, + {F, {"tlut453", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_227", 0x10678C}}, + {F, {"tlut454", 0, 9, 0x0}}, + {F, {"tlut455", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_228", 0x106790}}, + {F, {"tlut456", 0, 9, 0x0}}, + {F, {"tlut457", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_229", 0x106794}}, + {F, {"tlut458", 0, 9, 0x0}}, + {F, {"tlut459", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_230", 0x106798}}, + {F, {"tlut460", 0, 9, 0x0}}, + {F, {"tlut461", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_231", 0x10679C}}, + {F, {"tlut462", 0, 9, 0x0}}, + {F, {"tlut463", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_232", 0x1067A0}}, + {F, {"tlut464", 0, 9, 0x0}}, + {F, {"tlut465", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_233", 0x1067A4}}, + {F, {"tlut466", 0, 9, 0x0}}, + {F, {"tlut467", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_234", 0x1067A8}}, + {F, {"tlut468", 0, 9, 0x0}}, + {F, {"tlut469", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_235", 0x1067AC}}, + {F, {"tlut470", 0, 9, 0x0}}, + {F, {"tlut471", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_236", 0x1067B0}}, + {F, {"tlut472", 0, 9, 0x0}}, + {F, {"tlut473", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_237", 0x1067B4}}, + {F, {"tlut474", 0, 9, 0x0}}, + {F, {"tlut475", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_238", 0x1067B8}}, + {F, {"tlut476", 0, 9, 0x0}}, + {F, {"tlut477", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_239", 0x1067BC}}, + {F, {"tlut478", 0, 9, 0x0}}, + {F, {"tlut479", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_240", 0x1067C0}}, + {F, {"tlut480", 0, 9, 0x0}}, + {F, {"tlut481", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_241", 0x1067C4}}, + {F, {"tlut482", 0, 9, 0x0}}, + {F, {"tlut483", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_242", 0x1067C8}}, + {F, {"tlut484", 0, 9, 0x0}}, + {F, {"tlut485", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_243", 0x1067CC}}, + {F, {"tlut486", 0, 9, 0x0}}, + {F, {"tlut487", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_244", 0x1067D0}}, + {F, {"tlut488", 0, 9, 0x0}}, + {F, {"tlut489", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_245", 0x1067D4}}, + {F, {"tlut490", 0, 9, 0x0}}, + {F, {"tlut491", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_246", 0x1067D8}}, + {F, {"tlut492", 0, 9, 0x0}}, + {F, {"tlut493", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_247", 0x1067DC}}, + {F, {"tlut494", 0, 9, 0x0}}, + {F, {"tlut495", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_248", 0x1067E0}}, + {F, {"tlut496", 0, 9, 0x0}}, + {F, {"tlut497", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_249", 0x1067E4}}, + {F, {"tlut498", 0, 9, 0x0}}, + {F, {"tlut499", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_250", 0x1067E8}}, + {F, {"tlut500", 0, 9, 0x0}}, + {F, {"tlut501", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_251", 0x1067EC}}, + {F, {"tlut502", 0, 9, 0x0}}, + {F, {"tlut503", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_252", 0x1067F0}}, + {F, {"tlut504", 0, 9, 0x0}}, + {F, {"tlut505", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_253", 0x1067F4}}, + {F, {"tlut506", 0, 9, 0x0}}, + {F, {"tlut507", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_254", 0x1067F8}}, + {F, {"tlut508", 0, 9, 0x0}}, + {F, {"tlut509", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/t_drop_lut_255", 0x1067FC}}, + {F, {"tlut510", 0, 9, 0x0}}, + {F, {"tlut511", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6800", 0x106800}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6804", 0x106804}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6808", 0x106808}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_680C", 0x10680C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6810", 0x106810}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6814", 0x106814}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6818", 0x106818}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_681C", 0x10681C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6820", 0x106820}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6824", 0x106824}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6828", 0x106828}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_682C", 0x10682C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6830", 0x106830}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6834", 0x106834}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6838", 0x106838}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_683C", 0x10683C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6840", 0x106840}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6844", 0x106844}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6848", 0x106848}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_684C", 0x10684C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6850", 0x106850}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6854", 0x106854}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6858", 0x106858}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_685C", 0x10685C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6860", 0x106860}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6864", 0x106864}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6868", 0x106868}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_686C", 0x10686C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6870", 0x106870}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6874", 0x106874}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6878", 0x106878}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_687C", 0x10687C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6880", 0x106880}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6884", 0x106884}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6888", 0x106888}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_688C", 0x10688C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6890", 0x106890}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6894", 0x106894}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6898", 0x106898}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_689C", 0x10689C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68A0", 0x1068A0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68A4", 0x1068A4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68A8", 0x1068A8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68AC", 0x1068AC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68B0", 0x1068B0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68B4", 0x1068B4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68B8", 0x1068B8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68BC", 0x1068BC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68C0", 0x1068C0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68C4", 0x1068C4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68C8", 0x1068C8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68CC", 0x1068CC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68D0", 0x1068D0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68D4", 0x1068D4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68D8", 0x1068D8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68DC", 0x1068DC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68E0", 0x1068E0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68E4", 0x1068E4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68E8", 0x1068E8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68EC", 0x1068EC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68F0", 0x1068F0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68F4", 0x1068F4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68F8", 0x1068F8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_68FC", 0x1068FC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6900", 0x106900}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6904", 0x106904}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6908", 0x106908}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_690C", 0x10690C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6910", 0x106910}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6914", 0x106914}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6918", 0x106918}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_691C", 0x10691C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6920", 0x106920}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6924", 0x106924}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6928", 0x106928}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_692C", 0x10692C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6930", 0x106930}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6934", 0x106934}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6938", 0x106938}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_693C", 0x10693C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6940", 0x106940}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6944", 0x106944}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6948", 0x106948}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_694C", 0x10694C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6950", 0x106950}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6954", 0x106954}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6958", 0x106958}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_695C", 0x10695C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6960", 0x106960}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6964", 0x106964}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6968", 0x106968}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_696C", 0x10696C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6970", 0x106970}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6974", 0x106974}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6978", 0x106978}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_697C", 0x10697C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6980", 0x106980}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6984", 0x106984}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6988", 0x106988}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_698C", 0x10698C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6990", 0x106990}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6994", 0x106994}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6998", 0x106998}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_699C", 0x10699C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69A0", 0x1069A0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69A4", 0x1069A4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69A8", 0x1069A8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69AC", 0x1069AC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69B0", 0x1069B0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69B4", 0x1069B4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69B8", 0x1069B8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69BC", 0x1069BC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69C0", 0x1069C0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69C4", 0x1069C4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69C8", 0x1069C8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69CC", 0x1069CC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69D0", 0x1069D0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69D4", 0x1069D4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69D8", 0x1069D8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69DC", 0x1069DC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69E0", 0x1069E0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69E4", 0x1069E4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69E8", 0x1069E8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69EC", 0x1069EC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69F0", 0x1069F0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69F4", 0x1069F4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69F8", 0x1069F8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_69FC", 0x1069FC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A00", 0x106A00}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A04", 0x106A04}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A08", 0x106A08}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A0C", 0x106A0C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A10", 0x106A10}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A14", 0x106A14}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A18", 0x106A18}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A1C", 0x106A1C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A20", 0x106A20}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A24", 0x106A24}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A28", 0x106A28}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A2C", 0x106A2C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A30", 0x106A30}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A34", 0x106A34}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A38", 0x106A38}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A3C", 0x106A3C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A40", 0x106A40}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A44", 0x106A44}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A48", 0x106A48}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A4C", 0x106A4C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A50", 0x106A50}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A54", 0x106A54}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A58", 0x106A58}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A5C", 0x106A5C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A60", 0x106A60}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A64", 0x106A64}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A68", 0x106A68}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A6C", 0x106A6C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A70", 0x106A70}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A74", 0x106A74}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A78", 0x106A78}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A7C", 0x106A7C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A80", 0x106A80}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A84", 0x106A84}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A88", 0x106A88}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A8C", 0x106A8C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A90", 0x106A90}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A94", 0x106A94}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A98", 0x106A98}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6A9C", 0x106A9C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AA0", 0x106AA0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AA4", 0x106AA4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AA8", 0x106AA8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AAC", 0x106AAC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AB0", 0x106AB0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AB4", 0x106AB4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AB8", 0x106AB8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6ABC", 0x106ABC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AC0", 0x106AC0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AC4", 0x106AC4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AC8", 0x106AC8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6ACC", 0x106ACC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AD0", 0x106AD0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AD4", 0x106AD4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AD8", 0x106AD8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6ADC", 0x106ADC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AE0", 0x106AE0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AE4", 0x106AE4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AE8", 0x106AE8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AEC", 0x106AEC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AF0", 0x106AF0}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AF4", 0x106AF4}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AF8", 0x106AF8}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6AFC", 0x106AFC}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B00", 0x106B00}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B04", 0x106B04}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B08", 0x106B08}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B0C", 0x106B0C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B10", 0x106B10}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B14", 0x106B14}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B18", 0x106B18}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B1C", 0x106B1C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B20", 0x106B20}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B24", 0x106B24}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B28", 0x106B28}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B2C", 0x106B2C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B30", 0x106B30}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B34", 0x106B34}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B38", 0x106B38}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B3C", 0x106B3C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B40", 0x106B40}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B44", 0x106B44}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B48", 0x106B48}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B4C", 0x106B4C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B50", 0x106B50}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B54", 0x106B54}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B58", 0x106B58}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B5C", 0x106B5C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B60", 0x106B60}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B64", 0x106B64}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B68", 0x106B68}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B6C", 0x106B6C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B70", 0x106B70}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B74", 0x106B74}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B78", 0x106B78}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B7C", 0x106B7C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B80", 0x106B80}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B84", 0x106B84}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B88", 0x106B88}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B8C", 0x106B8C}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B90", 0x106B90}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/erc/Reserved_6B94", 0x106B94}}, + {F, {"Reserved_5_0", 0, 6, 0x0}}, + {F, {"Reserved_13_8", 8, 6, 0x0}}, + {F, {"Reserved_21_16", 16, 6, 0x0}}, + {F, {"Reserved_29_24", 24, 6, 0x0}}, + + {R, {"SENSOR_IF/IMX636/edf/pipeline_control", 0x107000}}, + {F, {"Reserved_0", 0, 1, 0x1}}, + {F, {"format", 1, 1, 0x0}}, + {F, {"Reserved_2", 2, 1, 0x0}}, + {F, {"Reserved_3", 3, 1, 0x0}}, + {F, {"Reserved_4", 4, 1, 0x0}}, + {F, {"Reserved_31_16", 16, 16, 0xFFFF}}, + + {R, {"SENSOR_IF/IMX636/edf/Reserved_7004", 0x107004}}, + {F, {"Reserved_10", 10, 1, 0x1}}, + + {R, {"SENSOR_IF/IMX636/eoi/Reserved_8000", 0x108000}}, + {F, {"Reserved_7_6", 6, 2, 0x2}}, + + {R, {"SENSOR_IF/IMX636/ro/readout_ctrl", 0x109000}}, + {F, {"Reserved_0", 0, 1, 0x0}}, + {F, {"ro_td_self_test_en", 1, 1, 0x0}}, + {F, {"Reserved_3", 3, 1, 0x1}}, + {F, {"Reserved_4", 4, 1, 0x0}}, + {F, {"ro_inv_pol_td", 5, 1, 0x0}}, + {F, {"Reserved_7_6", 6, 2, 0x0}}, + {F, {"Reserved_31_8", 8, 24, 0x2}}, + + {R, {"SENSOR_IF/IMX636/ro/ro_fsm_ctrl", 0x109004}}, + {F, {"readout_wait", 0, 16, 0x1E}}, + {F, {"Reserved_31_16", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/time_base_ctrl", 0x109008}}, + {F, {"time_base_enable", 0, 1, 0x0}}, + {F, {"time_base_mode", 1, 1, 0x0}}, + {F, {"external_mode", 2, 1, 0x0}}, + {F, {"external_mode_enable", 3, 1, 0x0}}, + {F, {"Reserved_10_4", 4, 7, 0x64}}, + + {R, {"SENSOR_IF/IMX636/ro/dig_ctrl", 0x10900C}}, + {F, {"dig_crop_enable", 0, 3, 0x0}}, + {F, {"dig_crop_reset_orig", 4, 1, 0x0}}, + {F, {"Reserved_31_5", 5, 27, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/dig_start_pos", 0x109010}}, + {F, {"dig_crop_start_x", 0, 11, 0x0}}, + {F, {"dig_crop_start_y", 16, 10, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/dig_end_pos", 0x109014}}, + {F, {"dig_crop_end_x", 0, 11, 0x0}}, + {F, {"dig_crop_end_y", 16, 10, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/ro_ctrl", 0x109028}}, + {F, {"area_cnt_en", 0, 1, 0x0}}, + {F, {"output_disable", 1, 1, 0x0}}, + {F, {"keep_th", 2, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_x0_addr", 0x10902C}}, + {F, {"x0_addr", 0, 11, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_x1_addr", 0x109030}}, + {F, {"x1_addr", 0, 11, 0x140}}, + + {R, {"SENSOR_IF/IMX636/ro/area_x2_addr", 0x109034}}, + {F, {"x2_addr", 0, 11, 0x280}}, + + {R, {"SENSOR_IF/IMX636/ro/area_x3_addr", 0x109038}}, + {F, {"x3_addr", 0, 11, 0x3C0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_x4_addr", 0x10903C}}, + {F, {"x4_addr", 0, 11, 0x500}}, + + {R, {"SENSOR_IF/IMX636/ro/area_y0_addr", 0x109040}}, + {F, {"y0_addr", 0, 11, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_y1_addr", 0x109044}}, + {F, {"y1_addr", 0, 11, 0xB4}}, + + {R, {"SENSOR_IF/IMX636/ro/area_y2_addr", 0x109048}}, + {F, {"y2_addr", 0, 11, 0x168}}, + + {R, {"SENSOR_IF/IMX636/ro/area_y3_addr", 0x10904C}}, + {F, {"y3_addr", 0, 11, 0x21C}}, + + {R, {"SENSOR_IF/IMX636/ro/area_y4_addr", 0x109050}}, + {F, {"y4_addr", 0, 11, 0x2D0}}, + + {R, {"SENSOR_IF/IMX636/ro/counter_ctrl", 0x109054}}, + {F, {"count_en", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"Reserved_2", 2, 1, 0x1}}, + + {R, {"SENSOR_IF/IMX636/ro/counter_timer_threshold", 0x109058}}, + {F, {"timer_threshold", 0, 32, 0x3E8}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_00", 0x109100}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_01", 0x109104}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_02", 0x109108}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_03", 0x10910C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_04", 0x109110}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_05", 0x109114}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_06", 0x109118}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_07", 0x10911C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_08", 0x109120}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_09", 0x109124}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_10", 0x109128}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_11", 0x10912C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_12", 0x109130}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_13", 0x109134}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_14", 0x109138}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_15", 0x10913C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_16", 0x109140}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_17", 0x109144}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_18", 0x109148}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_19", 0x10914C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_20", 0x109150}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_21", 0x109154}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_22", 0x109158}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_23", 0x10915C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_24", 0x109160}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_25", 0x109164}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_26", 0x109168}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_27", 0x10916C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_28", 0x109170}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_29", 0x109174}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_30", 0x109178}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_31", 0x10917C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_32", 0x109180}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_33", 0x109184}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_34", 0x109188}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_35", 0x10918C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_36", 0x109190}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_37", 0x109194}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_38", 0x109198}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_39", 0x10919C}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_40", 0x1091A0}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_41", 0x1091A4}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_42", 0x1091A8}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_43", 0x1091AC}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_44", 0x1091B0}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_45", 0x1091B4}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_46", 0x1091B8}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_47", 0x1091BC}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_48", 0x1091C0}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_49", 0x1091C4}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_50", 0x1091C8}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_51", 0x1091CC}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_52", 0x1091D0}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_53", 0x1091D4}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_54", 0x1091D8}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_55", 0x1091DC}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_56", 0x1091E0}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_57", 0x1091E4}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_58", 0x1091E8}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_59", 0x1091EC}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_60", 0x1091F0}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_61", 0x1091F4}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_62", 0x1091F8}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/digital_mask_pixel_63", 0x1091FC}}, + {F, {"x", 0, 11, 0x0}}, + {F, {"y", 16, 11, 0x0}}, + {F, {"valid", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt00", 0x109200}}, + {F, {"area_cnt_val_00", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt01", 0x109204}}, + {F, {"area_cnt_val_01", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt02", 0x109208}}, + {F, {"area_cnt_val_02", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt03", 0x10920C}}, + {F, {"area_cnt_val_03", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt04", 0x109210}}, + {F, {"area_cnt_val_04", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt05", 0x109214}}, + {F, {"area_cnt_val_05", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt06", 0x109218}}, + {F, {"area_cnt_val_06", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt07", 0x10921C}}, + {F, {"area_cnt_val_07", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt08", 0x109220}}, + {F, {"area_cnt_val_08", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt09", 0x109224}}, + {F, {"area_cnt_val_09", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt10", 0x109228}}, + {F, {"area_cnt_val_10", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt11", 0x10922C}}, + {F, {"area_cnt_val_11", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt12", 0x109230}}, + {F, {"area_cnt_val_12", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt13", 0x109234}}, + {F, {"area_cnt_val_13", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt14", 0x109238}}, + {F, {"area_cnt_val_14", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/area_cnt15", 0x10923C}}, + {F, {"area_cnt_val_15", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/ro/evt_vector_cnt_val", 0x109244}}, + {F, {"evt_vector_cnt_val", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/mipi_csi/mipi_control", 0x10B000}}, + {F, {"mipi_csi_enable", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"Reserved_2", 2, 1, 0x0}}, + {F, {"mipi_data_lane1", 3, 1, 0x1}}, + {F, {"mipi_data_lane2", 4, 1, 0x1}}, + {F, {"mipi_packet_timeout_enable", 5, 1, 0x0}}, + {F, {"line_blanking_clk_disable", 6, 1, 0x1}}, + {F, {"Reserved_7", 7, 1, 0x0}}, + {F, {"line_blanking_en", 8, 1, 0x1}}, + {F, {"frame_blanking_en", 9, 1, 0x0}}, + {F, {"Reserved_31_10", 10, 22, 0x0}}, + + {R, {"SENSOR_IF/IMX636/mipi_csi/mipi_packet_size", 0x10B020}}, + {F, {"mipi_packet_size", 0, 15, 0x2000}}, + + {R, {"SENSOR_IF/IMX636/mipi_csi/mipi_packet_timeout", 0x10B024}}, + {F, {"mipi_packet_timeout", 0, 16, 0x40}}, + + {R, {"SENSOR_IF/IMX636/mipi_csi/mipi_frame_period", 0x10B028}}, + {F, {"mipi_frame_period", 4, 12, 0x7D}}, + + {R, {"SENSOR_IF/IMX636/mipi_csi/mipi_line_blanking", 0x10B02C}}, + {F, {"mipi_line_blanking", 0, 8, 0xA}}, + + {R, {"SENSOR_IF/IMX636/mipi_csi/mipi_frame_blanking", 0x10B030}}, + {F, {"mipi_frame_blanking", 0, 16, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/pipeline_control", 0x10C000}}, + {F, {"Reserved_0", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"afk_bypass", 2, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/param", 0x10C004}}, + {F, {"counter_low", 0, 3, 0x4}}, + {F, {"counter_high", 3, 3, 0x6}}, + {F, {"invert", 6, 1, 0x0}}, + {F, {"drop_disable", 7, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/filter_period", 0x10C008}}, + {F, {"min_cutoff_period", 0, 8, 0xF}}, + {F, {"max_cutoff_period", 8, 8, 0x9C}}, + {F, {"inverted_duty_cycle", 16, 4, 0x8}}, + + {R, {"SENSOR_IF/IMX636/afk/invalidation", 0x10C0C0}}, + {F, {"dt_fifo_wait_time", 0, 12, 0x5A0}}, + {F, {"Reserved_23_12", 12, 12, 0x5A}}, + {F, {"Reserved_27_24", 24, 4, 0xA}}, + {F, {"Reserved_28", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/initialization", 0x10C0C4}}, + {F, {"afk_req_init", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"afk_flag_init_done", 2, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/shadow_ctrl", 0x10C0D4}}, + {F, {"timer_en", 0, 1, 0x0}}, + {F, {"Reserved_31_1", 1, 31, 0x2}}, + + {R, {"SENSOR_IF/IMX636/afk/shadow_timer_threshold", 0x10C0D8}}, + {F, {"timer_threshold", 0, 32, 0x3E8}}, + + {R, {"SENSOR_IF/IMX636/afk/shadow_status", 0x10C0DC}}, + {F, {"shadow_valid", 0, 1, 0x0}}, + {F, {"shadow_overrun", 1, 1, 0x0}}, + {F, {"Reserved_31_2", 2, 30, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/total_evt_count", 0x10C0E0}}, + {F, {"total_evt_count", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/flicker_evt_count", 0x10C0E4}}, + {F, {"flicker_evt_count", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/afk/vector_evt_count", 0x10C0E8}}, + {F, {"vector_evt_count", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/pipeline_control", 0x10D000}}, + {F, {"Reserved_0", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"stc_trail_bypass", 2, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/stc_param", 0x10D004}}, + {F, {"stc_enable", 0, 1, 0x0}}, + {F, {"stc_threshold", 1, 19, 0x2710}}, + {F, {"disable_stc_cut_trail", 24, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/trail_param", 0x10D008}}, + {F, {"trail_enable", 0, 1, 0x0}}, + {F, {"trail_threshold", 1, 19, 0x186A0}}, + + {R, {"SENSOR_IF/IMX636/stc/timestamping", 0x10D00C}}, + {F, {"prescaler", 0, 5, 0xD}}, + {F, {"multiplier", 5, 4, 0x1}}, + {F, {"Reserved_9", 9, 1, 0x1}}, + {F, {"enable_last_ts_update_at_every_event", 16, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/invalidation", 0x10D0C0}}, + {F, {"dt_fifo_wait_time", 0, 12, 0x4}}, + {F, {"dt_fifo_timeout", 12, 12, 0x118}}, + {F, {"Reserved_27_24", 24, 4, 0xA}}, + {F, {"Reserved_28", 28, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/initialization", 0x10D0C4}}, + {F, {"stc_req_init", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"stc_flag_init_done", 2, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/shadow_ctrl", 0x10D0D4}}, + {F, {"timer_en", 0, 1, 0x0}}, + {F, {"Reserved_31_1", 1, 31, 0x2}}, + + {R, {"SENSOR_IF/IMX636/stc/shadow_timer_threshold", 0x10D0D8}}, + {F, {"timer_threshold", 0, 32, 0x3E8}}, + + {R, {"SENSOR_IF/IMX636/stc/shadow_status", 0x10D0DC}}, + {F, {"shadow_valid", 0, 1, 0x0}}, + {F, {"shadow_overrun", 1, 1, 0x0}}, + {F, {"Reserved_31_2", 2, 30, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/total_evt_count", 0x10D0E0}}, + {F, {"total_evt_count", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/stc_evt_count", 0x10D0E4}}, + {F, {"stc_evt_count", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/stc/trail_evt_count", 0x10D0E8}}, + {F, {"trail_evt_count", 0, 32, 0x0}}, + + {R, {"IMX636/stc/output_vector_count", 0x10D0EC}}, + {F, {"output_vector_count", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/IMX636/slvs/slvs_control", 0x10E000}}, + {F, {"slvs_llp_enable", 0, 1, 0x0}}, + {F, {"Reserved_1", 1, 1, 0x0}}, + {F, {"Reserved_2", 2, 1, 0x1}}, + {F, {"slvs_packet_timeout_enable", 5, 1, 0x0}}, + {F, {"slvs_line_blanking_en", 8, 1, 0x1}}, + {F, {"slvs_frame_blanking_en", 9, 1, 0x0}}, + + {R, {"SENSOR_IF/IMX636/slvs/slvs_packet_size", 0x10E020}}, + {F, {"slvs_packet_size", 0, 14, 0x1000}}, + + {R, {"SENSOR_IF/IMX636/slvs/slvs_packet_timeout", 0x10E024}}, + {F, {"slvs_packet_timeout", 0, 16, 0x40}}, + + {R, {"SENSOR_IF/IMX636/slvs/slvs_line_blanking", 0x10E02C}}, + {F, {"slvs_line_blanking", 0, 8, 0xA}}, + + {R, {"SENSOR_IF/IMX636/slvs/slvs_frame_blanking", 0x10E030}}, + {F, {"slvs_frame_blanking", 0, 16, 0x0}}, + + {R, {"SENSOR_IF/IMX636/slvs/slvs_phy_logic_ctrl_00", 0x10E150}}, + {F, {"oportsel", 0, 2, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/CORE_CONFIG", 0x700000}}, + {F, {"CORE_ENABLE", 0, 1, 0x1}}, + {F, {"SOFT_RESET", 1, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/PROTOCOL_CONFIG", 0x700004}}, + {F, {"ACTIVE_LANES", 0, 2, 0x1}}, + {F, {"MAX_LANES", 3, 2, 0x1}}, + + {R, {"SENSOR_IF/MIPI_RX/CORE_STAT", 0x700010}}, + {F, {"SOFT_RESET", 0, 1, 0x0}}, + {F, {"STREAM_LINE_BUFFER_FULL", 1, 1, 0x0}}, + {F, {"SHORT_PACKET_FIFO_NOT_EMPTY", 2, 1, 0x0}}, + {F, {"SHORT_PACKET_FIFO_FULL", 3, 1, 0x0}}, + {F, {"PACKET_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/GLOBAL_IRQ_ENABLE", 0x700020}}, + {F, {"", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/IRQ_STAT", 0x700024}}, + {F, {"VC0_ERR_FRAME_DATA", 0, 1, 0x0}}, + {F, {"VC0_ERR_FRAME_SYNC", 1, 1, 0x0}}, + {F, {"VC1_ERR_FRAME_DATA", 2, 1, 0x0}}, + {F, {"VC1_ERR_FRAME_SYNC", 3, 1, 0x0}}, + {F, {"VC2_ERR_FRAME_DATA", 4, 1, 0x0}}, + {F, {"VC2_ERR_FRAME_SYNC", 5, 1, 0x0}}, + {F, {"VC3_ERR_FRAME_DATA", 6, 1, 0x0}}, + {F, {"VC3_ERR_FRAME_SYNC", 7, 1, 0x0}}, + {F, {"ERR_ID", 8, 1, 0x0}}, + {F, {"ERR_CRC", 9, 1, 0x0}}, + {F, {"ERR_ECC_CORRECTED", 10, 1, 0x0}}, + {F, {"ERR_ECC_DOUBLE", 11, 1, 0x0}}, + {F, {"ERR_SOT_SYNC_HS", 12, 1, 0x0}}, + {F, {"ERR_SOT_HS", 13, 1, 0x0}}, + {F, {"STOP_STATE", 17, 1, 0x0}}, + {F, {"ST_LINE_BUF_FULL", 18, 1, 0x0}}, + {F, {"SHT_PKT_FIFO_N_EMPTY", 19, 1, 0x0}}, + {F, {"SHT_PKT_FIFO_FULL", 20, 1, 0x0}}, + {F, {"LANE_CONFIG_ERR", 21, 1, 0x0}}, + {F, {"WC_CORRUPTION", 22, 1, 0x0}}, + {F, {"RX_SKEWCALHS", 29, 1, 0x0}}, + {F, {"VCX FRAME ERROR", 30, 1, 0x0}}, + {F, {"FRAME_RECEIVED", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/IRQ_ENABLE", 0x700028}}, + {F, {"VC0_ERR_FRAME_DATA", 0, 1, 0x0}}, + {F, {"VC0_ERR_FRAME_SYNC", 1, 1, 0x0}}, + {F, {"VC1_ERR_FRAME_DATA", 2, 1, 0x0}}, + {F, {"VC1_ERR_FRAME_SYNC", 3, 1, 0x0}}, + {F, {"VC2_ERR_FRAME_DATA", 4, 1, 0x0}}, + {F, {"VC2_ERR_FRAME_SYNC", 5, 1, 0x0}}, + {F, {"VC3_ERR_FRAME_DATA", 6, 1, 0x0}}, + {F, {"VC3_ERR_FRAME_SYNC", 7, 1, 0x0}}, + {F, {"ERR_ID", 8, 1, 0x0}}, + {F, {"ERR_CRC", 9, 1, 0x0}}, + {F, {"ERR_ECC_CORRECTED", 10, 1, 0x0}}, + {F, {"ERR_ECC_DOUBLE", 11, 1, 0x0}}, + {F, {"ERR_SOT_SYNC_HS", 12, 1, 0x0}}, + {F, {"ERR_SOT_HS", 13, 1, 0x0}}, + {F, {"STOP_STATE", 17, 1, 0x0}}, + {F, {"ST_LINE_BUF_FULL", 18, 1, 0x0}}, + {F, {"SHT_PKT_FIFO_N_EMPTY", 19, 1, 0x0}}, + {F, {"SHT_PKT_FIFO_FULL", 20, 1, 0x0}}, + {F, {"LANE_CONFIG_ERR", 21, 1, 0x0}}, + {F, {"WC_CORRUPTION", 22, 1, 0x0}}, + {F, {"RX_SKEWCALHS", 29, 1, 0x0}}, + {F, {"FRAME_RECEIVED", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/GENERIC_SHT_PKT", 0x700030}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + {F, {"VIRTUAL_CHANNEL", 6, 2, 0x0}}, + {F, {"DATA", 8, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VCX_FRAME_ERROR", 0x700034}}, + {F, {"FRAME_LEVEL_ERR_VC4", 0, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC4", 1, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC5", 2, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC5", 3, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC6", 4, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC6", 5, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC7", 6, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC7", 7, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC8", 8, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC8", 9, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC9", 10, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC9", 11, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC10", 12, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC10", 13, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC11", 14, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC11", 15, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC12", 16, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC12", 17, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC13", 18, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC13", 19, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC14", 20, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC14", 21, 1, 0x0}}, + {F, {"FRAME_LEVEL_ERR_VC15", 22, 1, 0x0}}, + {F, {"FRAME_SYNC_ERR_VC15", 23, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/CLK_LANE_INFO", 0x70003C}}, + {F, {"RESERVED", 0, 1, 0x0}}, + {F, {"STOP_STATE", 1, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE0_INFO", 0x700040}}, + {F, {"SOT_SYNC_ERR", 0, 1, 0x0}}, + {F, {"SOT_ERR", 1, 1, 0x0}}, + {F, {"STOP_STATE", 5, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE1_INFO", 0x700044}}, + {F, {"SOT_SYNC_ERR", 0, 1, 0x0}}, + {F, {"SOT_ERR", 1, 1, 0x0}}, + {F, {"STOP_STATE", 5, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE2_INFO", 0x700048}}, + {F, {"SOT_SYNC_ERR", 0, 1, 0x0}}, + {F, {"SOT_ERR", 1, 1, 0x0}}, + {F, {"STOP_STATE", 5, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE3_INFO", 0x70004C}}, + {F, {"SOT_SYNC_ERR", 0, 1, 0x0}}, + {F, {"SOT_ERR", 1, 1, 0x0}}, + {F, {"STOP_STATE", 5, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC0_IMAGE_INFO_1", 0x700060}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC0_IMAGE_INFO_2", 0x700064}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC1_IMAGE_INFO_1", 0x700068}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC1_IMAGE_INFO_2", 0x70006C}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC2_IMAGE_INFO_1", 0x700070}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC2_IMAGE_INFO_2", 0x700074}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC3_IMAGE_INFO_1", 0x700078}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC3_IMAGE_INFO_2", 0x70007C}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC4_IMAGE_INFO_1", 0x700080}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC4_IMAGE_INFO_2", 0x700084}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC5_IMAGE_INFO_1", 0x700088}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC5_IMAGE_INFO_2", 0x70008C}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC6_IMAGE_INFO_1", 0x700090}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC6_IMAGE_INFO_2", 0x700094}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC7_IMAGE_INFO_1", 0x700098}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC7_IMAGE_INFO_2", 0x70009C}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC8_IMAGE_INFO_1", 0x7000A0}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC8_IMAGE_INFO_2", 0x7000A4}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC9_IMAGE_INFO_1", 0x7000A8}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC9_IMAGE_INFO_2", 0x7000AC}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC10_IMAGE_INFO_1", 0x7000B0}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC10_IMAGE_INFO_2", 0x7000B4}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC11_IMAGE_INFO_1", 0x7000B8}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC11_IMAGE_INFO_2", 0x7000BC}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC12_IMAGE_INFO_1", 0x7000C0}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC12_IMAGE_INFO_2", 0x7000C4}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC13_IMAGE_INFO_1", 0x7000C8}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC13_IMAGE_INFO_2", 0x7000CC}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC14_IMAGE_INFO_1", 0x7000D0}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC14_IMAGE_INFO_2", 0x7000D4}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC15_IMAGE_INFO_1", 0x7000D8}}, + {F, {"BYTE_COUNT", 0, 16, 0x0}}, + {F, {"LINE_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/VC15_IMAGE_INFO_2", 0x7000DC}}, + {F, {"DATA_TYPE", 0, 6, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/CONTROL", 0x708000}}, + {F, {"SRST", 0, 1, 0x0}}, + {F, {"DPHY_EN", 1, 1, 0x1}}, + + {R, {"SENSOR_IF/MIPI_RX/IDELAY_TAP_VALUE", 0x708004}}, + {F, {"LANE_0", 0, 5, 0x0}}, + {F, {"LANE_1", 8, 5, 0x0}}, + {F, {"LANE_2", 16, 5, 0x0}}, + {F, {"LANE_3", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/INIT", 0x708008}}, + {F, {"INIT_VAL", 0, 32, 0x186A0}}, + + {R, {"SENSOR_IF/MIPI_RX/HS_TIMEOUT", 0x708010}}, + {F, {"RX_VALUE", 0, 32, 0x10005}}, + + {R, {"SENSOR_IF/MIPI_RX/ESC_TIMEOUT", 0x708014}}, + {F, {"VALUE", 0, 32, 0x6400}}, + + {R, {"SENSOR_IF/MIPI_RX/CL_STATUS", 0x708018}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"STOP_STATE", 4, 1, 0x0}}, + {F, {"ERR_CONTROL", 5, 1, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE0_STATUS", 0x70801C}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE1_STATUS", 0x708020}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE2_STATUS", 0x708024}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE3_STATUS", 0x708028}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE0_HS_SETTLE", 0x708030}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x8D}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE1_HS_SETTLE", 0x708048}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x8D}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE2_HS_SETTLE", 0x70804C}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x8D}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE3_HS_SETTLE", 0x708050}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x8D}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE4_HS_SETTLE", 0x708054}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE5_HS_SETTLE", 0x708058}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE6_HS_SETTLE", 0x70805C}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE7_HS_SETTLE", 0x708060}}, + {F, {"HS_SETTLE_NS", 0, 9, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE4_STATUS", 0x708064}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE5_STATUS", 0x708068}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE6_STATUS", 0x70806C}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/LANE7_STATUS", 0x708070}}, + {F, {"MODE", 0, 2, 0x0}}, + {F, {"ULPS", 2, 1, 0x0}}, + {F, {"INIT_DONE", 3, 1, 0x0}}, + {F, {"HS_ABORT", 4, 1, 0x0}}, + {F, {"ESC_ABORT", 5, 1, 0x0}}, + {F, {"STOP_STATE", 6, 1, 0x0}}, + {F, {"PKT_CNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/MIPI_RX/IDELAY_TAP_VALUE_L4_TO_L7", 0x708074}}, + {F, {"LANE_4", 0, 5, 0x0}}, + {F, {"LANE_5", 8, 5, 0x0}}, + {F, {"LANE_6", 16, 5, 0x0}}, + {F, {"LANE_7", 24, 5, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/CONTROL", 0x70F000}}, + {F, {"ENABLE", 0, 1, 0x0}}, + {F, {"BYPASS", 1, 1, 0x0}}, + {F, {"LAST_CTRL_MODE", 11, 1, 0x0}}, + {F, {"HALF_WORD_SWAP", 12, 1, 0x0}}, + {F, {"AUX_PRESENCE", 16, 1, 0x0}}, + {F, {"MIPI_RX_PRESENCE", 17, 1, 0x0}}, + {F, {"SLVS_RX_PRESENCE", 18, 1, 0x0}}, + {F, {"TD_POL_INV", 20, 1, 0x0}}, + {F, {"EM_POL_INV", 21, 1, 0x0}}, + {F, {"GEN_LAST", 22, 1, 0x0}}, + {F, {"AUX_IN_MODE", 24, 1, 0x0}}, + {F, {"AUX_8BN_4B", 25, 1, 0x0}}, + {F, {"SLVS_IN_MODE", 26, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/TRIGGER", 0x70F004}}, + {F, {"AFIFO_RESET", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/TEST_PATTERN_CONTROL", 0x70F008}}, + {F, {"EVT_TYPE", 0, 4, 0x0}}, + {F, {"EVT_FORMAT", 4, 2, 0x2}}, + {A, {"2.0", 0x2}}, + {A, {"3.0", 0x3}}, + {F, {"ENABLE", 8, 1, 0x0}}, + {F, {"VECTOR_MODE", 9, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/TEST_PATTERN_N_PERIOD", 0x70F00C}}, + {F, {"VALID_RATIO", 0, 10, 0x0}}, + {F, {"LENGTH", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/TEST_PATTERN_P_PERIOD", 0x70F010}}, + {F, {"VALID_RATIO", 0, 10, 0x0}}, + {F, {"LENGTH", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/TEST_PATTERN_VECTOR", 0x70F014}}, + {F, {"SEED_VALUE", 0, 5, 0x1F}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/OOB_FILTER_CONTROL", 0x70F018}}, + {F, {"ENABLE", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/OOB_FILTER_ORIGIN", 0x70F01C}}, + {F, {"Y", 0, 11, 0x0}}, + {F, {"X", 16, 11, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/OOB_FILTER_SIZE", 0x70F020}}, + {F, {"HEIGHT", 0, 11, 0x2CF}}, + {F, {"WIDTH", 16, 11, 0x4FF}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/CCAM5_CONTROL", 0x70F024}}, + {F, {"PSU_EN", 0, 1, 0x0}}, + {F, {"RST_N", 1, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/TRIGGER_FWD", 0x70F028}}, + {F, {"TRIGGER_ID", 0, 8, 0x0}}, + {F, {"ENABLE", 8, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/MIPI_RX_CONTROL", 0x70F02C}}, + {F, {"VIDEO_RESET", 0, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/GEN41_CTRL", 0x70F030}}, + {F, {"BOOT", 0, 1, 0x0}}, + {F, {"DFT_MODE", 1, 1, 0x0}}, + {F, {"TEST_MODE", 2, 1, 0x0}}, + {F, {"I2C_ADDR", 3, 1, 0x0}}, + {F, {"CPU_DEBUG", 4, 1, 0x0}}, + {F, {"AGPIO", 5, 2, 0x0}}, + {F, {"DGPIO", 7, 1, 0x0}}, + {F, {"ARST_N", 8, 1, 0x0}}, + {F, {"TDRST_N", 9, 1, 0x0}}, + {F, {"XCLEAR", 10, 1, 0x0}}, + {F, {"I2C_SPI_SEL", 11, 1, 0x0}}, + {F, {"TRIG_IO_DIR", 12, 1, 0x0}}, + {F, {"DGPIO_DIR", 13, 1, 0x0}}, + {F, {"DGPIO_VAL", 14, 1, 0x0}}, + {F, {"OMODE_BUF", 15, 1, 0x0}}, + {F, {"CPUSTAIT_BUF", 16, 1, 0x0}}, + {F, {"TPA_SEL_1V", 17, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/GEN41_POWER_CTRL", 0x70F034}}, + {F, {"1V8_SYS", 0, 1, 0x0}}, + {F, {"3V3_SYS", 1, 1, 0x0}}, + {F, {"VDDLSC", 2, 1, 0x0}}, + {F, {"VDDPLL", 3, 1, 0x0}}, + {F, {"VDDLIF", 4, 1, 0x0}}, + {F, {"VDDMIF", 5, 1, 0x0}}, + {F, {"VDDIO", 6, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_IF_CTRL/GEN41_CLK_CTRL", 0x70F038}}, + {F, {"ENABLE", 0, 1, 0x0}}, + {F, {"VALID", 1, 1, 0x0}}, + {F, {"VCO_HIGH_TIME", 10, 6, 0x0}}, + {F, {"VCO_LOW_TIME", 20, 6, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/IODELAY_DEC", 0x710004}}, + {F, {"DATA", 0, 8, 0x0}}, + {F, {"VALID", 8, 1, 0x0}}, + {F, {"CLK", 9, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/IODELAY_INC", 0x710008}}, + {F, {"DATA", 0, 8, 0x0}}, + {F, {"VALID", 8, 1, 0x0}}, + {F, {"CLK", 9, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/IODELAY_LOAD", 0x71000C}}, + {F, {"DATA", 0, 8, 0x0}}, + {F, {"VALID", 8, 1, 0x0}}, + {F, {"CLK", 9, 1, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/IODELAY_SET_VALUE_0", 0x710010}}, + {F, {"DATA_0", 0, 5, 0x0}}, + {F, {"DATA_1", 5, 5, 0x0}}, + {F, {"DATA_2", 10, 5, 0x0}}, + {F, {"DATA_3", 15, 5, 0x0}}, + {F, {"DATA_4", 20, 5, 0x0}}, + {F, {"DATA_5", 25, 5, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/IODELAY_SET_VALUE_1", 0x710014}}, + {F, {"DATA_6", 0, 5, 0x0}}, + {F, {"DATA_7", 5, 5, 0x0}}, + {F, {"VALID", 10, 5, 0x0}}, + {F, {"CLK", 15, 5, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/IODELAY_GET_VALUE_0", 0x710018}}, + {F, {"DATA_0", 0, 5, 0x0}}, + {F, {"DATA_1", 5, 5, 0x0}}, + {F, {"DATA_2", 10, 5, 0x0}}, + {F, {"DATA_3", 15, 5, 0x0}}, + {F, {"DATA_4", 20, 5, 0x0}}, + {F, {"DATA_5", 25, 5, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/IODELAY_GET_VALUE_1", 0x71001C}}, + {F, {"DATA_6", 0, 5, 0x0}}, + {F, {"DATA_7", 5, 5, 0x0}}, + {F, {"VALID", 10, 5, 0x0}}, + {F, {"CLK", 15, 5, 0x0}}, + + {R, {"SENSOR_IF/GEN41_AUX_IF/SAMPLE_CLK_EDGE", 0x710020}}, + {F, {"DATA", 0, 8, 0x0}}, + {F, {"VALID", 8, 1, 0x0}}, + + {R, {"SENSOR_IF/VIP/CONTROL", 0x710100}}, + {F, {"MODE", 0, 3, 0x0}}, + {F, {"RATE", 3, 10, 0x0}}, + {F, {"REPEAT", 16, 13, 0x0}}, + {F, {"DISABLE_OUTPUT", 29, 1, 0x0}}, + {F, {"FORCE_READY", 30, 1, 0x1}}, + + {R, {"SENSOR_IF/VIP/TEST_STATUS", 0x710104}}, + {F, {"STATUS", 0, 1, 0x0}}, + {F, {"RESET", 1, 1, 0x0}}, + + {R, {"SENSOR_IF/VIP/PATTERN_TEST_DATA", 0x710108}}, + {F, {"DATA", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/VIP/TEST_RESULT", 0x71010C}}, + {F, {"RESULT", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/VIP/VALID_COUNTER", 0x710110}}, + {F, {"COUNTER", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/VIP/ERROR_COUNTER", 0x710114}}, + {F, {"COUNTER", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/VIP/ERROR_INDEX", 0x710118}}, + {F, {"INDEX", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/CORE_CONFIG", 0x710200}}, + {F, {"CORE_ENABLE", 0, 1, 0x0}}, + {F, {"DATA_FORMAT", 1, 2, 0x3}}, + + {R, {"SENSOR_IF/SLVS_RX/PROTOCOL_CONFIG", 0x710204}}, + {F, {"ACTIVE_LANES", 0, 2, 0x3}}, + {F, {"EN_IN_BYTE_ENDIANNESS_SWAP", 4, 1, 0x0}}, + {F, {"EN_PLD_BYTE_ORDER_SWAP", 8, 1, 0x0}}, + {F, {"EN_PLD_BYTE_ENDIANNESS_SWAP", 12, 1, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/CORE_STAT", 0x710208}}, + {F, {"SOFT_RESET", 0, 1, 0x0}}, + {F, {"OUT_BUFFER_FULL", 1, 1, 0x0}}, + {F, {"PHASE_DETECT_LOCKED", 4, 4, 0x0}}, + {F, {"ACCU_REG_LOCKED", 8, 4, 0x0}}, + {F, {"PACKET_COUNT", 16, 16, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC1_CODE_MSB", 0x71020C}}, + {F, {"VALUE", 0, 32, 0xDB0DB1DB}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC1_CODE_LSB", 0x710210}}, + {F, {"VALUE", 0, 32, 0x2DB3DB4D}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC2_CODE_MSB", 0x710214}}, + {F, {"VALUE", 0, 32, 0xB5DB6DB7}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC2_CODE_LSB", 0x710218}}, + {F, {"VALUE", 0, 32, 0xDB8DB9DB}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC3_CODE_MSB", 0x71021C}}, + {F, {"VALUE", 0, 32, 0xADBBDBCD}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC3_CODE_LSB", 0x710220}}, + {F, {"VALUE", 0, 32, 0xBDDBEDBF}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_FS_CODE_MSB", 0x710224}}, + {F, {"VALUE", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_FS_CODE_LSB", 0x710228}}, + {F, {"VALUE", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_FE_CODE_MSB", 0x71022C}}, + {F, {"VALUE", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_FE_CODE_LSB", 0x710230}}, + {F, {"VALUE", 0, 32, 0x4000}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_SAV_CODE_MSB", 0x710234}}, + {F, {"VALUE", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_SAV_CODE_LSB", 0x710238}}, + {F, {"VALUE", 0, 32, 0x8000}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_EAV_CODE_MSB", 0x71023C}}, + {F, {"VALUE", 0, 32, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/SYNC4_EAV_CODE_LSB", 0x710240}}, + {F, {"VALUE", 0, 32, 0xC000}}, + + {R, {"SENSOR_IF/SLVS_RX/BLK_CODE_MSB", 0x710244}}, + {F, {"VALUE", 0, 32, 0xB0B1B2B3}}, + + {R, {"SENSOR_IF/SLVS_RX/BLK_CODE_LSB", 0x710248}}, + {F, {"VALUE", 0, 32, 0xB4B5B6B7}}, + + {R, {"SENSOR_IF/SLVS_RX/DMY_CODE_MSB", 0x71024C}}, + {F, {"VALUE", 0, 32, 0x99999999}}, + + {R, {"SENSOR_IF/SLVS_RX/DMY_CODE_LSB", 0x710250}}, + {F, {"VALUE", 0, 32, 0x99999999}}, + + {R, {"SENSOR_IF/SLVS_RX/IODELAY_LOAD", 0x710254}}, + {F, {"LANE_0", 0, 1, 0x0}}, + {F, {"LANE_1", 8, 1, 0x0}}, + {F, {"LANE_2", 16, 1, 0x0}}, + {F, {"LANE_3", 24, 1, 0x0}}, + {F, {"BUSY", 31, 1, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/IODELAY_SET_VALUE_0", 0x710258}}, + {F, {"LANE_0", 0, 9, 0x0}}, + {F, {"LANE_1", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/IODELAY_SET_VALUE_1", 0x71025C}}, + {F, {"LANE_2", 0, 9, 0x0}}, + {F, {"LANE_3", 16, 9, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/STAT_IODELAY_SET_VALUE_0", 0x710260}}, + {F, {"LANE_0", 0, 9, 0x0}}, + {F, {"LANE_1", 18, 9, 0x0}}, + + {R, {"SENSOR_IF/SLVS_RX/STAT_IODELAY_SET_VALUE_1", 0x710264}}, + {F, {"LANE_2", 0, 9, 0x0}}, + {F, {"LANE_3", 18, 9, 0x0}} + + // clang-format on +}; + +static uint32_t Imx636Evk2EspRegisterMapSize = sizeof(Imx636Evk2EspRegisterMap) / sizeof(Imx636Evk2EspRegisterMap[0]); + +#endif // METAVISION_HAL_IMX636_EVK2_ESP_REGISTERMAP_H diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/error_category.h b/hal_psee_plugins/include/devices/imx8/imx8_tz_device.h similarity index 57% rename from sdk/modules/base/cpp/include/metavision/sdk/base/utils/error_category.h rename to hal_psee_plugins/include/devices/imx8/imx8_tz_device.h index 4bfbf6039..65ace0085 100644 --- a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/error_category.h +++ b/hal_psee_plugins/include/devices/imx8/imx8_tz_device.h @@ -9,31 +9,31 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_BASE_ERROR_CATEGORY_H -#define METAVISION_SDK_BASE_ERROR_CATEGORY_H +#ifndef METAVISION_HAL_PSEE_PLUGINS_DEVICES_IMX8_TZ_DEVICE_H +#define METAVISION_HAL_PSEE_PLUGINS_DEVICES_IMX8_TZ_DEVICE_H -#include -#include +#include + +#include "devices/treuzell/tz_unknown.h" +#include "metavision/psee_hw_layer/devices/treuzell/tz_main_device.h" namespace Metavision { -struct [[deprecated("'ErrorCategory' struct is deprecated since v4.6.0 and will be removed in future releases, " - "please use derive exceptions from 'BaseException' and provide adapted singleton error category" - " instead.")]] ErrorCategory : public std::error_category { - ErrorCategory() = delete; - ErrorCategory(const ErrorCategory &) = delete; - ErrorCategory(int error_code, const std::string &name = "", const std::string &message = ""); - virtual ~ErrorCategory(); +class TzImx8Device : public TzMainDevice, public TzUnknownDevice { +public: + TzImx8Device(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent); - const char *name() const noexcept override; - std::string message(int ev) const override; + // TzMainDevice + bool set_mode_standalone() override; + bool set_mode_master() override; + bool set_mode_slave() override; + I_CameraSynchronization::SyncMode get_mode() const override; + I_HW_Identification::SensorInfo get_sensor_info() override; -private: - std::string name_, error_message_; + static std::shared_ptr build(std::shared_ptr cmd, uint32_t id, + std::shared_ptr parent); }; } // namespace Metavision -#include "detail/error_category_impl.h" - -#endif // METAVISION_SDK_BASE_ERROR_CATEGORY_H +#endif // METAVISION_HAL_PSEE_PLUGINS_DEVICES_IMX8_TZ_DEVICE_H diff --git a/hal_psee_plugins/include/devices/treuzell/tz_device_builder.h b/hal_psee_plugins/include/devices/treuzell/tz_device_builder.h index 1d527f4ae..a7fa2f6b1 100644 --- a/hal_psee_plugins/include/devices/treuzell/tz_device_builder.h +++ b/hal_psee_plugins/include/devices/treuzell/tz_device_builder.h @@ -12,9 +12,6 @@ #ifndef TZ_DEVICE_BUILDER_H #define TZ_DEVICE_BUILDER_H -#include "metavision/hal/utils/device_config.h" -#include "metavision/hal/utils/device_builder.h" - #include #include #include @@ -39,6 +36,9 @@ class TzDeviceBuilder { void set(std::string key, Build_Fun method, Check_Fun buildable = nullptr) { map[key] = {method, buildable}; } + void clear() { + map.clear(); + } bool can_build(std::shared_ptr); bool can_build_device(std::shared_ptr, uint32_t dev_id); /****************************************************************************************************************** diff --git a/hal_psee_plugins/include/devices/utils/device_system_id.h b/hal_psee_plugins/include/devices/utils/device_system_id.h index fbdedcfb5..2099bc61f 100644 --- a/hal_psee_plugins/include/devices/utils/device_system_id.h +++ b/hal_psee_plugins/include/devices/utils/device_system_id.h @@ -62,6 +62,7 @@ enum SystemId : long { SYSTEM_EVK3_GENX320_MP = 0x3B, SYSTEM_EVK3_GENX320 = 0x40, SYSTEM_EVK3D_SL = 0x41, + SYSTEM_EVK2_IMX636_ESP = 0x42, SYSTEM_FX3_UNKNOWN = static_cast(0xFFFFFFF0), SYSTEM_INVALID_NO_FPGA = static_cast(0xFFFFFFFF) }; diff --git a/hal_psee_plugins/include/utils/make_decoder.h b/hal_psee_plugins/include/utils/make_decoder.h index 358edc738..4866e652c 100644 --- a/hal_psee_plugins/include/utils/make_decoder.h +++ b/hal_psee_plugins/include/utils/make_decoder.h @@ -13,6 +13,7 @@ #define MAKE_DECODER_H #include +#include "metavision/hal/utils/device_config.h" namespace Metavision { @@ -27,7 +28,7 @@ class DeviceBuilder; * If the provided fromat is not handled, the function will throw. */ std::shared_ptr make_decoder(DeviceBuilder &, const StreamFormat &, size_t &raw_size_bytes, - bool do_time_shifting); + bool do_time_shifting, const Metavision::DeviceConfig &config = Metavision::DeviceConfig{}); } // namespace Metavision #endif /* MAKE_DECODER_H */ diff --git a/hal_psee_plugins/lib/CMakeLists.txt b/hal_psee_plugins/lib/CMakeLists.txt index b94ae2b8a..a525ab263 100644 --- a/hal_psee_plugins/lib/CMakeLists.txt +++ b/hal_psee_plugins/lib/CMakeLists.txt @@ -75,11 +75,14 @@ add_custom_command(TARGET metavision_psee_hw_layer POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${HAL_BUILD_PLUGIN_PATH}" COMMAND ${CMAKE_COMMAND} -E copy "$" "${HAL_BUILD_PLUGIN_PATH}") -if(HAL_SENSORLIB_SUPPORT) +if(BUILD_INTERNAL_PLUGINS) + add_custom_command(TARGET metavision_psee_hw_layer POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${HAL_BUILD_PLUGIN_PATH}/universal_internal" + COMMAND ${CMAKE_COMMAND} -E copy "$" "${HAL_BUILD_PLUGIN_PATH}/universal_internal") add_custom_command(TARGET metavision_psee_hw_layer POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${HAL_BUILD_PLUGIN_PATH}/sensorlib" COMMAND ${CMAKE_COMMAND} -E copy "$" "${HAL_BUILD_PLUGIN_PATH}/sensorlib") -endif(HAL_SENSORLIB_SUPPORT) +endif(BUILD_INTERNAL_PLUGINS) # Install public headers install(DIRECTORY ${metavision_psee_hw_layer_include_dir}/metavision @@ -127,7 +130,13 @@ install(FILES ${metavision_psee_hw_layer_config_file} ${metavision_psee_hw_layer COMPONENT metavision-hal-prophesee-hw-layer-dev ) -set(lib_obj_list ${lib_common_obj_list}) +if(BUILD_INTERNAL_PLUGINS) + set(lib_internal_obj_list + metavision_hal_psee_plugin_internal_obj + ) +endif(BUILD_INTERNAL_PLUGINS) + +set(lib_obj_list ${lib_common_obj_list} ${lib_internal_obj_list}) foreach(lib_obj ${lib_obj_list}) add_library(${lib_obj} OBJECT) @@ -152,6 +161,13 @@ foreach(lib_obj ${lib_obj_list}) ) endforeach() +foreach(lib_obj ${lib_internal_obj_list}) + target_include_directories(${lib_obj} + PUBLIC + $ + ) +endforeach() + # Custom target for all plugins (useful to use as a dependency) add_custom_target(hal_plugins) add_dependencies(hal_plugins metavision_psee_hw_layer) @@ -162,6 +178,14 @@ set(plugin_list hal_plugin_prophesee ) +if(BUILD_INTERNAL_PLUGINS) + list(APPEND plugin_list + hal_plugin_sensorlib_tz + hal_plugin_sensorlib_fx3 + hal_plugin_prophesee_internal + ) +endif(BUILD_INTERNAL_PLUGINS) + if(POLICY CMP0095) # Don't escape RPATH content cmake_policy(SET CMP0095 OLD) @@ -209,12 +233,20 @@ foreach(plugin ${plugin_list}) list(APPEND hal_psee_plugins_target_file_list $) - set(HAL_COPY_PLUGIN_PATH "${HAL_BUILD_PLUGIN_PATH}") - install(TARGETS ${plugin} - LIBRARY DESTINATION "${HAL_INSTALL_PLUGIN_RELATIVE_PATH}" COMPONENT metavision-hal-prophesee-plugins - RUNTIME DESTINATION "${HAL_INSTALL_PLUGIN_RELATIVE_PATH}" COMPONENT metavision-hal-prophesee-plugins - #ARCHIVE : we don't want to install .lib files for the plugins, it's useless - ) + if(plugin STREQUAL "hal_plugin_sensorlib_tz") + set(HAL_COPY_PLUGIN_PATH "${HAL_BUILD_PLUGIN_PATH}/sensorlib") + elseif(plugin STREQUAL "hal_plugin_sensorlib_fx3") + set(HAL_COPY_PLUGIN_PATH "${HAL_BUILD_PLUGIN_PATH}/sensorlib") + elseif(plugin STREQUAL "hal_plugin_prophesee_internal") + set(HAL_COPY_PLUGIN_PATH "${HAL_BUILD_PLUGIN_PATH}/universal_internal") + else() + set(HAL_COPY_PLUGIN_PATH "${HAL_BUILD_PLUGIN_PATH}") + install(TARGETS ${plugin} + LIBRARY DESTINATION "${HAL_INSTALL_PLUGIN_RELATIVE_PATH}" COMPONENT metavision-hal-prophesee-plugins + RUNTIME DESTINATION "${HAL_INSTALL_PLUGIN_RELATIVE_PATH}" COMPONENT metavision-hal-prophesee-plugins + #ARCHIVE : we don't want to install .lib files for the plugins, it's useless + ) + endif() # instead of setting the RUNTIME/LIBRARY_OUTPUT_DIRECTORY property on the target, we manually copy # the library : this will work for linux and windows and avoid the automatic copy of the DLLs the # plugin depends on by MSVC @@ -239,6 +271,35 @@ foreach(object ${lib_common_obj_list}) ) endforeach() +# Linkage with generic hal plugin object +if(BUILD_INTERNAL_PLUGINS) + set(internal_plugin_list hal_plugin_sensorlib_tz hal_plugin_sensorlib_fx3 hal_plugin_prophesee_internal) + + foreach(internal_plugin ${internal_plugin_list}) + foreach(object ${lib_obj_list}) + # Linkage with generic hal plugin object + target_sources(${internal_plugin} + PRIVATE + $ + ) + + target_link_libraries(${internal_plugin} + PRIVATE + ${object} + ) + endforeach() + endforeach() + + set(output_universal_internal_plugin_path "${GENERATE_FILES_DIRECTORY}/universal_internal_plugin_${PROJECT_VERSION_FULL}.tar") + add_custom_target(create_universal_internal_plugin_archive + COMMAND ${CMAKE_COMMAND} -E remove_directory "universal_internal_plugin" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${HAL_BUILD_PLUGIN_PATH}/universal_internal" "universal_internal_plugin" + COMMAND ${CMAKE_COMMAND} -E tar cvf ${output_universal_plugin_path} "universal_internal_plugin") + + add_dependencies(create_universal_internal_plugin_archive hal_plugin_prophesee_internal) + +endif(BUILD_INTERNAL_PLUGINS) + if(EXISTS "${PROJECT_SOURCE_DIR}/licensing/LICENSE_METAVISION_SDK") install(FILES ${PROJECT_SOURCE_DIR}/licensing/LICENSE_METAVISION_SDK DESTINATION share/metavision/licensing) diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/file_hw_identification.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/file_hw_identification.h index 8bf33792d..f6db1bbbc 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/file_hw_identification.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/file_hw_identification.h @@ -27,7 +27,6 @@ class FileHWIdentification : public I_HW_Identification { const PseeRawFileHeader &raw_header); std::string get_serial() const override final; - long get_system_id() const override final; std::vector get_available_data_encoding_formats() const override final; std::string get_current_data_encoding_format() const override final; std::string get_integrator() const override final; diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/psee_raw_file_header.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/psee_raw_file_header.h index f898e06f6..8e3a30c1e 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/psee_raw_file_header.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/rawfile/psee_raw_file_header.h @@ -35,9 +35,9 @@ class PseeRawFileHeader : public RawFileHeader { std::string get_serial() const; - long get_system_id() const; - // This isn't part of standard I_HW_Identification + void set_system_id(long system_id); + long get_system_id() const; void set_sub_system_id(long); long get_sub_system_id() const; @@ -48,7 +48,6 @@ class PseeRawFileHeader : public RawFileHeader { private: void check_header(); void set_serial(std::string); - void set_system_id(long system_id); void set_sensor_info(const I_HW_Identification::SensorInfo &); void set_system_version(long); void set_format(const StreamFormat &); diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/board_command.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/board_command.h index 62daa0532..63f32b6c8 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/board_command.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/board_command.h @@ -13,28 +13,30 @@ #define METAVISION_HAL_BOARD_COMMAND_H #include +#include #include #include -#include +#include + +#include "metavision/hal/utils/data_transfer.h" namespace Metavision { class TzCtrlFrame; -class DataTransfer; class BoardCommand { public: - virtual std::vector read_device_register(uint32_t device, uint32_t address, int nval = 1) = 0; - virtual void write_device_register(uint32_t device, uint32_t address, const std::vector &val) = 0; - virtual void transfer_tz_frame(TzCtrlFrame &req) = 0; - virtual uint32_t get_device_count() = 0; - virtual std::string get_name() = 0; - virtual std::string get_serial() = 0; - virtual std::unique_ptr build_data_transfer(uint32_t raw_event_size_bytes) = 0; - virtual long get_board_speed() = 0; - virtual std::string get_manufacturer() = 0; - virtual uint32_t get_version() = 0; - virtual time_t get_build_date() = 0; + virtual std::vector read_device_register(uint32_t device, uint32_t address, int nval = 1) = 0; + virtual void write_device_register(uint32_t device, uint32_t address, const std::vector &val) = 0; + virtual void transfer_tz_frame(TzCtrlFrame &req) = 0; + virtual uint32_t get_device_count() = 0; + virtual std::string get_name() = 0; + virtual std::string get_serial() = 0; + virtual std::unique_ptr build_raw_data_producer(uint32_t raw_event_size_bytes) = 0; + virtual long get_board_speed() = 0; + virtual std::string get_manufacturer() = 0; + virtual uint32_t get_version() = 0; + virtual time_t get_build_date() = 0; }; -} +} // namespace Metavision #endif // METAVISION_HAL_BOARD_COMMAND_H diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_hw_identification.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_hw_identification.h index 672b69089..5b8f65fce 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_hw_identification.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_hw_identification.h @@ -36,16 +36,6 @@ class TzHWIdentification : public I_HW_Identification { */ virtual std::string get_serial() const override; - /** - * Returns the serial number of the camera - * - * @return the system id as a integer - * - * @note this number can be used to check the compatibility - * of biases file for example - */ - virtual long get_system_id() const override; - /** * Returns the detail about the sensor available * diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h index b67c02308..77db6d8c8 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h @@ -9,19 +9,16 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ - #ifndef METAVISION_HAL_TZ_LIBUSB_BOARD_COMMAND_H #define METAVISION_HAL_TZ_LIBUSB_BOARD_COMMAND_H #include -#include #include #include #include -#include -#include #include +#include "metavision/hal/utils/data_transfer.h" #include "metavision/psee_hw_layer/boards/utils/psee_libusb.h" #include "metavision/psee_hw_layer/boards/treuzell/board_command.h" @@ -44,7 +41,7 @@ struct BoardQuirks { bool do_not_set_config; }; -class TzLibUSBBoardCommand: public virtual BoardCommand { +class TzLibUSBBoardCommand : public virtual BoardCommand { public: TzLibUSBBoardCommand() = delete; TzLibUSBBoardCommand(std::shared_ptr ctx, libusb_device *dev, libusb_device_descriptor &desc, @@ -69,7 +66,7 @@ class TzLibUSBBoardCommand: public virtual BoardCommand { void write_device_register(uint32_t device, uint32_t address, const std::vector &val) override; // @brief Create a new DataTransfer object to stream the currently opened device - std::unique_ptr build_data_transfer(uint32_t raw_event_size_bytes) override; + std::unique_ptr build_raw_data_producer(uint32_t raw_event_size_bytes) override; private: bool clear_endpoint(); diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h index 5746670b2..3b3a71cf7 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h @@ -12,31 +12,33 @@ #ifndef METAVISION_HAL_PSEE_LIBUSB_DATA_TRANSFER_H #define METAVISION_HAL_PSEE_LIBUSB_DATA_TRANSFER_H -#include #include -#include #include "metavision/psee_hw_layer/boards/utils/psee_libusb.h" #include "metavision/hal/utils/data_transfer.h" namespace Metavision { -class PseeLibUSBDataTransfer : public Metavision::DataTransfer { +class PseeLibUSBDataTransfer : public DataTransfer::RawDataProducer { using EpId = unsigned char; + using BufferPtr = DataTransfer::DefaultBufferPtr; + public: - static DataTransfer::BufferPool make_buffer_pool(size_t max_pool_byte_size = 0); + static DataTransfer::DefaultBufferPool make_buffer_pool(size_t max_pool_byte_size = 0); PseeLibUSBDataTransfer(const std::shared_ptr dev, EpId endpoint, uint32_t raw_event_size_bytes, - const DataTransfer::BufferPool &buffer_pool = make_buffer_pool()); + const DataTransfer::DefaultBufferPool &buffer_pool = make_buffer_pool()); ~PseeLibUSBDataTransfer() override; private: - void start_impl(BufferPtr buffer) override final; - void run_impl() override final; + void start_impl() override final; + void run_impl(const DataTransfer &data_transfer) override final; void stop_impl() override final; - void run_transfers(); + void run_transfers(const DataTransfer &data_transfer); + + DataTransfer::DefaultBufferPool buffer_pool_; std::shared_ptr dev_; EpId bEpCommAddress_; diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/v4l2/v4l2_board_command.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/v4l2/v4l2_board_command.h index feb97f6eb..7561b4cdb 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/v4l2/v4l2_board_command.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/boards/v4l2/v4l2_board_command.h @@ -50,17 +50,13 @@ class V4L2BoardCommand : public virtual BoardCommand { std::vector read_device_register(uint32_t device, uint32_t address, int nval = 1) override; void write_device_register(uint32_t device, uint32_t address, const std::vector &val) override; - // @brief Create a new DataTransfer object to stream the currently opened device - std::unique_ptr build_data_transfer(uint32_t raw_event_size_bytes) override; + // @brief Create a new RawDataProducer object to stream the currently opened device + std::unique_ptr build_raw_data_producer(uint32_t raw_event_size_bytes) override; + void transfer_tz_frame(TzCtrlFrame &req) override; std::shared_ptr get_device_control(); private: - /* bool clear_endpoint(); */ - /* bool reset_device(); */ - - // Board state - // dd std::shared_ptr device_; std::mutex tz_control_mutex_; std::string manufacturer; diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h index 36656015f..c6af83784 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen31/gen31_event_rate_noise_filter_module.h @@ -28,8 +28,6 @@ class Gen31_EventRateNoiseFilterModule : public I_EventRateActivityFilterModule bool enable(bool enable_filter) override; bool is_enabled() const override; - bool set_event_rate_threshold(uint32_t threshold_Kev_s) override; - uint32_t get_event_rate_threshold() const override; NflThresholds is_thresholds_supported() const override; bool set_thresholds(const NflThresholds &thresholds_ev_s) override; @@ -52,7 +50,6 @@ class Gen31_EventRateNoiseFilterModule : public I_EventRateActivityFilterModule std::shared_ptr i_hw_register_; const std::string base_name_; - mutable uint32_t current_threshold_kev_s_{0}; }; } // namespace Metavision diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_ll_biases.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_ll_biases.h index 8e7c8b16b..b997dd017 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_ll_biases.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/gen41/gen41_ll_biases.h @@ -23,6 +23,23 @@ class I_HW_Register; class Gen41_LL_Biases : public I_LL_Biases { public: + class Gen41LLBias : public LL_Bias_Info { + public: + Gen41LLBias(int min_recommended_value, int max_recommended_value, bool modifiable, std::string register_name, + const std::string &description, const std::string &category) : + LL_Bias_Info(0x00, 0xFF, min_recommended_value, max_recommended_value, description, modifiable, category) { + register_name_ = register_name; + } + + ~Gen41LLBias() {} + const std::string &get_register_name() const { + return register_name_; + } + + private: + std::string register_name_; + }; + Gen41_LL_Biases(const DeviceConfig &device_config, const std::shared_ptr &i_hw_register, const std::string &sensor_prefix); @@ -30,6 +47,8 @@ class Gen41_LL_Biases : public I_LL_Biases { protected: const std::shared_ptr &get_hw_register() const; + std::map &get_gen41_biases_map(); + const std::map &get_gen41_biases_map() const; private: virtual bool set_impl(const std::string &bias_name, int bias_value) override; @@ -38,6 +57,7 @@ class Gen41_LL_Biases : public I_LL_Biases { std::shared_ptr i_hw_register_; std::string base_name_; + std::map biases_map_; }; } // namespace Metavision diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h index 254b6650f..0cf57cfbd 100644 --- a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/genx320/genx320_nfl_interface.h @@ -29,16 +29,6 @@ class GenX320NflInterface : public I_EventRateActivityFilterModule { /// @return the noise filter state bool is_enabled() const; - /// @brief Sets the event rate threshold. Below this threshold, no events are streamed. - /// @param threshold_Kev_s Event rate threshold in Kevt/s - /// @return true if the input value was correctly set (i.e. it falls in the range of acceptable values for the - /// sensor) - bool set_event_rate_threshold(uint32_t threshold_Kev_s); - - /// @brief Gets the event rate threshold in Kevt/s below which no events are streamed - /// @return Event rate threshold in Kevt/s - uint32_t get_event_rate_threshold() const; - I_EventRateActivityFilterModule::thresholds is_thresholds_supported() const; bool set_thresholds(const I_EventRateActivityFilterModule::thresholds &thresholds_ev_s); I_EventRateActivityFilterModule::thresholds get_thresholds() const; diff --git a/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/imx636/imx636_evk2_esp.h b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/imx636/imx636_evk2_esp.h new file mode 100644 index 000000000..150d1927b --- /dev/null +++ b/hal_psee_plugins/psee_hw_layer_headers/include/metavision/psee_hw_layer/devices/imx636/imx636_evk2_esp.h @@ -0,0 +1,45 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_HAL_IMX636_EVK2_ESP_H +#define METAVISION_HAL_IMX636_EVK2_ESP_H + +#include +#include + +#include "metavision/hal/facilities/i_registrable_facility.h" + +namespace Metavision { + +class RegisterMap; +class PseeDeviceControl; +class TzDevice; + +class Imx636Evk2Esp : public I_RegistrableFacility { +public: + Imx636Evk2Esp(const std::shared_ptr ®map, const std::string &prefix); + + virtual bool enable(bool en); + virtual bool is_enabled() const; + virtual bool enable_out_th_recovery(bool en); + virtual bool is_out_th_recovery_enabled() const; + virtual bool enable_out_gen_last(bool en); + virtual bool is_out_gen_last_enabled() const; + virtual bool initialize(); + +private: + std::shared_ptr register_map_; + std::string prefix_; +}; + +} // namespace Metavision + +#endif // METAVISION_HAL_IMX636_EVK2_ESP_H diff --git a/hal_psee_plugins/python/CMakeLists.txt b/hal_psee_plugins/python/CMakeLists.txt new file mode 100644 index 000000000..674b09098 --- /dev/null +++ b/hal_psee_plugins/python/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +# Tests +if (BUILD_TESTING) + add_subdirectory(tests) +endif (BUILD_TESTING) diff --git a/hal_psee_plugins/python/tests/CMakeLists.txt b/hal_psee_plugins/python/tests/CMakeLists.txt new file mode 100644 index 000000000..6170d8df9 --- /dev/null +++ b/hal_psee_plugins/python/tests/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +get_pybind_pythonpath(PYTHON3_PYTHON_PATH) + +add_pytest(NAME hal-psee-plugins-python-bindings-test + PATH ${CMAKE_CURRENT_SOURCE_DIR} + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + HAL_PLUGIN_PATH "${PROJECT_BINARY_DIR}/hal/cpp/test/plugins" + PYTHONPATH ${PYTHON3_PYTHON_PATH} +) diff --git a/hal_psee_plugins/python/tests/device_discovery_pytest.py b/hal_psee_plugins/python/tests/device_discovery_pytest.py new file mode 100644 index 000000000..d2fd22c73 --- /dev/null +++ b/hal_psee_plugins/python/tests/device_discovery_pytest.py @@ -0,0 +1,25 @@ +# 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.import inspect + +import os +import pytest +import inspect + +import metavision_hal + + +def pytestcase_hal_psee_plugin_can_open_raw_string_path(dataset_dir): + device = metavision_hal.DeviceDiscovery.open_raw_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + assert device is not None + + +def pytestcase_hal_psee_plugin_can_open_raw_pathlib(dataset_dir): + import pathlib + device = metavision_hal.DeviceDiscovery.open_raw_file(pathlib.Path(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + assert device is not None diff --git a/hal_psee_plugins/resources/rules/99-evkv2.rules b/hal_psee_plugins/resources/rules/99-evkv2.rules index ad8adcef7..0bacd3546 100644 --- a/hal_psee_plugins/resources/rules/99-evkv2.rules +++ b/hal_psee_plugins/resources/rules/99-evkv2.rules @@ -1 +1,2 @@ -ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="03fd", ATTR{idProduct}=="5832", MODE="0666" \ No newline at end of file +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="03fd", ATTR{idProduct}=="5832", MODE="0666" +ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="1fc9", ATTR{idProduct}=="5838", MODE="0666" diff --git a/hal_psee_plugins/samples/metavision_riscv_logger/CMakeLists.txt b/hal_psee_plugins/samples/metavision_riscv_logger/CMakeLists.txt index 19bc58386..9155e5467 100644 --- a/hal_psee_plugins/samples/metavision_riscv_logger/CMakeLists.txt +++ b/hal_psee_plugins/samples/metavision_riscv_logger/CMakeLists.txt @@ -15,7 +15,7 @@ target_link_libraries(metavision_riscv_logger PRIVATE ${common_libraries}) install(TARGETS ${sample} RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES diff --git a/hal_psee_plugins/src/boards/fx3/fx3_camera_discovery.cpp b/hal_psee_plugins/src/boards/fx3/fx3_camera_discovery.cpp index 2c6fba8e7..9cd97fd59 100644 --- a/hal_psee_plugins/src/boards/fx3/fx3_camera_discovery.cpp +++ b/hal_psee_plugins/src/boards/fx3/fx3_camera_discovery.cpp @@ -61,7 +61,7 @@ Metavision::CameraDiscovery::SystemList Fx3CameraDiscovery::list_available_sourc cmd.open(serial); SystemId system_id = static_cast(cmd.get_system_id()); if (device_builder_factory().contains(system_id) || device_builder_factory().contains(SYSTEM_FX3_UNKNOWN)) { - system_list.push_back({serial, Metavision::USB_LINK, system_id}); + system_list.push_back({serial, Metavision::USB_LINK}); } } return system_list; diff --git a/hal_psee_plugins/src/boards/fx3/fx3_hw_identification.cpp b/hal_psee_plugins/src/boards/fx3/fx3_hw_identification.cpp index 895688e0c..ceb906eb0 100644 --- a/hal_psee_plugins/src/boards/fx3/fx3_hw_identification.cpp +++ b/hal_psee_plugins/src/boards/fx3/fx3_hw_identification.cpp @@ -45,9 +45,6 @@ Fx3HWIdentification::Fx3HWIdentification(const std::shared_ptrget_serial(); } -long Fx3HWIdentification::get_system_id() const { - return icmd_->get_system_id(); -} std::string Fx3HWIdentification::get_integrator() const { return integrator_; diff --git a/hal_psee_plugins/src/boards/rawfile/file_hw_identification.cpp b/hal_psee_plugins/src/boards/rawfile/file_hw_identification.cpp index 45112172f..64d1c7e53 100644 --- a/hal_psee_plugins/src/boards/rawfile/file_hw_identification.cpp +++ b/hal_psee_plugins/src/boards/rawfile/file_hw_identification.cpp @@ -32,10 +32,6 @@ std::string FileHWIdentification::get_serial() const { return raw_header_.get_serial(); } -long FileHWIdentification::get_system_id() const { - return raw_header_.get_system_id(); -} - I_HW_Identification::SensorInfo FileHWIdentification::get_sensor_info() const { return raw_header_.get_sensor_info(); } diff --git a/hal_psee_plugins/src/boards/rawfile/psee_file_discovery.cpp b/hal_psee_plugins/src/boards/rawfile/psee_file_discovery.cpp index bca83ef65..b22dbd074 100644 --- a/hal_psee_plugins/src/boards/rawfile/psee_file_discovery.cpp +++ b/hal_psee_plugins/src/boards/rawfile/psee_file_discovery.cpp @@ -17,7 +17,7 @@ #include "metavision/psee_hw_layer/boards/rawfile/file_hw_identification.h" #include "metavision/hal/facilities/i_events_stream.h" #include "metavision/hal/utils/device_builder.h" -#include "metavision/hal/utils/file_data_transfer.h" +#include "metavision/hal/utils/file_raw_data_producer.h" #include "metavision/hal/utils/raw_file_config.h" #include "metavision/sdk/base/events/event_cd.h" #include "metavision/sdk/base/events/event_erc_counter.h" @@ -41,7 +41,8 @@ bool PseeFileDiscovery::discover(DeviceBuilder &device_builder, std::unique_ptr< std::make_unique(device_builder.get_plugin_software_info(), psee_header)); device_builder.add_facility(std::make_unique( - std::make_unique(std::move(stream), raw_size_bytes, file_config), file_hw_id, decoder)); + std::make_unique(std::move(stream), raw_size_bytes, file_config), file_hw_id, + decoder)); return true; } catch (std::exception &e) { MV_HAL_LOG_TRACE() << "Could not read file:" << e.what(); diff --git a/hal_psee_plugins/src/boards/rawfile/psee_raw_file_header.cpp b/hal_psee_plugins/src/boards/rawfile/psee_raw_file_header.cpp index 2dc18980a..4c99b1ac7 100644 --- a/hal_psee_plugins/src/boards/rawfile/psee_raw_file_header.cpp +++ b/hal_psee_plugins/src/boards/rawfile/psee_raw_file_header.cpp @@ -49,7 +49,6 @@ static const std::string legacy_evt21_value = "2.1"; PseeRawFileHeader::PseeRawFileHeader(const I_HW_Identification &hw, const StreamFormat &format) { set_serial(hw.get_serial()); - set_system_id(hw.get_system_id()); set_sensor_info(hw.get_sensor_info()); set_format(format); } diff --git a/hal_psee_plugins/src/boards/treuzell/tz_camera_discovery.cpp b/hal_psee_plugins/src/boards/treuzell/tz_camera_discovery.cpp index 16bd2aa4c..e2c949f4d 100644 --- a/hal_psee_plugins/src/boards/treuzell/tz_camera_discovery.cpp +++ b/hal_psee_plugins/src/boards/treuzell/tz_camera_discovery.cpp @@ -80,8 +80,7 @@ CameraDiscovery::SystemList TzCameraDiscovery::list_available_sources() { CameraDiscovery::SystemList system_list; auto boards = list_boards(); for (auto board : boards) { - // Last argument is the system ID, but we can't know how many the board has before building the devices - system_list.push_back({board->get_serial(), USB_LINK, 0}); + system_list.push_back({board->get_serial(), USB_LINK}); } return system_list; } diff --git a/hal_psee_plugins/src/boards/treuzell/tz_hw_identification.cpp b/hal_psee_plugins/src/boards/treuzell/tz_hw_identification.cpp index 940e20a04..afc5e0b20 100644 --- a/hal_psee_plugins/src/boards/treuzell/tz_hw_identification.cpp +++ b/hal_psee_plugins/src/boards/treuzell/tz_hw_identification.cpp @@ -41,14 +41,6 @@ std::string TzHWIdentification::get_serial() const { return icmd_->get_serial(); } -long TzHWIdentification::get_system_id() const { - for (auto dev : devices_) { - if (auto main_dev = dynamic_cast(dev.get())) - return main_dev->get_system_id(); - } - return 0; -} - I_HW_Identification::SensorInfo TzHWIdentification::get_sensor_info() const { for (auto dev : devices_) { if (auto main_dev = dynamic_cast(dev.get())) diff --git a/hal_psee_plugins/src/boards/treuzell/tz_libusb_board_command.cpp b/hal_psee_plugins/src/boards/treuzell/tz_libusb_board_command.cpp index 6a6cba343..257cce560 100644 --- a/hal_psee_plugins/src/boards/treuzell/tz_libusb_board_command.cpp +++ b/hal_psee_plugins/src/boards/treuzell/tz_libusb_board_command.cpp @@ -342,7 +342,8 @@ void TzLibUSBBoardCommand::write_device_register(uint32_t device, uint32_t addre throw std::system_error(TZ_PROPERTY_MISMATCH, TzError(), "address mismatch"); } -std::unique_ptr TzLibUSBBoardCommand::build_data_transfer(uint32_t raw_event_size_bytes) { +std::unique_ptr + TzLibUSBBoardCommand::build_raw_data_producer(uint32_t raw_event_size_bytes) { return std::make_unique(dev_, bEpCommAddress, raw_event_size_bytes); } diff --git a/hal_psee_plugins/src/boards/utils/psee_libusb_data_transfer.cpp b/hal_psee_plugins/src/boards/utils/psee_libusb_data_transfer.cpp index 87614711c..8d991a193 100644 --- a/hal_psee_plugins/src/boards/utils/psee_libusb_data_transfer.cpp +++ b/hal_psee_plugins/src/boards/utils/psee_libusb_data_transfer.cpp @@ -11,7 +11,6 @@ #include #include -#include #ifdef _WIN32 #ifndef _MSC_VER @@ -23,11 +22,10 @@ #define WIN_CALLBACK_DECL #endif +#include "metavision/hal/utils/data_transfer.h" #include "metavision/hal/utils/hal_connection_exception.h" -#include "metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h" -#include "boards/utils/config_registers_map.h" - #include "metavision/hal/utils/hal_log.h" +#include "metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h" namespace Metavision { @@ -87,11 +85,11 @@ class PseeLibUSBDataTransfer::AsyncTransfer { } catch (const std::exception &e) { MV_HAL_LOG_TRACE() << "Exception in ~AsyncTransfer:" << e.what(); } } - DataTransfer::BufferPtr &&get_buf() { + BufferPtr &&get_buf() { if (!completed()) { throw std::runtime_error("Trying to alter an ongoing transfer"); } - buf_->resize(static_cast(transfer_->actual_length)); + buf_->resize(static_cast(transfer_->actual_length)); return std::move(buf_); } libusb_transfer_status status() const { @@ -116,7 +114,7 @@ class PseeLibUSBDataTransfer::AsyncTransfer { // The USB device for which the transfer is prepared std::shared_ptr dev_; // The memory to be transfered from/to - DataTransfer::BufferPtr buf_; + BufferPtr buf_; // The underlying object for libusb std::unique_ptr transfer_; @@ -128,15 +126,16 @@ const size_t PseeLibUSBDataTransfer::packet_size_ = get_packet_size(); const size_t PseeLibUSBDataTransfer::async_transfer_num_ = get_async_transfer_number(); const unsigned int PseeLibUSBDataTransfer::timeout_ = static_cast(get_time_out()); -DataTransfer::BufferPool PseeLibUSBDataTransfer::make_buffer_pool(size_t default_pool_byte_size) { - DataTransfer::BufferPool pool = - DataTransfer::BufferPool::make_unbounded(PseeLibUSBDataTransfer::async_transfer_num_, get_packet_size()); +DataTransfer::DefaultBufferPool PseeLibUSBDataTransfer::make_buffer_pool(size_t default_pool_byte_size) { + auto pool = + DataTransfer::DefaultBufferPool::make_unbounded(PseeLibUSBDataTransfer::async_transfer_num_, get_packet_size()); + auto buffer_pool_byte_size = get_envar_or_default("MV_PSEE_PLUGIN_DATA_TRANSFER_BUFFER_POOL_BYTE_SIZE", default_pool_byte_size); if (buffer_pool_byte_size) { auto num_obj_pool = buffer_pool_byte_size / packet_size_; MV_HAL_LOG_INFO() << "Creating Fixed size data pool of : " << num_obj_pool << "x" << packet_size_ << "B"; - pool = DataTransfer::BufferPool::make_bounded(num_obj_pool, packet_size_); + pool = DataTransfer::DefaultBufferPool::make_bounded(num_obj_pool, packet_size_); } return pool; @@ -144,18 +143,15 @@ DataTransfer::BufferPool PseeLibUSBDataTransfer::make_buffer_pool(size_t default PseeLibUSBDataTransfer::PseeLibUSBDataTransfer(const std::shared_ptr dev, EpId endpoint, uint32_t raw_event_size_bytes, - const DataTransfer::BufferPool &buffer_pool) : - DataTransfer(raw_event_size_bytes, buffer_pool, true), - dev_(dev), - bEpCommAddress_(endpoint), - vtransfer_(async_transfer_num_) {} + const DataTransfer::DefaultBufferPool &buffer_pool) : + buffer_pool_(buffer_pool), dev_(dev), bEpCommAddress_(endpoint), vtransfer_(async_transfer_num_) {} PseeLibUSBDataTransfer::~PseeLibUSBDataTransfer() { // Nothing to do, just need the definition of ~AsyncTransfer where this destructor is // defined, to be able to delete vtransfer_ } -void PseeLibUSBDataTransfer::start_impl(BufferPtr buffer) { +void PseeLibUSBDataTransfer::start_impl() { // Drop existing URB on device side if (auto r = dev_->clear_halt(bEpCommAddress_); r < 0) { throw HalConnectionException(r, libusb_error_category()); @@ -164,22 +160,22 @@ void PseeLibUSBDataTransfer::start_impl(BufferPtr buffer) { auto shift = timeout_ / async_transfer_num_; // Queue transfers on host side for (auto &transfer : vtransfer_) { + auto buffer = buffer_pool_.acquire(); buffer->resize(packet_size_); transfer.prepare(dev_, bEpCommAddress_, std::move(buffer), timeout); transfer.submit(); // Timeout is counted from submit time // Desynchronize the first completions so that completions happen steadily timeout += shift; - buffer = get_buffer(); } } -void PseeLibUSBDataTransfer::run_impl() { +void PseeLibUSBDataTransfer::run_impl(const DataTransfer &data_transfer) { MV_HAL_LOG_TRACE() << "poll thread running"; timeout_cnt_ = 0; try { - while (!should_stop()) { - run_transfers(); + while (!data_transfer.should_stop()) { + run_transfers(data_transfer); } } catch (const HalConnectionException &e) { if (e.code().value() == LIBUSB_TRANSFER_CANCELLED) { @@ -193,7 +189,7 @@ void PseeLibUSBDataTransfer::run_impl() { MV_HAL_LOG_TRACE() << "poll thread shutting down"; } -void PseeLibUSBDataTransfer::run_transfers() { +void PseeLibUSBDataTransfer::run_transfers(const DataTransfer &data_producer) { // start() queued the transfers, wait for their completion, pass the data to DataTransfer, // and requeue an other buffer for (auto &transfer : vtransfer_) { @@ -203,13 +199,13 @@ void PseeLibUSBDataTransfer::run_transfers() { // generating an event transfer.wait_completion(); // if we are stopping, there is no point forwarding data and requeuing buffers - if (should_stop()) { + if (data_producer.should_stop()) { break; } // There was an event and we are still streaming, check the transfer status switch (transfer.status()) { - case LIBUSB_TRANSFER_TIMED_OUT: + case LIBUSB_TRANSFER_TIMED_OUT: { timeout_cnt_++; if ((timeout_cnt_ % BULK_NAK_REPORT_THRESHOLD) == 0) { MV_HAL_LOG_TRACE() << "\rBulk Transfer NACK " << timeout_cnt_; @@ -217,19 +213,21 @@ void PseeLibUSBDataTransfer::run_transfers() { // No data, just requeue the same buffer transfer.submit(); break; - case LIBUSB_TRANSFER_COMPLETED: + } + case LIBUSB_TRANSFER_COMPLETED: { timeout_cnt_ = 0; // Note: unlike raw libusb, partial transfers are reported as completed - transfer_res.first = transfer.get_buf(); // Pass the data and get a new buffer - transfer_res = transfer_data(transfer_res.first); + data_producer.transfer_data(transfer.get_buf()); // Ensure the buffer can receive a transfer - transfer_res.first->resize(packet_size_); + auto buff = buffer_pool_.acquire(); + buff->resize(packet_size_); // Attach it to the transfer - transfer.prepare(dev_, bEpCommAddress_, std::move(transfer_res.first), timeout_); + transfer.prepare(dev_, bEpCommAddress_, std::move(buff), timeout_); // Requeue the transfer with the new buffer transfer.submit(); break; + } default: throw HalConnectionException(transfer.status(), libusb_error_category()); } diff --git a/hal_psee_plugins/src/boards/v4l2/CMakeLists.txt b/hal_psee_plugins/src/boards/v4l2/CMakeLists.txt index 592ff9508..8e29b3974 100644 --- a/hal_psee_plugins/src/boards/v4l2/CMakeLists.txt +++ b/hal_psee_plugins/src/boards/v4l2/CMakeLists.txt @@ -20,8 +20,9 @@ target_sources(metavision_hal_psee_plugin_obj PRIVATE target_sources(metavision_psee_hw_layer_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_camera_discovery.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_data_transfer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_mmap_allocator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_dmabuf_allocator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_device.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_user_ptr_data.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_board_command.cpp ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_hardware_identification.cpp ) diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_board_command.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_board_command.cpp index c261c1a7b..d8a23a668 100644 --- a/hal_psee_plugins/src/boards/v4l2/v4l2_board_command.cpp +++ b/hal_psee_plugins/src/boards/v4l2/v4l2_board_command.cpp @@ -27,20 +27,9 @@ #include "boards/v4l2/v4l2_device.h" #include "boards/v4l2/v4l2_data_transfer.h" #include "metavision/psee_hw_layer/boards/v4l2/v4l2_board_command.h" -#include "boards/treuzell/treuzell_command_definition.h" -#include "metavision/psee_hw_layer/boards/treuzell/tz_control_frame.h" -#include "devices/utils/device_system_id.h" #include "metavision/hal/utils/hal_exception.h" #include "utils/psee_hal_plugin_error_code.h" -#ifdef USE_JAVA_BINDINGS -#include "is_usb_java.h" -#endif - -#define PSEE_EVK_PROTOCOL 0 - -#define TZ_MAX_ANSWER_SIZE 1024 - namespace Metavision { V4L2BoardCommand::V4L2BoardCommand(std::string device_path) { @@ -58,15 +47,19 @@ V4L2BoardCommand::V4L2BoardCommand(std::string device_path) { // TODO: get video_path_ and sensor_subdev_path_ from media_path when available. // Hack for now, let's just dismiss the /dev/mediaX device and hardcode the video and sensor subdev path. + // More hack: sometimes it's not subdev1 + const char *sensor_path = getenv("V4L2_SENSOR_PATH"); + if (!sensor_path) + sensor_path = "/dev/v4l-subdev1"; // and now for sensor_fd_: - if (-1 == stat("/dev/v4l-subdev1", &st)) + if (-1 == stat(sensor_path, &st)) raise_error("Cannot identify device /dev/v4l-subdev1."); if (!S_ISCHR(st.st_mode)) throw std::runtime_error("/dev/v4l-subdev1 is not a device"); - sensor_fd_ = open("/dev/v4l-subdev1", O_RDWR); + sensor_fd_ = open(sensor_path, O_RDWR); if (-1 == sensor_fd_) { raise_error("Cannot open device /dev/v4l-subdev1"); }; @@ -117,8 +110,8 @@ unsigned int V4L2BoardCommand::get_device_count() { std::vector V4L2BoardCommand::read_device_register(uint32_t device, uint32_t address, int nval) { std::vector res; - struct v4l2_dbg_match match; - struct v4l2_dbg_register get_reg; + struct v4l2_dbg_match match = {0}; + struct v4l2_dbg_register get_reg = {0}; int i, retval; match.type = V4L2_CHIP_MATCH_BRIDGE; @@ -137,8 +130,8 @@ std::vector V4L2BoardCommand::read_device_register(uint32_t device, ui } void V4L2BoardCommand::write_device_register(uint32_t device, uint32_t address, const std::vector &val) { - struct v4l2_dbg_match match; - struct v4l2_dbg_register set_reg; + struct v4l2_dbg_match match = {0}; + struct v4l2_dbg_register set_reg = {0}; int i, retval; match.type = V4L2_CHIP_MATCH_BRIDGE; @@ -158,12 +151,19 @@ std::shared_ptr V4L2BoardCommand::get_device_control() { return device_; } -std::unique_ptr V4L2BoardCommand::build_data_transfer(uint32_t raw_event_size_bytes) { +std::unique_ptr + V4L2BoardCommand::build_raw_data_producer(uint32_t raw_event_size_bytes) { // TODO: based on the /dev/mediaX device (not available with thor96 psee eb driver), extract the pipeline topology, // extract the /dev/videoX associated entity, and populate the DataTransfer with it. // Right now, we'll just hard code it to /dev/video0 ¯\_(ツ)_/¯ // more details in: https://github.com/gjasny/v4l-utils/blob/master/utils/media-ctl/media-ctl.c#L526 - return std::make_unique(device_, raw_event_size_bytes); + + // If the environment set a heap, us it, otherwise, use the driver's allocator + if (std::getenv("V4L2_HEAP")) + return std::make_unique(device_->get_fd(), raw_event_size_bytes, "/dev/dma_heap", + std::getenv("V4L2_HEAP")); + else + return std::make_unique(device_->get_fd(), raw_event_size_bytes); } } // namespace Metavision diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_camera_discovery.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_camera_discovery.cpp index 77d2903b8..b8fb1d4eb 100644 --- a/hal_psee_plugins/src/boards/v4l2/v4l2_camera_discovery.cpp +++ b/hal_psee_plugins/src/boards/v4l2/v4l2_camera_discovery.cpp @@ -72,7 +72,7 @@ CameraDiscovery::SerialList V4l2CameraDiscovery::list() { CameraDiscovery::SystemList V4l2CameraDiscovery::list_available_sources() { SystemList system_list; for (const auto &device : devices_) { - system_list.push_back({device->get_serial(), ConnectionType::MIPI_LINK, 000420}); + system_list.push_back({device->get_serial(), ConnectionType::MIPI_LINK}); } return system_list; } diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_data_transfer.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_data_transfer.cpp index 58168c0a5..0b1482ae4 100644 --- a/hal_psee_plugins/src/boards/v4l2/v4l2_data_transfer.cpp +++ b/hal_psee_plugins/src/boards/v4l2/v4l2_data_transfer.cpp @@ -9,69 +9,228 @@ * 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 "boards/v4l2/v4l2_device.h" #include "boards/v4l2/v4l2_data_transfer.h" -#include "boards/v4l2/v4l2_user_ptr_data.h" +#include "boards/v4l2/dma_buf_heap.h" +#include "metavision/hal/utils/data_transfer.h" #include "metavision/hal/utils/hal_log.h" -using namespace Metavision; +namespace Metavision { -constexpr bool allow_buffer_drop = true; -constexpr size_t data_stream_buffer_number = 32; -constexpr size_t data_stream_buffer_size = 1 * 1024; +static constexpr bool allow_buffer_drop = true; +static constexpr size_t device_buffer_preload_number = 4; -constexpr size_t device_buffer_size = 8 * 1024 * 1024; -constexpr size_t device_buffer_number = 3; +V4l2DataTransfer::V4l2DataTransfer(int fd, uint32_t raw_event_size_bytes) : + memtype_(V4L2_MEMORY_MMAP), + fd_(dup(fd)), + v4l2_allocator_(std::make_unique(fd)), + pool_(ObjectPool::make_bounded(device_buffer_number, Allocator{v4l2_allocator_.get()})) { + auto res = request_buffers(device_buffer_number); + if (res.count != device_buffer_number) + throw std::system_error(ENOMEM, std::generic_category(), "Unexpected amount of V4L2 buffers allocated"); +} -V4l2DataTransfer::V4l2DataTransfer(std::shared_ptr device, uint32_t raw_event_size_bytes) : - DataTransfer(raw_event_size_bytes, - DataTransfer::BufferPool::make_bounded(data_stream_buffer_number, data_stream_buffer_size), - allow_buffer_drop), - device_(device) {} +V4l2DataTransfer::V4l2DataTransfer(int fd, uint32_t raw_event_size_bytes, const std::string &heap_path, + const std::string &heap_name) : + memtype_(V4L2_MEMORY_DMABUF), + fd_(dup(fd)), + v4l2_allocator_(std::make_unique(fd, std::make_unique(heap_path, heap_name))), + pool_(ObjectPool::make_bounded(device_buffer_number, Allocator{v4l2_allocator_.get()})) { + auto res = request_buffers(device_buffer_number); + if (res.count != device_buffer_number) + throw std::system_error(ENOMEM, std::generic_category(), "Unexpected amount of V4L2 buffers allocated"); +} -V4l2DataTransfer::~V4l2DataTransfer() {} +V4l2DataTransfer::~V4l2DataTransfer() { + // Release the previously acquired buffers + request_buffers(0); + // and release this file handler + close(fd_); +} -void V4l2DataTransfer::start_impl(BufferPtr) { - MV_HAL_LOG_INFO() << "V4l2DataTransfer - start_impl() "; +V4l2RequestBuffers V4l2DataTransfer::request_buffers(uint32_t nb_buffers) { + V4l2RequestBuffers req{0}; + req.count = nb_buffers; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = memtype_; - buffers = std::make_unique(device_, "/dev/dma_heap", "linux,cma", device_buffer_size, - device_buffer_number); + if (-1 == ioctl(fd_, VIDIOC_REQBUFS, &req)) { + throw std::system_error(errno, std::generic_category(), "VIDIOC_REQBUFS failed"); + } - MV_HAL_LOG_TRACE() << " Nb buffers pre allocated: " << buffers->get_nb_buffers() << std::endl; - for (unsigned int i = 0; i < buffers->get_nb_buffers(); ++i) { - buffers->release_buffer(i); + return req; +} + +void V4l2DataTransfer::start_impl() { + MV_HAL_LOG_INFO() << "V4l2DataTransfer - start_impl() "; + + // DMA usually need 2 buffers to run, to be able to quickly switch from one transfer to the next + // The way datatransfer is built, run_impl sequentially dequeue a buffer, pass it to EventStream, query another + // from the buffer pool, queue it, then dequeue the next buffer. + // If all buffer are queued it becomes impossible to dequeue 2 of them to process them in parallel. + // Since 2 queued buffers are usually enough, and we have 32 of them, queuing 4 should avoid issues with hardware + // expecting more, while allowing 28 buffers in parallel (or in a 28-stage pipeline) in the app. + for (unsigned int i = 0; i < device_buffer_preload_number; ++i) { + auto input_buff = pool_.acquire(); + // Using DMABUF, the allocator handles the pool of buffers through file descriptors, we need to choose a free + // index to queue a buffer. + // On the other hand, with MMAP, the pool is handled through indices, and fill_v4l2_buffer will fix the index + // in the V4l2Buffer descriptor. + V4l2Buffer buffer = {.index = i, .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, .memory = memtype_}; + fill_v4l2_buffer(input_buff, buffer); + + // Update buffer size to its capacity so that it may only be downsized after transfer + // upsizing buffer size may default-initialize content, erasing the actual data + begin_cpu_access(input_buff); + input_buff->resize(input_buff->capacity()); + end_cpu_access(input_buff); + + if (ioctl(fd_, VIDIOC_QBUF, &buffer) < 0) { + throw std::system_error(errno, std::generic_category(), "VIDIOC_QBUF failed"); + } + queued_buffers_[buffer.index] = std::move(input_buff); } } -void V4l2DataTransfer::run_impl() { +void V4l2DataTransfer::run_impl(const DataTransfer &data_transfer) { MV_HAL_LOG_INFO() << "V4l2DataTransfer - run_impl() "; + struct pollfd fds[1]; + + fds[0].fd = fd_; + fds[0].events = POLLIN; + fds[0].revents = 0; + + while (!data_transfer.should_stop()) { + V4l2Buffer buf{0}; + + if (poll(fds, 1, -1) < 0) { + MV_HAL_LOG_ERROR() << "V4l2DataTransfer: poll failed" << strerror(errno); + break; + } + + if (fds[0].revents & POLLERR) { + // When stopping, STREAMOFF ioctl will return all buffers and epoll will signal an error, since there is no + // queued buffer anymore. This will usually trig faster than calling DataTransfer::stop, and should_stop() + // will still return false, even though I_EventStream is stopping. + // Stop polling and wait for DataTransfer to call stop_impl before cleaning + MV_HAL_LOG_TRACE() << "V4l2DataTransfer: poll returned" << std::hex << fds[0].revents << std::dec; + break; + } + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = memtype_; + if (ioctl(fd_, VIDIOC_DQBUF, &buf) < 0) { + MV_HAL_LOG_ERROR() << "V4l2DataTransfer: DQBUF failed" << strerror(errno); + break; + } + + MV_HAL_LOG_DEBUG() << "Grabbed buffer" << buf.index << "of:" << buf.bytesused << "Bytes."; + + // Advertise CPU operations to allow cache maintenance + begin_cpu_access(queued_buffers_[buf.index]); + + // Get the vector corresponding to this buffer and transfer the data + queued_buffers_[buf.index]->resize(buf.bytesused); + + // Transfer the data for processing + // if there is no more available buffer and buffer drop is allowed, + // skip this operation to be able to re-queue the buffer immediatly + if (!(allow_buffer_drop && pool_.empty())) { + data_transfer.transfer_data(queued_buffers_[buf.index]); + } + + // Release the buffer to DataTransfer BufferPool + queued_buffers_[buf.index].reset(); + + // Get the next buffer, possibly the one we just released (if not hold by data_transfer) + auto next = pool_.acquire(); + + // buf is filled with the info of the dequeued buffer + // update it with next information + fill_v4l2_buffer(next, buf); + + // Update buffer size to its capacity so that it may only be downsized after transfer + // upsizing buffer size may default-initialize content, erasing the actual data + next->resize(next->capacity()); + + // Advertise end of CPU operations to allow cache maintenance + end_cpu_access(next); + + // Queue the next buffer to keep the device running + if (ioctl(fd_, VIDIOC_QBUF, &buf) < 0) { + throw std::system_error(errno, std::generic_category(), "VIDIOC_QBUF failed"); + } + queued_buffers_[buf.index] = std::move(next); + } +} + +void V4l2DataTransfer::stop_impl() { + MV_HAL_LOG_TRACE() << "V4l2DataTransfer - stop_impl() "; + // Here we trust that I_EventStream has also stopped V4L2 Device Control, which does STREAMOFF + // and return every buffer, allowing to release buffers here + for (size_t i = 0; i < device_buffer_number; i++) + queued_buffers_[i].reset(); +} - while (!should_stop()) { - // Grab a MIPI frame - int idx = buffers->poll_buffer(); - auto [data, data_length] = buffers->get_buffer_desc(idx); +V4l2DataTransfer::V4l2Allocator &V4l2DataTransfer::v4l2_alloc(BufferPtr &buf) const { + // The std::vectors in BufferPool are built with a V4l2Allocator, which can do this work + V4l2Allocator *alloc = dynamic_cast(buf->get_allocator().resource()); + if (!alloc) + throw std::system_error(EPERM, std::generic_category(), "Memory resource is expected to be V4l2Allocator"); + return *alloc; +} - MV_HAL_LOG_TRACE() << "Grabed buffer " << idx << "from: " << std::hex << data << " of: " << std::dec - << data_length << " Bytes."; +// Fills the V4L2 descriptor with the buffer info. This information depends on the Allocator implementation +// For instance in MMAP the buffer is mapped to an index of the device +// But on DMABUF, the buffer is mapped to a standalone file descriptor +// fill_v4l2_buffer requires v4l2_buf to be filled with a non-queued index of the V4L2 device, but may +// rewrite it, in case there is a fixed mapping between buffers and indices, as in MMAP use case +// The caller shall not assume that v4l2_buf.index is unchanged after a call to fill_v4l2_buffer +void V4l2DataTransfer::fill_v4l2_buffer(BufferPtr &buf, V4l2Buffer &v4l2_buf) const { + // Since we inherit from DataTransfer, which requires a BufferPool, we can't query the actual buffer + // size before building the BufferPool, and it is built with empty buffers. This ensure the vectors + // are allocated before trying to map their allocations with the V4L2 buffers + if (!buf->data()) { + if (auto *v4l2_alloc = dynamic_cast(buf->get_allocator().resource())) { + buf->reserve(v4l2_alloc->max_byte_size()); + } else { + MV_HAL_LOG_ERROR() << "V4l2DataTransfer - Resource allocator should implement 'V4l2Allocator'"; + } + } - // Get transfer buffer from the pool and transfer the data - auto local_buff = get_buffer(); - local_buff->resize(data_length); - std::memcpy(local_buff->data(), data, data_length); - transfer_data(local_buff); + v4l2_alloc(buf).fill_v4l2_buffer(buf->data(), v4l2_buf); +} - // Reset the buffer data - memset(data, 0, data_length); +// Call the cache maintenance that fits the memory type +void V4l2DataTransfer::begin_cpu_access(BufferPtr &buf) const { + v4l2_alloc(buf).begin_cpu_access(buf->data()); +} - buffers->release_buffer(idx); - } +void V4l2DataTransfer::end_cpu_access(BufferPtr &buf) const { + v4l2_alloc(buf).end_cpu_access(buf->data()); } -void V4l2DataTransfer::stop_impl() { - MV_HAL_LOG_TRACE() << "V4l2DataTransfer - stop_impl() "; - buffers.reset(); +V4l2DataTransfer::V4l2Allocator::V4l2Allocator(int videodev_fd) { + struct v4l2_format format { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE + }; + + // Technically, the format is not locked yet, it will be locked when V4l2DataTransfer constructor does + // request_buffers, but we need to build the BufferPool with an Allocator first + if (ioctl(videodev_fd, VIDIOC_G_FMT, &format)) + throw std::system_error(errno, std::generic_category(), "VIDIOC_G_FMT failed"); + + buffer_byte_size_ = format.fmt.pix.sizeimage; } + +} // namespace Metavision diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_device.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_device.cpp index e036a67b5..051ba5de5 100644 --- a/hal_psee_plugins/src/boards/v4l2/v4l2_device.cpp +++ b/hal_psee_plugins/src/boards/v4l2/v4l2_device.cpp @@ -54,59 +54,13 @@ V4L2DeviceControl::V4L2DeviceControl(const std::string &dev_name) { if (!(cap_.capabilities & V4L2_CAP_STREAMING)) throw std::runtime_error(dev_name + " does not support streaming i/o"); - struct v4l2_format fmt; - std::memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - fmt.fmt.pix.field = V4L2_FIELD_ANY; - fmt.fmt.pix.width = 65536; - fmt.fmt.pix.height = 64; - - if (ioctl(fd_, VIDIOC_S_FMT, &fmt)) - raise_error("VIDIOC_S_FMT failed"); -} - -V4l2RequestBuffers V4L2DeviceControl::request_buffers(v4l2_memory memory, uint32_t nb_buffers) { - V4l2RequestBuffers req{0}; - req.count = nb_buffers; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = memory; - - if (-1 == ioctl(fd_, VIDIOC_REQBUFS, &req)) { - raise_error("VIDIOC_QUERYBUF failed"); - } - - return req; -} - -V4l2Buffer V4L2DeviceControl::query_buffer(v4l2_memory memory_type, uint32_t buf_index) { - V4l2Buffer buf{0}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = memory_type; - buf.index = buf_index; - - if (ioctl(fd_, VIDIOC_QUERYBUF, &buf)) - raise_error("VIDIOC_QUERYBUF failed"); - - return buf; + // Note: this code expects the V4L2 device to be configured to output a supported format } V4l2Capability V4L2DeviceControl::get_capability() const { return cap_; } -int V4L2DeviceControl::queue_buffer(V4l2Buffer &buffer) { - auto ioctl_res = ioctl(fd_, VIDIOC_QBUF, &buffer); - if (ioctl_res) { - raise_error("VIDIOC_QBUF failed"); - } - return ioctl_res; -} - -int V4L2DeviceControl::dequeue_buffer(V4l2Buffer *buffer) { - return ioctl(fd_, VIDIOC_DQBUF, buffer); -} - void V4L2DeviceControl::start() { enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl(fd_, VIDIOC_STREAMON, &type)) diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_dmabuf_allocator.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_dmabuf_allocator.cpp new file mode 100644 index 000000000..efc43c2d2 --- /dev/null +++ b/hal_psee_plugins/src/boards/v4l2/v4l2_dmabuf_allocator.cpp @@ -0,0 +1,78 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "boards/v4l2/v4l2_data_transfer.h" +#include "boards/v4l2/dma_buf_heap.h" + +using namespace Metavision; + +V4l2DataTransfer::DmabufAllocator::DmabufAllocator(int fd, std::unique_ptr &&heap) : + V4l2Allocator(fd), dmabuf_heap_(std::move(heap)) {} + +V4l2DataTransfer::DmabufAllocator::~DmabufAllocator() {} + +void *V4l2DataTransfer::DmabufAllocator::do_allocate(std::size_t bytes, std::size_t alignment) { + if (bytes > max_byte_size()) + throw std::length_error("Trying to allocate more than the V4L2 buffer length"); + + // Alloc a new buffer in the DMA buffer heap + auto dmabuf_fd = dmabuf_heap_->alloc(bytes); + + // Map it in the program memory + void *vaddr = mmap(NULL, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd, 0); + if (vaddr == MAP_FAILED) + throw std::system_error(errno, std::generic_category(), "Could not mmap DMABUF buffer"); + + // Save the mapping + mapping_[vaddr] = dmabuf_fd; + + return vaddr; +} + +void V4l2DataTransfer::DmabufAllocator::do_deallocate(void *p, std::size_t bytes, std::size_t alignment) { + // remove buffer mapping in userspace + munmap((void *)p, bytes); + // free it in the DmaHeap + dmabuf_heap_->free(mapping_[p]); + // Drop the map entry + mapping_.erase(p); +} + +bool V4l2DataTransfer::DmabufAllocator::do_is_equal(const std::pmr::memory_resource &other) const noexcept { + return dynamic_cast(&other) != nullptr; +} + +void V4l2DataTransfer::DmabufAllocator::fill_v4l2_buffer(void *vaddr, V4l2Buffer &buf) const { + buf.m.fd = fd(vaddr); +} + +void V4l2DataTransfer::DmabufAllocator::begin_cpu_access(void *vaddr) const { + dmabuf_heap_->cpu_sync_start(fd(vaddr)); +} + +void V4l2DataTransfer::DmabufAllocator::end_cpu_access(void *vaddr) const { + dmabuf_heap_->cpu_sync_stop(fd(vaddr)); +} + +int V4l2DataTransfer::DmabufAllocator::fd(void *vaddr) const { + auto it = mapping_.find(vaddr); + if (it == mapping_.end()) + throw std::system_error(EINVAL, std::generic_category(), "Requested fd of a non-Dmabuf buffer"); + return it->second; +} diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_hardware_identification.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_hardware_identification.cpp index b66622233..d5228078c 100644 --- a/hal_psee_plugins/src/boards/v4l2/v4l2_hardware_identification.cpp +++ b/hal_psee_plugins/src/boards/v4l2/v4l2_hardware_identification.cpp @@ -8,10 +8,6 @@ V4l2HwIdentification::V4l2HwIdentification(const V4l2Capability cap, const SensorDescriptor &sensor_descriptor) : I_HW_Identification(plugin_sw_info), cap_(cap), sensor_descriptor_(sensor_descriptor) {} -long V4l2HwIdentification::get_system_id() const { - // @TODO Retrieve those info through V4L2 - return 1234; -} I_HW_Identification::SensorInfo V4l2HwIdentification::get_sensor_info() const { // @TODO Retrieve those info through V4L2 return sensor_descriptor_.info; diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_mmap_allocator.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_mmap_allocator.cpp new file mode 100644 index 000000000..6fdde3508 --- /dev/null +++ b/hal_psee_plugins/src/boards/v4l2/v4l2_mmap_allocator.cpp @@ -0,0 +1,86 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "boards/v4l2/v4l2_data_transfer.h" + +using namespace Metavision; + +V4l2DataTransfer::V4l2MmapAllocator::V4l2MmapAllocator(int fd) : + V4l2Allocator(fd), mapping_(device_buffer_number, nullptr), fd_(dup(fd)) {} + +V4l2DataTransfer::V4l2MmapAllocator::~V4l2MmapAllocator() { + close(fd_); +} + +void *V4l2DataTransfer::V4l2MmapAllocator::do_allocate(std::size_t bytes, std::size_t alignment) { + void *vaddr; + int buffer_index; + + if (bytes > max_byte_size()) + throw std::length_error("Trying to expand allocation beyond V4L2 buffer length"); + + // Look for a free buffer + for (buffer_index = 0; buffer_index < device_buffer_number; buffer_index++) + if (mapping_[buffer_index] == nullptr) + break; + if (buffer_index >= device_buffer_number) + throw std::system_error(ENOMEM, std::generic_category(), "No more available V4L2 buffer"); + + // Query buffer information + V4l2Buffer buffer{}; + buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buffer.memory = V4L2_MEMORY_MMAP; + buffer.index = buffer_index; + + if (ioctl(fd_, VIDIOC_QUERYBUF, &buffer) < 0) + throw std::system_error(errno, std::generic_category(), "Could not query V4L2 buffer"); + + // Map it in the program memory + vaddr = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, buffer.m.offset); + if (vaddr == MAP_FAILED) + throw std::system_error(errno, std::generic_category(), "Could not mmap V4L2 buffer"); + + // Save the mapping, implicitly making the buffer used. + mapping_[buffer_index] = vaddr; + + return vaddr; +} + +void V4l2DataTransfer::V4l2MmapAllocator::do_deallocate(void *p, std::size_t bytes, std::size_t alignment) { + // Mark the buffer as unused + for (int i = 0; i < device_buffer_number; i++) + if (mapping_[i] == p) + mapping_[i] = nullptr; + // and remove its mapping in userspace + munmap(p, max_byte_size()); +} + +bool V4l2DataTransfer::V4l2MmapAllocator::do_is_equal(const std::pmr::memory_resource &other) const noexcept { + return dynamic_cast(&other) != nullptr; +} + +void V4l2DataTransfer::V4l2MmapAllocator::fill_v4l2_buffer(void *vaddr, V4l2Buffer &buf) const { + // There are at most 32 buffers, a std::map looks overkill for index search + for (int i = 0; i < device_buffer_number; i++) + if (mapping_[i] == vaddr) { + buf.index = i; + return; + } + throw std::system_error(EINVAL, std::generic_category(), "Requested index of a non-V4L2 buffer"); +} diff --git a/hal_psee_plugins/src/boards/v4l2/v4l2_user_ptr_data.cpp b/hal_psee_plugins/src/boards/v4l2/v4l2_user_ptr_data.cpp deleted file mode 100644 index a2d3c1c68..000000000 --- a/hal_psee_plugins/src/boards/v4l2/v4l2_user_ptr_data.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "boards/v4l2/dma_buf_heap.h" -#include "boards/v4l2/v4l2_device.h" -#include "boards/v4l2/v4l2_user_ptr_data.h" - -#include "metavision/hal/utils/hal_log.h" - -using namespace Metavision; - -V4l2DeviceUserPtr::V4l2DeviceUserPtr(std::shared_ptr device, const std::string &heap_path, - const std::string &heap_name, std::size_t length, unsigned int nb_buffers) : - device_(device), dma_buf_heap_(std::make_unique(heap_path, heap_name)), length_(length) { - auto granted_buffers = device->request_buffers(V4L2_MEMORY_USERPTR, nb_buffers); - MV_HAL_LOG_INFO() << "V4l2 - Requested buffers: " << nb_buffers << " granted buffers: " << granted_buffers.count - << std::endl; - - for (unsigned int i = 0; i < granted_buffers.count; ++i) { - /* Get a buffer using CMA allocator in user space. */ - auto dmabuf_fd = dma_buf_heap_->alloc(length_); - - void *start = mmap(NULL, length_, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf_fd, 0); - if (MAP_FAILED == start) - raise_error("mmap failed"); - - dma_buf_heap_->cpu_sync_start(dmabuf_fd); - memset(start, 0, length_); - - MV_HAL_LOG_TRACE() << "Allocate buffer: " << i << " at: " << std::hex << start << " of " << std::dec << length_ - << " bytes." << std::endl; - - /* Record the handle to manage the life cycle. */ - buffers_desc_.push_back(BufferDesc{start, dmabuf_fd}); - } -} - -V4l2DeviceUserPtr::~V4l2DeviceUserPtr() { - free_buffers(); -} - -/** Release the buffer designed by the index to the driver. */ -void V4l2DeviceUserPtr::release_buffer(int idx) const { - auto desc = buffers_desc_.at(idx); - - dma_buf_heap_->cpu_sync_stop(desc.dmabuf_fd); - - V4l2Buffer buf{0}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_USERPTR; - buf.index = idx; - buf.m.userptr = (unsigned long)desc.start; - buf.length = length_; - device_->queue_buffer(buf); -} - -/** Poll a MIPI frame buffer through the V4L2 interface. - * Return the buffer index. - * */ -int V4l2DeviceUserPtr::poll_buffer() const { - V4l2Buffer buf{0}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_USERPTR; - - while (device_->dequeue_buffer(&buf)) { - using namespace std::literals::chrono_literals; - std::this_thread::sleep_for(1ms); - } - - auto desc = buffers_desc_.at(buf.index); - dma_buf_heap_->cpu_sync_start(desc.dmabuf_fd); - return buf.index; -} - -/** Return the buffer address and size (in bytes) designed by the index. */ -std::pair V4l2DeviceUserPtr::get_buffer_desc(int idx) const { - auto desc = buffers_desc_.at(idx); - return std::make_pair(desc.start, V4L2DeviceControl::nb_not_null_data(desc.start, length_)); -} - -void V4l2DeviceUserPtr::free_buffers() { - int i = get_nb_buffers(); - - while (0 < i) { - auto idx = poll_buffer(); - auto buf = buffers_desc_.at(idx); - if (-1 == munmap(buf.start, length_)) - raise_error("munmap failed"); - dma_buf_heap_->free(buf.dmabuf_fd); - --i; - } - - buffers_desc_.clear(); -} - -unsigned int V4l2DeviceUserPtr::get_nb_buffers() const { - return buffers_desc_.size(); -} diff --git a/hal_psee_plugins/src/devices/CMakeLists.txt b/hal_psee_plugins/src/devices/CMakeLists.txt index 562cf68d3..a0b44e632 100644 --- a/hal_psee_plugins/src/devices/CMakeLists.txt +++ b/hal_psee_plugins/src/devices/CMakeLists.txt @@ -7,10 +7,10 @@ # 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(HAL_PSEE_OPEN_PLUGIN_DEVICES gen31 gen41 imx636 imx646 genx320 treuzell v4l2 +set(HAL_PSEE_OPEN_PLUGIN_DEVICES gen31 gen41 imx636 imx646 imx8 genx320 treuzell v4l2 CACHE INTERNAL "Hal plugin open sourced devices") -set(HAL_PSEE_CLOSED_PLUGIN_DEVICES saphir evk3d +set(HAL_PSEE_CLOSED_PLUGIN_DEVICES saphir sensorlib evk3d geny esp_proto CACHE INTERNAL "Hal plugin close sourced devices") set(HAL_PSEE_PLUGIN_DEVICES_COMMON utils common psee-video others) @@ -21,4 +21,3 @@ endforeach() foreach (hal_closed_device ${HAL_PSEE_CLOSED_PLUGIN_DEVICES}) add_subdirectory_if_exists(${hal_closed_device}) endforeach() - diff --git a/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp b/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp index daa18d959..d2c3e8b63 100644 --- a/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp +++ b/hal_psee_plugins/src/devices/gen31/gen31_event_rate_noise_filter_module.cpp @@ -49,7 +49,7 @@ Gen31_EventRateNoiseFilterModule::Gen31_EventRateNoiseFilterModule(const std::sh bool Gen31_EventRateNoiseFilterModule::enable(bool enable_filter) { get_hw_register()->write_register(base_name_ + "nfl_ctrl", "nfl_en", enable_filter); - get_event_rate_threshold(); + get_thresholds(); return true; } @@ -71,7 +71,9 @@ uint32_t Gen31_EventRateNoiseFilterModule::get_time_window() const { return get_hw_register()->read_register(base_name_ + "nfl_thresh", "period_cnt_thresh"); } -bool Gen31_EventRateNoiseFilterModule::set_event_rate_threshold(uint32_t threshold_kev_s) { +bool Gen31_EventRateNoiseFilterModule::set_thresholds( + const Gen31_EventRateNoiseFilterModule::NflThresholds &thresholds_ev_s) { + uint32_t threshold_kev_s = std::round(thresholds_ev_s.lower_bound_start / 1000.0); if (threshold_kev_s < min_event_rate_threshold_kev_s || threshold_kev_s > max_event_rate_threshold_kev_s) { return false; } @@ -83,29 +85,21 @@ bool Gen31_EventRateNoiseFilterModule::set_event_rate_threshold(uint32_t thresho auto min_event_count_in_time_shifting_window = std::round((threshold_kev_s / 1000.) * get_time_window()); // ev per microseconds get_hw_register()->write_register(base_name_ + "nfl_thresh", "evt_thresh", min_event_count_in_time_shifting_window); - get_event_rate_threshold(); + get_thresholds(); return true; } -uint32_t Gen31_EventRateNoiseFilterModule::get_event_rate_threshold() const { - current_threshold_kev_s_ = std::round( - (get_hw_register()->read_register(base_name_ + "nfl_thresh", "evt_thresh") * 1000.) / get_time_window()); - return current_threshold_kev_s_; +Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::get_thresholds() const { + const uint32_t current_threshold_kev_s = std::round( + (get_hw_register()->read_register(base_name_ + "nfl_thresh", "evt_thresh") * 1000.) / get_time_window()); + + return {(current_threshold_kev_s * 1000), 0, 0, 0}; } Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::is_thresholds_supported() const { return {1, 0, 0, 0}; } -bool Gen31_EventRateNoiseFilterModule::set_thresholds( - const Gen31_EventRateNoiseFilterModule::NflThresholds &thresholds_ev_s) { - return set_event_rate_threshold(std::round(thresholds_ev_s.lower_bound_start / 1000.0)); -} - -Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::get_thresholds() const { - return {(get_event_rate_threshold() * 1000), 0, 0, 0}; -} - Gen31_EventRateNoiseFilterModule::NflThresholds Gen31_EventRateNoiseFilterModule::get_min_supported_thresholds() const { return {(min_event_rate_threshold_kev_s * 1000), 0, 0, 0}; } diff --git a/hal_psee_plugins/src/devices/gen41/gen41_evk2_tz_device.cpp b/hal_psee_plugins/src/devices/gen41/gen41_evk2_tz_device.cpp index f06944142..a929177bb 100644 --- a/hal_psee_plugins/src/devices/gen41/gen41_evk2_tz_device.cpp +++ b/hal_psee_plugins/src/devices/gen41/gen41_evk2_tz_device.cpp @@ -37,10 +37,9 @@ #include "utils/psee_hal_utils.h" namespace Metavision { -namespace { -std::string ROOT_PREFIX = "PSEE/"; -std::string SENSOR_PREFIX = "SENSOR_IF/GEN41/"; -} // namespace + +std::string TzEvk2Gen41::ROOT_PREFIX = "PSEE/"; +std::string TzEvk2Gen41::SENSOR_PREFIX = "SENSOR_IF/GEN41/"; TzEvk2Gen41::TzEvk2Gen41(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent) : TzDevice(cmd, dev_id, parent), @@ -66,6 +65,7 @@ std::shared_ptr TzEvk2Gen41::build(std::shared_ptr cmd, uint32_t dev_id) { return (cmd->read_device_register(dev_id, 0x800)[0] == SYSTEM_EVK2_GEN41); } + static TzRegisterBuildMethod method("psee,video_gen4.1", TzEvk2Gen41::build, TzEvk2Gen41::can_build); void TzEvk2Gen41::spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config) { diff --git a/hal_psee_plugins/src/devices/gen41/gen41_ll_biases.cpp b/hal_psee_plugins/src/devices/gen41/gen41_ll_biases.cpp index b871b72de..8e4e603b7 100644 --- a/hal_psee_plugins/src/devices/gen41/gen41_ll_biases.cpp +++ b/hal_psee_plugins/src/devices/gen41/gen41_ll_biases.cpp @@ -21,29 +21,7 @@ namespace Metavision { static constexpr uint32_t BIAS_CONF = 0x11A10000; -class Gen41LLBias : public LL_Bias_Info { -public: - Gen41LLBias(int min_recommended_value, int max_recommended_value, bool modifiable, std::string register_name, - const std::string &description, const std::string &category) : - LL_Bias_Info(0x00, 0xFF, min_recommended_value, max_recommended_value, description, modifiable, category) { - register_name_ = register_name; - } - - ~Gen41LLBias() {} - const std::string &get_register_name() const { - return register_name_; - } - -private: - std::string register_name_; -}; - -std::map &get_gen41_biases_map() { - static std::map biases_map_; - return biases_map_; -} - -uint32_t get_gen41_bias_encoding(const Gen41LLBias &bias, int bias_value, bool saturate_value) { +uint32_t get_gen41_bias_encoding(const Gen41_LL_Biases::Gen41LLBias &bias, int bias_value, bool saturate_value) { if (saturate_value) { if (bias_value < 0) { bias_value = 0; @@ -153,4 +131,12 @@ const std::shared_ptr &Gen41_LL_Biases::get_hw_register() const { return i_hw_register_; } +std::map &Gen41_LL_Biases::get_gen41_biases_map() { + return biases_map_; +} + +const std::map &Gen41_LL_Biases::get_gen41_biases_map() const { + return biases_map_; +} + } // namespace Metavision diff --git a/hal_psee_plugins/src/devices/gen41/gen41_tz_device.cpp b/hal_psee_plugins/src/devices/gen41/gen41_tz_device.cpp index 455cc1543..bb252ece6 100644 --- a/hal_psee_plugins/src/devices/gen41/gen41_tz_device.cpp +++ b/hal_psee_plugins/src/devices/gen41/gen41_tz_device.cpp @@ -42,10 +42,9 @@ using vfield = std::map; namespace Metavision { -namespace { -std::string ROOT_PREFIX = "PSEE/GEN41/"; -std::string SENSOR_PREFIX = ""; -} // namespace + +std::string TzGen41::ROOT_PREFIX = "PSEE/GEN41/"; +std::string TzGen41::SENSOR_PREFIX = ""; TzGen41::TzGen41(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent) : TzDevice(cmd, dev_id, parent), @@ -65,6 +64,7 @@ std::shared_ptr TzGen41::build(std::shared_ptr c return nullptr; } } + static TzRegisterBuildMethod method("psee,ccam5_gen41", TzGen41::build, TzGen41::can_build); bool TzGen41::can_build(std::shared_ptr cmd, uint32_t dev_id) { diff --git a/hal_psee_plugins/src/devices/genx320/CMakeLists.txt b/hal_psee_plugins/src/devices/genx320/CMakeLists.txt index 3cc2a92a0..54f9db68f 100644 --- a/hal_psee_plugins/src/devices/genx320/CMakeLists.txt +++ b/hal_psee_plugins/src/devices/genx320/CMakeLists.txt @@ -7,10 +7,6 @@ # 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. -if(ANDROID) - return() -endif(ANDROID) - target_sources(metavision_psee_hw_layer_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/genx320_tz_trigger_event.cpp ${CMAKE_CURRENT_SOURCE_DIR}/genx320_roi_driver.cpp diff --git a/hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp b/hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp index 9d7fbb8fd..4e69ed423 100644 --- a/hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp +++ b/hal_psee_plugins/src/devices/genx320/genx320_nfl_interface.cpp @@ -24,20 +24,6 @@ bool GenX320NflInterface::is_enabled() const { return driver_->is_enabled(); } -bool GenX320NflInterface::set_event_rate_threshold(uint32_t threshold_Kev_s) { - auto thres_ev_s = threshold_Kev_s * 1000; - auto thres_max = driver_->get_max_supported_thresholds(); - bool valid = driver_->set_thresholds( - {thres_ev_s, thres_ev_s + 10000, thres_max.upper_bound_start, thres_max.upper_bound_stop}); - - return valid; -} - -uint32_t GenX320NflInterface::get_event_rate_threshold() const { - auto thres_ev_s = driver_->get_thresholds().lower_bound_start; - return std::round(thres_ev_s / 1000.0); -} - I_EventRateActivityFilterModule::thresholds GenX320NflInterface::is_thresholds_supported() const { return driver_->is_thresholds_supported(); } diff --git a/hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp b/hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp index 94f2e75e3..a26895d77 100644 --- a/hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp +++ b/hal_psee_plugins/src/devices/genx320/genx320_roi_driver.cpp @@ -143,8 +143,12 @@ void GenX320RoiDriver::Grid::set_vector(const unsigned int &vector_id, const uns } std::filesystem::path GenX320RoiDriver::default_calibration_path() { +#ifndef __ANDROID__ static auto calib_path = std::filesystem::path(ResourcesFolder::get_user_path()) / "active_pixel_calib.txt"; return calib_path; +#else + throw HalException(HalErrorCode::OperationNotImplemented); +#endif } GenX320RoiDriver::GenX320RoiDriver(int width, int height, const std::shared_ptr ®map, diff --git a/hal_psee_plugins/src/devices/imx636/imx636_evk2_tz_device.cpp b/hal_psee_plugins/src/devices/imx636/imx636_evk2_tz_device.cpp index 1039bda99..de7530d98 100644 --- a/hal_psee_plugins/src/devices/imx636/imx636_evk2_tz_device.cpp +++ b/hal_psee_plugins/src/devices/imx636/imx636_evk2_tz_device.cpp @@ -37,10 +37,9 @@ #include "utils/psee_hal_utils.h" namespace Metavision { -namespace { -std::string ROOT_PREFIX = "PSEE/"; -std::string SENSOR_PREFIX = "SENSOR_IF/IMX636/"; -} // namespace + +std::string TzEvk2Imx636::ROOT_PREFIX = "PSEE/"; +std::string TzEvk2Imx636::SENSOR_PREFIX = "SENSOR_IF/IMX636/"; TzEvk2Imx636::TzEvk2Imx636(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent) : @@ -67,6 +66,7 @@ std::shared_ptr TzEvk2Imx636::build(std::shared_ptr cmd, uint32_t dev_id) { return (cmd->read_device_register(dev_id, 0x800)[0] == SYSTEM_EVK2_IMX636); } + static TzRegisterBuildMethod method("psee,video_imx636", TzEvk2Imx636::build, TzEvk2Imx636::can_build); void TzEvk2Imx636::spawn_facilities(DeviceBuilder &device_builder, const DeviceConfig &device_config) { diff --git a/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp b/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp index 930912406..f214d7c61 100644 --- a/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp +++ b/hal_psee_plugins/src/devices/imx636/imx636_tz_device.cpp @@ -40,10 +40,9 @@ using vfield = std::map; namespace Metavision { -namespace { -std::string ROOT_PREFIX = "PSEE/IMX636/"; -std::string SENSOR_PREFIX = ""; -} // namespace + +std::string TzImx636::ROOT_PREFIX = "PSEE/IMX636/"; +std::string TzImx636::SENSOR_PREFIX = ""; TzImx636::TzImx636(std::shared_ptr cmd, uint32_t dev_id, std::shared_ptr parent) : TzDevice(cmd, dev_id, parent), @@ -64,6 +63,7 @@ std::shared_ptr TzImx636::build(std::shared_ptr the pulse width is set to 1 us which is the default behavior (decided by PO). - * -> the period is set to 100 us by default which is the default behavior (decided by PO). - * - * In this interface, the pulse width remains constant. In term of code logic, - * there is nothing to do as this value is set by default and never changes. - */ +using namespace Metavision; -namespace Metavision { +static TzRegisterBuildMethod method("fsl,imx8mq-csi", TzImx8Device::build); -TriggerOut::TriggerOut(I_TriggerOut *i_trigger_out) : pimpl_(i_trigger_out) {} +TzImx8Device::TzImx8Device(std::shared_ptr cmd, uint32_t dev_id, + std::shared_ptr parent) : + TzUnknownDevice(cmd, dev_id, parent) {} -TriggerOut::~TriggerOut() = default; - -void TriggerOut::set_pulse_period(uint32_t period_us) { - pimpl_->set_period(period_us); +// TzMainDevice +bool TzImx8Device::set_mode_standalone() { + return true; } -void TriggerOut::set_duty_cycle(double period_ratio) { - pimpl_->set_duty_cycle(period_ratio); +bool TzImx8Device::set_mode_master() { + return false; } -void TriggerOut::enable() { - pimpl_->enable(); +bool TzImx8Device::set_mode_slave() { + return false; } -void TriggerOut::disable() { - pimpl_->disable(); +I_CameraSynchronization::SyncMode TzImx8Device::get_mode() const { + return I_CameraSynchronization::SyncMode::STANDALONE; } -I_TriggerOut *TriggerOut::get_facility() const { - return pimpl_; +I_HW_Identification::SensorInfo TzImx8Device::get_sensor_info() { + return I_HW_Identification::SensorInfo{}; } -} // namespace Metavision +std::shared_ptr TzImx8Device::build(std::shared_ptr cmd, uint32_t id, + std::shared_ptr parent) { + return std::make_shared(cmd, id, parent); +} diff --git a/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp b/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp index 09354cc54..71247742e 100644 --- a/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp +++ b/hal_psee_plugins/src/devices/psee-video/tz_psee_video_build.cpp @@ -25,6 +25,7 @@ std::shared_ptr TzPseeVideo::build(std::shared_ptr cmd, uint32_t dev_id, s TzDevice::~TzDevice() {} void TzDevice::initialize() { + MV_HAL_LOG_TRACE() << "TreuzellDevice - init"; TzGenericCtrlFrame enable(TZ_PROP_DEVICE_ENABLE | TZ_WRITE_FLAG); enable.push_back32(tzID); enable.push_back32(1); @@ -41,6 +42,7 @@ void TzDevice::initialize() { } void TzDevice::destroy() { + MV_HAL_LOG_TRACE() << "TreuzellDevice - Destroy"; TzGenericCtrlFrame disable(TZ_PROP_DEVICE_ENABLE | TZ_WRITE_FLAG); disable.push_back32(tzID); disable.push_back32(0); @@ -48,6 +50,7 @@ void TzDevice::destroy() { } void TzDevice::start() { + MV_HAL_LOG_TRACE() << "TreuzellDevice - Start"; TzGenericCtrlFrame start(TZ_PROP_DEVICE_STREAM | TZ_WRITE_FLAG); start.push_back32(tzID); start.push_back32(1); @@ -55,6 +58,7 @@ void TzDevice::start() { } void TzDevice::stop() { + MV_HAL_LOG_TRACE() << "TreuzellDevice - Stop"; TzGenericCtrlFrame stop(TZ_PROP_DEVICE_STREAM | TZ_WRITE_FLAG); stop.push_back32(tzID); stop.push_back32(0); diff --git a/hal_psee_plugins/src/devices/treuzell/tz_device_builder.cpp b/hal_psee_plugins/src/devices/treuzell/tz_device_builder.cpp index 55ff70715..7ca3420fa 100644 --- a/hal_psee_plugins/src/devices/treuzell/tz_device_builder.cpp +++ b/hal_psee_plugins/src/devices/treuzell/tz_device_builder.cpp @@ -10,18 +10,17 @@ **********************************************************************************************************************/ #include "metavision/hal/facilities/i_events_stream.h" - -#include "metavision/psee_hw_layer/devices/treuzell/tz_device.h" #include "metavision/psee_hw_layer/boards/treuzell/tz_control_frame.h" -#include "metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h" -#include "boards/treuzell/treuzell_command_definition.h" #include "metavision/psee_hw_layer/boards/treuzell/tz_hw_identification.h" -#include "metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h" +#include "metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h" +#include "metavision/psee_hw_layer/devices/treuzell/tz_device.h" #include "metavision/psee_hw_layer/facilities/tz_camera_synchronization.h" -#include "metavision/psee_hw_layer/facilities/tz_monitoring.h" #include "metavision/psee_hw_layer/facilities/tz_hw_register.h" +#include "metavision/psee_hw_layer/facilities/tz_monitoring.h" #include "metavision/psee_hw_layer/utils/psee_format.h" #include "metavision/psee_hw_layer/utils/tz_device_control.h" + +#include "boards/treuzell/treuzell_command_definition.h" #include "devices/treuzell/tz_device_builder.h" #include "utils/make_decoder.h" @@ -148,7 +147,7 @@ bool TzDeviceBuilder::build_devices(std::shared_ptr cmd, auto format = devices[0]->get_output_format(); auto decoder = make_decoder(device_builder, format, raw_size_bytes, false); device_builder.add_facility(std::make_unique( - cmd->build_data_transfer(raw_size_bytes), hw_identification, decoder, ctrl)); + cmd->build_raw_data_producer(raw_size_bytes), hw_identification, decoder, ctrl)); } catch (std::exception &e) { MV_HAL_LOG_WARNING() << "System can't stream:" << e.what(); } std::shared_ptr temp = get_provider(devices); diff --git a/hal_psee_plugins/src/devices/v4l2/CMakeLists.txt b/hal_psee_plugins/src/devices/v4l2/CMakeLists.txt index 8d9c49372..7ab690b58 100644 --- a/hal_psee_plugins/src/devices/v4l2/CMakeLists.txt +++ b/hal_psee_plugins/src/devices/v4l2/CMakeLists.txt @@ -10,7 +10,7 @@ if(NOT HAS_V4L2 OR ANDROID) return() endif() - + target_sources(metavision_psee_hw_layer_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/v4l2_device_builder.cpp ) diff --git a/hal_psee_plugins/src/devices/v4l2/v4l2_device_builder.cpp b/hal_psee_plugins/src/devices/v4l2/v4l2_device_builder.cpp index fd6e3d509..697b97ad4 100644 --- a/hal_psee_plugins/src/devices/v4l2/v4l2_device_builder.cpp +++ b/hal_psee_plugins/src/devices/v4l2/v4l2_device_builder.cpp @@ -13,7 +13,6 @@ #include "metavision/psee_hw_layer/boards/treuzell/board_command.h" #include "metavision/psee_hw_layer/boards/v4l2/v4l2_board_command.h" -#include "metavision/psee_hw_layer/boards/utils/psee_libusb_data_transfer.h" #include "metavision/psee_hw_layer/utils/psee_format.h" #include "metavision/psee_hw_layer/utils/register_map.h" #include "metavision/psee_hw_layer/facilities/psee_hw_register.h" @@ -51,6 +50,9 @@ #include "utils/make_decoder.h" #include "devices/common/sensor_descriptor.h" +#include +#include + namespace Metavision { static bool match(std::shared_ptr cmd, std::vector match_list) { @@ -125,6 +127,16 @@ static SensorDescriptor *get_sensor_descriptor(std::shared_ptr cmd {320, 0, "GenX320"}, "EVT21;height=320;width=320", }, + { + GenX320ESRegisterMap, + GenX320ESRegisterMapSize, + genx320_spawn_facilities, + { + {.addr = 0x14, .value = 0xb0602003, .mask = 0xFFFFFFFF}, + }, + {320, 1, "GenX320MP"}, + "EVT21;height=320;width=320", + }, { Imx636RegisterMap, Imx636RegisterMapSize, @@ -175,7 +187,52 @@ bool V4L2DeviceBuilder::build_device(std::shared_ptr cmd, DeviceBu auto v4l2cmd = std::dynamic_pointer_cast(cmd); - auto ctrl = v4l2cmd->get_device_control(); + auto ctrl = v4l2cmd->get_device_control(); + { + // This plugin code does not set format yet, it shall be set before starting Metavision SDK, but several values + // are possible. Update sensor information accordingly. + struct v4l2_format fmt { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE + }; + + if (ioctl(ctrl->get_fd(), VIDIOC_G_FMT, &fmt)) + raise_error("VIDIOC_G_FMT failed"); + + switch (fmt.fmt.pix.pixelformat) { + case v4l2_fourcc('P', 'S', 'E', 'E'): { + StreamFormat format("EVT2"); + format["width"] = std::to_string(fmt.fmt.pix.width); + format["height"] = std::to_string(fmt.fmt.pix.height); + sensor_descriptor->encoding_format = format.to_string(); + break; + } + case v4l2_fourcc('P', 'S', 'E', '1'): { + StreamFormat format("EVT21"); + format["endianness"] = "legacy"; + format["width"] = std::to_string(fmt.fmt.pix.width); + format["height"] = std::to_string(fmt.fmt.pix.height); + sensor_descriptor->encoding_format = format.to_string(); + break; + } + case v4l2_fourcc('P', 'S', 'E', '2'): { + StreamFormat format("EVT21"); + format["width"] = std::to_string(fmt.fmt.pix.width); + format["height"] = std::to_string(fmt.fmt.pix.height); + sensor_descriptor->encoding_format = format.to_string(); + break; + } + case v4l2_fourcc('P', 'S', 'E', '3'): { + StreamFormat format("EVT3"); + format["width"] = std::to_string(fmt.fmt.pix.width); + format["height"] = std::to_string(fmt.fmt.pix.height); + sensor_descriptor->encoding_format = format.to_string(); + break; + } + default: + // Possibly hacky configuration to get things working. Assume default format + break; + } + } auto cap = ctrl->get_capability(); auto software_info = device_builder.get_plugin_software_info(); auto hw_identification = @@ -185,7 +242,7 @@ bool V4L2DeviceBuilder::build_device(std::shared_ptr cmd, DeviceBu size_t raw_size_bytes = 0; auto format = StreamFormat(hw_identification->get_current_data_encoding_format()); auto decoder = make_decoder(device_builder, format, raw_size_bytes, false); - device_builder.add_facility(std::make_unique(v4l2cmd->build_data_transfer(raw_size_bytes), + device_builder.add_facility(std::make_unique(v4l2cmd->build_raw_data_producer(raw_size_bytes), hw_identification, decoder, ctrl)); } catch (std::exception &e) { MV_HAL_LOG_WARNING() << "System can't stream:" << e.what(); } diff --git a/hal_psee_plugins/src/plugin/psee_universal.cpp b/hal_psee_plugins/src/plugin/psee_universal.cpp index 1c0afc17c..05b5c32b9 100644 --- a/hal_psee_plugins/src/plugin/psee_universal.cpp +++ b/hal_psee_plugins/src/plugin/psee_universal.cpp @@ -8,41 +8,60 @@ * 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. * **********************************************************************************************************************/ -#if !defined(__ANDROID__) || defined(ANDROID_USES_LIBUSB) -#include "boards/fx3/fx3_camera_discovery.h" -#include "boards/treuzell/tz_camera_discovery.h" -#include "boards/v4l2/v4l2_camera_discovery.h" -#include "metavision/psee_hw_layer/boards/treuzell/tz_libusb_board_command.h" -#endif -#include "boards/rawfile/psee_file_discovery.h" -#include "devices/utils/device_system_id.h" +#include + #include "metavision/hal/plugin/plugin.h" #include "metavision/hal/plugin/plugin_entrypoint.h" -#include "metavision/hal/utils/hal_software_info.h" #include "plugin/psee_plugin.h" -void initialize_plugin(void *plugin_ptr) { - using namespace Metavision; +using namespace Metavision; - Plugin &plugin = plugin_cast(plugin_ptr); - initialize_psee_plugin(plugin); +struct PluginDiscovery { + static std::vector> plugin_discovery; + PluginDiscovery(std::function f) { + plugin_discovery.push_back(f); + } + + static void discover(Plugin &plugin) { + for (const auto &f : plugin_discovery) { + f(plugin); + } + } +}; +std::vector> PluginDiscovery::plugin_discovery; #if !defined(__ANDROID__) || defined(ANDROID_USES_LIBUSB) +#include "boards/fx3/fx3_camera_discovery.h" +#include "boards/treuzell/tz_camera_discovery.h" +PluginDiscovery register_treuzell([](Plugin &plugin) { auto tz_cam_discovery = std::make_unique(); // Register the known USB vendor ID, with the subclass used for Treuzell tz_cam_discovery->add_usb_id(0x03fd, 0x5832, 0x19); tz_cam_discovery->add_usb_id(0x03fd, 0x5832, 0x0); tz_cam_discovery->add_usb_id(0x04b4, 0x00f4, 0x19); tz_cam_discovery->add_usb_id(0x04b4, 0x00f5, 0x19); + tz_cam_discovery->add_usb_id(0x1FC9, 0x5838, 0x19); // Register live camera discoveries auto &fx3_disc = plugin.add_camera_discovery(std::make_unique()); auto &tz_disc = plugin.add_camera_discovery(std::move(tz_cam_discovery)); -#ifdef HAS_V4L2 +}); +#endif // !defined(__ANDROID__) || defined(ANDROID_USES_LIBUSB) + +#if !defined(__ANDROID__) && defined(HAS_V4L2) +#include "boards/v4l2/v4l2_camera_discovery.h" +PluginDiscovery register_v4l2([](Plugin &plugin) { auto &v4l2_disc = plugin.add_camera_discovery(std::make_unique()); +}); #endif // HAS_V4L2 -#endif // !defined(__ANDROID__) - +#include "boards/rawfile/psee_file_discovery.h" +PluginDiscovery register_psee_file([](Plugin &plugin) { auto &file_disc = plugin.add_file_discovery(std::make_unique()); +}); + +void initialize_plugin(void *plugin_ptr) { + Plugin &plugin = plugin_cast(plugin_ptr); + initialize_psee_plugin(plugin); + PluginDiscovery::discover(plugin); } diff --git a/hal_psee_plugins/src/utils/make_decoder.cpp b/hal_psee_plugins/src/utils/make_decoder.cpp index 9f8cf16fa..5fb649454 100644 --- a/hal_psee_plugins/src/utils/make_decoder.cpp +++ b/hal_psee_plugins/src/utils/make_decoder.cpp @@ -23,6 +23,7 @@ #include "metavision/hal/decoders/evt2/evt2_decoder.h" #include "metavision/hal/decoders/evt21/evt21_decoder.h" #include "metavision/hal/decoders/evt3/evt3_decoder.h" +#include "metavision/hal/decoders/evt4/evt4_decoder.h" #include "metavision/hal/decoders/ehc/ehc_decoder.h" #include "metavision/hal/decoders/mtr/mtr_decoder.h" #include "metavision/hal/utils/hal_log.h" @@ -61,13 +62,23 @@ static std::pair get_pixel_layout(const std::string &layout_ } std::shared_ptr make_decoder(DeviceBuilder &device_builder, const StreamFormat &format, - size_t &raw_size_bytes, bool do_time_shifting) { + size_t &raw_size_bytes, bool do_time_shifting, const Metavision::DeviceConfig &config) { std::shared_ptr decoder; std::shared_ptr frame_decoder; auto i_geometry = device_builder.add_facility(format.geometry()); raw_size_bytes = 0; - if (format.name() == "EVT3") { + if (format.name() == "EVT4") { + auto cd_decoder = device_builder.add_facility(std::make_unique>()); + auto ext_trig_decoder = device_builder.add_facility(std::make_unique>()); + auto erc_count_ev_decoder = device_builder.add_facility(std::make_unique>()); + + decoder = device_builder.add_facility(make_evt4_decoder(do_time_shifting, i_geometry->get_width(), + i_geometry->get_height(), cd_decoder, ext_trig_decoder, + erc_count_ev_decoder)); + + raw_size_bytes = decoder->get_raw_event_size_bytes(); + } else if (format.name() == "EVT3") { auto cd_decoder = device_builder.add_facility(std::make_unique>()); auto ext_trig_decoder = device_builder.add_facility(std::make_unique>()); auto erc_count_ev_decoder = device_builder.add_facility(std::make_unique>()); @@ -85,19 +96,36 @@ std::shared_ptr make_decoder(DeviceBuilder &device_builde device_builder.add_facility(std::make_unique(do_time_shifting, cd_decoder, ext_trig_decoder)); raw_size_bytes = decoder->get_raw_event_size_bytes(); } else if (format.name() == "EVT21") { - auto cd_decoder = device_builder.add_facility(std::make_unique>()); + auto ext_trig_decoder = device_builder.add_facility(std::make_unique>()); auto erc_count_ev_decoder = device_builder.add_facility(std::make_unique>()); auto endianness = format["endianness"]; - if (endianness == "legacy") { - decoder = device_builder.add_facility(std::make_unique( - do_time_shifting, cd_decoder, ext_trig_decoder, erc_count_ev_decoder)); - } else { + auto evt21_keep_vectors = config.get("evt21_keep_vectors"); + + if (evt21_keep_vectors){ + if (endianness != "little"){ + throw std::invalid_argument("Value for option 'endianness` not supported when option `evt21_keep_vectors=true` is set"); + } + + auto cd_vector_decoder = device_builder.add_facility(std::make_unique>()); + decoder = device_builder.add_facility( - std::make_unique(do_time_shifting, cd_decoder, ext_trig_decoder, erc_count_ev_decoder)); + std::make_unique(do_time_shifting, cd_vector_decoder, ext_trig_decoder, erc_count_ev_decoder)); + + }else{ + auto cd_decoder = device_builder.add_facility(std::make_unique>()); + + if (endianness == "legacy") { + decoder = device_builder.add_facility(std::make_unique( + do_time_shifting, cd_decoder, ext_trig_decoder, erc_count_ev_decoder)); + } else { + decoder = device_builder.add_facility( + std::make_unique(do_time_shifting, cd_decoder, ext_trig_decoder, erc_count_ev_decoder)); + } } raw_size_bytes = decoder->get_raw_event_size_bytes(); + } else if (format.name() == "HISTO3D") { auto pixel_layout = get_pixel_layout(format["pixellayout"]); int pixel_bytes; @@ -130,7 +158,7 @@ std::shared_ptr make_decoder(DeviceBuilder &device_builde } else if (format.name().rfind("MTR") == 0) { auto mtr_decoder = mtr_decoder_from_format(*i_geometry, format.name()); if (mtr_decoder) { - frame_decoder = device_builder.add_facility(std::move(mtr_decoder)); + frame_decoder = device_builder.add_facility(std::move(mtr_decoder)); raw_size_bytes = frame_decoder->get_raw_event_size_bytes(); } } diff --git a/hal_psee_plugins/test/CMakeLists.txt b/hal_psee_plugins/test/CMakeLists.txt index 9981e0493..813a081be 100644 --- a/hal_psee_plugins/test/CMakeLists.txt +++ b/hal_psee_plugins/test/CMakeLists.txt @@ -11,7 +11,7 @@ set(metavision_hal_psee_plugins_tests_src ${CMAKE_CURRENT_SOURCE_DIR}/device_discovery_psee_plugins_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/event_encoders_gtest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/file_data_transfer_gtest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/file_raw_data_producer_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/file_events_stream_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gen31_event_rate_noise_filter_module_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/i_events_stream_gtest.cpp @@ -31,7 +31,6 @@ target_link_libraries(gtest_metavision_hal_psee_plugins metavision_hal_discovery metavision_hal_psee_plugin_obj MetavisionUtils::gtest-main - Boost::filesystem ) # Need to set RPATH to be able to run test either from build binaries or from a .deb install @@ -57,7 +56,6 @@ target_link_libraries(gtest_metavision_hal_psee_hw_layer metavision_hal_discovery Metavision::PSEEHWLayer MetavisionUtils::gtest-main - Boost::filesystem ) # Need to set RPATH to be able to run test either from build binaries or from a .deb install diff --git a/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp b/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp index 7f735d630..4bd69450a 100644 --- a/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp +++ b/hal_psee_plugins/test/device_discovery_psee_plugins_gtest.cpp @@ -215,7 +215,6 @@ TEST_F(DeviceDiscoveryPseePlugins_GTest, open_rawfile_success_with_supported_sys // Check hw identification I_HW_Identification *hw_id = device->get_facility(); ASSERT_NE(nullptr, hw_id); - ASSERT_EQ(system_id, hw_id->get_system_id()); ASSERT_EQ("File", hw_id->get_connection_type()); // Check decoder @@ -578,11 +577,8 @@ TEST_WITH_CAMERA(DeviceDiscoveryRepositoryNoF_GTest, open_camera_build_gen31, ASSERT_NE(nullptr, device->get_facility()); ASSERT_EQ(VGAGeometry::width_, geometry->get_width()); ASSERT_EQ(VGAGeometry::height_, geometry->get_height()); - if (hw_id_->get_system_id() == 0x28) { - ASSERT_EQ(2, decoder->get_raw_event_size_bytes()); - } else { - ASSERT_EQ(4, decoder->get_raw_event_size_bytes()); - } + // The format may be either evt 2.0 or 3.0, this information was already used to spawn + // a decoder, and it worked, there is no point re-checking it } TEST_WITH_CAMERA(DeviceDiscoveryRepositoryNoF_GTest, open_camera_build_gen4, diff --git a/hal_psee_plugins/test/file_events_stream_gtest.cpp b/hal_psee_plugins/test/file_events_stream_gtest.cpp index 13b979358..111e93fa9 100644 --- a/hal_psee_plugins/test/file_events_stream_gtest.cpp +++ b/hal_psee_plugins/test/file_events_stream_gtest.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include "metavision/utils/gtest/gtest_with_tmp_dir.h" #include "metavision/sdk/base/events/event_cd.h" @@ -227,14 +226,13 @@ TEST_F(FileEventsStream_Gtest, reading_all_data) { ASSERT_TRUE(open_and_start_file_events_stream()); std::vector data_read; - long n_bytes_polled; while (file_events_stream_->wait_next_buffer() > 0) { auto buffer = file_events_stream_->get_latest_raw_data(); - ASSERT_TRUE(buffer->size() == (n_events_to_read_default_ * decoder_->get_raw_event_size_bytes()) || - buffer->size() == (n_events_read_in_last_buffer_ * decoder_->get_raw_event_size_bytes())); - data_read.insert(data_read.end(), reinterpret_cast(buffer->data()), - reinterpret_cast(buffer->data() + buffer->size())); + ASSERT_TRUE(buffer.size() == (n_events_to_read_default_ * decoder_->get_raw_event_size_bytes()) || + buffer.size() == (n_events_read_in_last_buffer_ * decoder_->get_raw_event_size_bytes())); + data_read.insert(data_read.end(), reinterpret_cast(buffer.data()), + reinterpret_cast(buffer.data() + buffer.size())); } ASSERT_EQ(data_ref, data_read); @@ -346,10 +344,10 @@ TEST_F(FileEventsStream_Gtest, rawfile_logging_data_logged_is_data_read) { std::vector data_read; while (file_events_stream_->wait_next_buffer() > 0) { auto buffer = file_events_stream_->get_latest_raw_data(); - ASSERT_TRUE(buffer->size() == n_events_to_read_default_ * decoder_->get_raw_event_size_bytes() || - buffer->size() == n_events_read_in_last_buffer_ * decoder_->get_raw_event_size_bytes()); - data_read.insert(data_read.end(), reinterpret_cast(buffer->data()), - reinterpret_cast(buffer->data() + buffer->size())); + ASSERT_TRUE(buffer.size() == n_events_to_read_default_ * decoder_->get_raw_event_size_bytes() || + buffer.size() == n_events_read_in_last_buffer_ * decoder_->get_raw_event_size_bytes()); + data_read.insert(data_read.end(), reinterpret_cast(buffer.begin()), + reinterpret_cast(buffer.end())); } ASSERT_EQ(data_ref, data_read); @@ -388,10 +386,10 @@ TEST_F(FileEventsStream_Gtest, reading_from_custom_istream) { std::vector data_read; while (file_events_stream_->wait_next_buffer() > 0) { auto buffer = file_events_stream_->get_latest_raw_data(); - ASSERT_TRUE(buffer->size() == n_events_to_read_default_ * decoder_->get_raw_event_size_bytes() || - buffer->size() == n_events_read_in_last_buffer_ * decoder_->get_raw_event_size_bytes()); - data_read.insert(data_read.end(), reinterpret_cast(buffer->data()), - reinterpret_cast(buffer->data() + buffer->size())); + ASSERT_TRUE(buffer.size() == n_events_to_read_default_ * decoder_->get_raw_event_size_bytes() || + buffer.size() == n_events_read_in_last_buffer_ * decoder_->get_raw_event_size_bytes()); + data_read.insert(data_read.end(), reinterpret_cast(buffer.begin()), + reinterpret_cast(buffer.end())); } ASSERT_EQ(data_ref, data_read); diff --git a/hal_psee_plugins/test/file_data_transfer_gtest.cpp b/hal_psee_plugins/test/file_raw_data_producer_gtest.cpp similarity index 85% rename from hal_psee_plugins/test/file_data_transfer_gtest.cpp rename to hal_psee_plugins/test/file_raw_data_producer_gtest.cpp index 5b1e3566d..8510a7b82 100644 --- a/hal_psee_plugins/test/file_data_transfer_gtest.cpp +++ b/hal_psee_plugins/test/file_raw_data_producer_gtest.cpp @@ -14,15 +14,15 @@ #include #include #include -#include +#include "metavision/hal/utils/data_transfer.h" #include "metavision/hal/utils/hal_exception.h" -#include "metavision/hal/utils/file_data_transfer.h" +#include "metavision/hal/utils/file_raw_data_producer.h" #include "metavision/utils/gtest/gtest_with_tmp_dir.h" using namespace Metavision; -class FileDataTransfer_Gtest : public GTestWithTmpDir { +class FileRawDataProducer_Gtest : public GTestWithTmpDir { protected: virtual void SetUp() override { // Create and open the rawfile @@ -80,7 +80,8 @@ class FileDataTransfer_Gtest : public GTestWithTmpDir { config.n_events_to_read_ = raw_events_per_read; config.n_read_buffers_ = read_buffers_count; - file_data_transfer_.reset(new FileDataTransfer(std::move(ifs), raw_event_size_bytes_, config)); + file_raw_data_producer_ = std::make_shared(std::move(ifs), raw_event_size_bytes_, config); + file_data_transfer_ = std::make_unique(file_raw_data_producer_); if (!file_data_transfer_ || !file_data_transfer_) { file_data_transfer_.reset(nullptr); return false; @@ -96,20 +97,21 @@ class FileDataTransfer_Gtest : public GTestWithTmpDir { static constexpr uint32_t read_buffers_count_ = 3; protected: - std::unique_ptr file_data_transfer_; + std::unique_ptr file_data_transfer_; + std::shared_ptr file_raw_data_producer_; std::unique_ptr rawfile_to_log_; std::string rawfile_to_log_path_; std::string rawfile_to_log_from_rawfile_path_; }; -constexpr uint32_t FileDataTransfer_Gtest::raw_event_size_bytes_; -constexpr uint32_t FileDataTransfer_Gtest::read_buffers_count_; -constexpr uint32_t FileDataTransfer_Gtest::bytes_per_written_buffer_default_; -constexpr uint32_t FileDataTransfer_Gtest::n_buffers_default_; -constexpr uint32_t FileDataTransfer_Gtest::raw_events_per_read_default_; +constexpr uint32_t FileRawDataProducer_Gtest::raw_event_size_bytes_; +constexpr uint32_t FileRawDataProducer_Gtest::read_buffers_count_; +constexpr uint32_t FileRawDataProducer_Gtest::bytes_per_written_buffer_default_; +constexpr uint32_t FileRawDataProducer_Gtest::n_buffers_default_; +constexpr uint32_t FileRawDataProducer_Gtest::raw_events_per_read_default_; -TEST_F(FileDataTransfer_Gtest, file_does_not_exists) { +TEST_F(FileRawDataProducer_Gtest, file_does_not_exists) { //////////////////////////////////////////////////////////////////////////////// // PURPOSE // Check that you can't read a file that doesn't exist @@ -117,7 +119,7 @@ TEST_F(FileDataTransfer_Gtest, file_does_not_exists) { ASSERT_EQ(nullptr, file_data_transfer_.get()); } -TEST_F(FileDataTransfer_Gtest, reading_integrity) { +TEST_F(FileRawDataProducer_Gtest, reading_integrity) { // GIVEN a RAW file with known content auto data_ref = write_ref_data(); @@ -126,8 +128,9 @@ TEST_F(FileDataTransfer_Gtest, reading_integrity) { // AND WHEN copying the read data in a buffer std::vector data_read; + file_data_transfer_->add_new_buffer_callback( - [&](auto &buffer) { data_read.insert(data_read.end(), buffer->cbegin(), buffer->cend()); }); + [&](auto &buffer) { data_read.insert(data_read.end(), buffer.cbegin(), buffer.cend()); }); // AND WHEN setting a callback on stop std::atomic stopped{false}; @@ -143,7 +146,7 @@ TEST_F(FileDataTransfer_Gtest, reading_integrity) { ASSERT_EQ(data_ref, data_read); } -TEST_F(FileDataTransfer_Gtest, memory_usage) { +TEST_F(FileRawDataProducer_Gtest, memory_usage) { // GIVEN a RAW file with known content auto data_ref = write_ref_data(); @@ -159,7 +162,7 @@ TEST_F(FileDataTransfer_Gtest, memory_usage) { std::lock_guard lock(buffers_safety); buffers.push_back(buffer); // THEN each buffer contains at most the requested RAW events to read count in bytes - ASSERT_LE(buffer->size(), raw_events_per_read_default_ * raw_event_size_bytes_); + ASSERT_LE(buffer.size(), raw_events_per_read_default_ * raw_event_size_bytes_); }); // AND WHEN setting a callback on stop @@ -182,7 +185,7 @@ TEST_F(FileDataTransfer_Gtest, memory_usage) { ++trials; if (trials >= max_trials) { for (auto &buffer : buffers) { - data_read.insert(data_read.end(), buffer->cbegin(), buffer->cend()); + data_read.insert(data_read.end(), buffer.cbegin(), buffer.cend()); } // release the buffers so that the object pool can reuse them buffers.clear(); @@ -193,7 +196,7 @@ TEST_F(FileDataTransfer_Gtest, memory_usage) { ASSERT_EQ(data_ref, data_read); } -TEST_F(FileDataTransfer_Gtest, invalid_parameters) { +TEST_F(FileRawDataProducer_Gtest, invalid_parameters) { // GIVEN a RAW file with known content auto data_ref = write_ref_data(); @@ -202,7 +205,7 @@ TEST_F(FileDataTransfer_Gtest, invalid_parameters) { ASSERT_THROW(open_file_data_transfer(0), HalException); } -TEST_F(FileDataTransfer_Gtest, remove_calback) { +TEST_F(FileRawDataProducer_Gtest, remove_calback) { // GIVEN a RAW file with known content auto data_ref = write_ref_data(); diff --git a/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp b/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp index 2c69e0f2c..f4618e817 100644 --- a/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp +++ b/hal_psee_plugins/test/gen31_event_rate_noise_filter_module_gtest.cpp @@ -18,7 +18,6 @@ #include "metavision/hal/device/device_discovery.h" #include "metavision/hal/device/device.h" #include "metavision/hal/utils/hal_exception.h" -#include "metavision/hal/utils/detail/warning_supression.h" #include "metavision/hal/facilities/i_hw_identification.h" #include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" #include "metavision/hal/facilities/i_events_stream.h" @@ -99,35 +98,3 @@ TEST_F_WITH_CAMERA(Gen31EventRateNoiseFilterModule_GTest, i_event_rate_gen31_eve ASSERT_FALSE(ev_rate_->set_thresholds({greater_out_of_range_time_window, 0, 0, 0})); ASSERT_EQ(currently_time_window_new, ev_rate_->get_thresholds().lower_bound_start); } - -TEST_F_WITH_CAMERA(Gen31EventRateNoiseFilterModule_GTest, i_event_rate_gen31_event_rate_threshold_deprecated, - camera_params(camera_param().integrator("Prophesee").generation("3.1"))) { - open(); - - constexpr uint32_t lower_out_of_range_time_window = 0; - constexpr uint32_t greater_out_of_range_time_window = max_event_rate_threshold_kev_s_ + 1; - - // Compute expected error as we converting kev/s in ev/us and the latter one is rounded - uint32_t expected_max_error_kev_s = std::abs(in_range_event_rate_threshold_kev_s_ - - 1000 * std::round(in_range_event_rate_threshold_kev_s_ / 1000.)); - - // GIVEN Valid values for the event rate threshold - // WHEN setting each of them - // THEN The value set in the sensor is the correct one - SUPRESS_DEPRECATION_WARNING( - ASSERT_TRUE(ev_rate_->set_event_rate_threshold(min_event_rate_threshold_kev_s_)); - ASSERT_NEAR(min_event_rate_threshold_kev_s_, ev_rate_->get_event_rate_threshold(), expected_max_error_kev_s); - ASSERT_TRUE(ev_rate_->set_event_rate_threshold(max_event_rate_threshold_kev_s_)); - ASSERT_NEAR(max_event_rate_threshold_kev_s_, ev_rate_->get_event_rate_threshold(), expected_max_error_kev_s); - ASSERT_TRUE(ev_rate_->set_event_rate_threshold(in_range_event_rate_threshold_kev_s_)); ASSERT_NEAR( - in_range_event_rate_threshold_kev_s_, ev_rate_->get_event_rate_threshold(), expected_max_error_kev_s);); - - // GIVEN Invalid values for the event rate threshold - // WHEN setting each of them - // THEN The value set in the sensor is not changed (equal to the last set) - SUPRESS_DEPRECATION_WARNING(const auto currently_time_window_deprecated = ev_rate_->get_event_rate_threshold(); - ASSERT_FALSE(ev_rate_->set_event_rate_threshold(lower_out_of_range_time_window)); - ASSERT_EQ(currently_time_window_deprecated, ev_rate_->get_event_rate_threshold()); - ASSERT_FALSE(ev_rate_->set_event_rate_threshold(greater_out_of_range_time_window)); - ASSERT_EQ(currently_time_window_deprecated, ev_rate_->get_event_rate_threshold());); -} diff --git a/hal_psee_plugins/test/i_events_stream_gtest.cpp b/hal_psee_plugins/test/i_events_stream_gtest.cpp index 1c78d8453..ad7c30a37 100644 --- a/hal_psee_plugins/test/i_events_stream_gtest.cpp +++ b/hal_psee_plugins/test/i_events_stream_gtest.cpp @@ -9,6 +9,9 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include +#include +#include #include #include @@ -19,7 +22,6 @@ #include "metavision/hal/facilities/i_event_decoder.h" #include "metavision/hal/facilities/i_events_stream.h" #include "metavision/hal/utils/data_transfer.h" -#include "metavision/hal/utils/file_data_transfer.h" #include "metavision/hal/device/device.h" #include "metavision/hal/device/device_discovery.h" #include "metavision/hal/utils/device_builder.h" @@ -44,9 +46,6 @@ class MockHWIdentification : public I_HW_Identification { virtual std::string get_serial() const override { return dummy_serial_; } - virtual long get_system_id() const override { - return system_id_; - } virtual SensorInfo get_sensor_info() const override { return SensorInfo(); } @@ -73,6 +72,7 @@ class MockHWIdentification : public I_HW_Identification { format["width"] = std::to_string(VGAGeometry().get_width()); format["height"] = std::to_string(VGAGeometry().get_height()); PseeRawFileHeader header(*this, format); + header.set_system_id(system_id_); header.set_sub_system_id(dummy_sub_system_id_); header.set_field(dummy_custom_key_, dummy_custom_value_); return header; @@ -101,28 +101,17 @@ const std::string MockHWIdentification::dummy_camera_integrator_name_ = "camera_ const std::string MockHWIdentification::dummy_custom_key_ = "custom"; const std::string MockHWIdentification::dummy_custom_value_ = "field"; -class MockDataTransfer : public DataTransfer { +class MockRawDataProducer : public DataTransfer::RawDataProducer { public: - MockDataTransfer() : DataTransfer(4) {} - - void trigger_transfer(const std::vector &data) { - buffer_->clear(); - buffer_->insert(buffer_->end(), data.cbegin(), data.cend()); - transfer_data(buffer_); - } + MockRawDataProducer() {} private: - void start_impl(BufferPtr buffer) final { - buffer_ = buffer; - } - - void run_impl() final { - while (!should_stop()) { + void start_impl() final {} + void run_impl(const DataTransfer &data_transfer) final { + while (!data_transfer.should_stop()) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } - - BufferPtr buffer_; }; class I_EventsStream_GTest : public GTestWithTmpDir { @@ -135,8 +124,6 @@ class I_EventsStream_GTest : public GTestWithTmpDir { virtual ~I_EventsStream_GTest() {} void reset() { - dt_ = new MockDataTransfer(); - std::unique_ptr dt(dt_); // needed by MockHWIdentification::get_header auto plugin_sw_info = std::make_shared(dummy_plugin_integrator_name_, dummy_plugin_name_, SoftwareInfo(0, 0, 0, "", "", "", "")); @@ -146,7 +133,7 @@ class I_EventsStream_GTest : public GTestWithTmpDir { DeviceBuilder device_builder = make_device_builder(); auto decoder = device_builder.add_facility(std::make_unique(false)); device_ = device_builder(); - events_stream_ = std::make_shared(std::move(dt), hw_identification_, + events_stream_ = std::make_shared(std::make_unique(), hw_identification_, std::shared_ptr(decoder)); events_stream_->start(); } @@ -154,16 +141,19 @@ class I_EventsStream_GTest : public GTestWithTmpDir { static const std::string dummy_plugin_name_; static const std::string dummy_plugin_integrator_name_; + void transfer_data(DataTransfer::DefaultBufferPtr data) const { + events_stream_->get_data_transfer().transfer_data(data); + } + protected: virtual void SetUp() override { datasets_.push_back( - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw") - .string()); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string()); datasets_.push_back( - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt2_hand.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt2_hand.raw") .string()); datasets_.push_back( - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw") .string()); } @@ -178,13 +168,13 @@ class I_EventsStream_GTest : public GTestWithTmpDir { std::unique_ptr device_; std::shared_ptr hw_identification_; std::shared_ptr events_stream_; - MockDataTransfer *dt_ = nullptr; long system_id_; std::vector datasets_; }; const std::string I_EventsStream_GTest::dummy_plugin_name_ = "plugin_name"; const std::string I_EventsStream_GTest::dummy_plugin_integrator_name_ = "plugin_integator_name"; +const std::initializer_list list = {1, 2, 3, 4, 5}; TEST_F(I_EventsStream_GTest, add_sub_system_id_to_header) { // Create tmp file @@ -201,8 +191,8 @@ TEST_F(I_EventsStream_GTest, add_sub_system_id_to_header) { TEST_F(I_EventsStream_GTest, poll_buffer) { ASSERT_EQ(0, events_stream_->poll_buffer()); - std::vector data = {1, 2, 3, 4, 5}; - dt_->trigger_transfer(data); + auto data = std::make_shared(list); + transfer_data(data); ASSERT_EQ(1, events_stream_->poll_buffer()); } @@ -222,8 +212,8 @@ TEST_F(I_EventsStream_GTest, add_data_triggers_wait_next_buffer) { while (!thread.joinable()) {} // wait thread to be started // trigger with add data - std::vector data = {1, 2, 3, 4, 5}; - dt_->trigger_transfer(data); + auto data = std::make_shared(list); + transfer_data(data); // Wait for the trigger to be processed (add a timeout to not wait forever) auto now = std::chrono::system_clock::now(); @@ -284,8 +274,8 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, valid_index_file) { const auto &dataset = datasets_[i]; // Remove the index file if any std::string path; - boost::filesystem::remove(dataset + ".tmp_index"); - ASSERT_FALSE(boost::filesystem::exists(dataset + ".tmp_index")); + std::filesystem::remove(dataset + ".tmp_index"); + ASSERT_FALSE(std::filesystem::exists(dataset + ".tmp_index")); // Open the file and generate the index ASSERT_TRUE(open_dataset(dataset)); @@ -350,8 +340,8 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, invalid_index_file) { // Remove the index file if any std::string path; - boost::filesystem::remove(dataset + ".tmp_index"); - ASSERT_FALSE(boost::filesystem::exists(dataset + ".tmp_index")); + std::filesystem::remove(dataset + ".tmp_index"); + ASSERT_FALSE(std::filesystem::exists(dataset + ".tmp_index")); // Open the file and generate the index ASSERT_TRUE(open_dataset(dataset)); @@ -483,8 +473,8 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, seek_range) { for (const auto &dataset : datasets_) { if (do_delete) { std::string path; - boost::filesystem::remove(dataset + ".tmp_index"); - ASSERT_FALSE(boost::filesystem::exists(dataset + ".tmp_index")); + std::filesystem::remove(dataset + ".tmp_index"); + ASSERT_FALSE(std::filesystem::exists(dataset + ".tmp_index")); } MV_HAL_LOG_INFO() << "\tTesting dataset" << dataset; @@ -524,9 +514,9 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, seek_range) { timestamp last_decoded_event_ts_us; while (fes->wait_next_buffer() > 0) { auto buffer = fes->get_latest_raw_data(); - auto data = buffer->data(); + auto data = buffer.data(); auto data_next = data + decoder->get_raw_event_size_bytes(); - auto data_end = data + buffer->size(); + auto data_end = buffer.end(); for (; first_decoded_event_ts_us == decoder->get_last_timestamp() && data != data_end; data = data_next, data_next += decoder->get_raw_event_size_bytes()) { @@ -542,7 +532,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, seek_range) { // -- Then decode the full dataset until the end while (fes->wait_next_buffer() > 0) { auto buffer = fes->get_latest_raw_data(); - decoder->decode(buffer->data(), buffer->data() + buffer->size()); + decoder->decode(buffer); } last_decoded_event_ts_us = decoder->get_last_timestamp(); @@ -579,8 +569,8 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, file_index_seek) { for (const auto &dataset : datasets_) { if (do_delete) { std::string path; - boost::filesystem::remove(dataset + ".tmp_index"); - ASSERT_FALSE(boost::filesystem::exists(dataset + ".tmp_index")); + std::filesystem::remove(dataset + ".tmp_index"); + ASSERT_FALSE(std::filesystem::exists(dataset + ".tmp_index")); } MV_HAL_LOG_INFO() << "\tTesting dataset" << dataset; @@ -625,7 +615,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, file_index_seek) { // Read data from the file ASSERT_TRUE(fes->wait_next_buffer() > 0); auto buffer = fes->get_latest_raw_data(); - decoder->decode(buffer->data(), buffer->data() + buffer->size()); + decoder->decode(buffer); } // ------------------------------ @@ -642,7 +632,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, file_index_seek) { auto buffer = fes->get_latest_raw_data(); // The first event decoded must have a timestamp that is equal to the first event's timestamp - decoder->decode(buffer->data(), buffer->data() + decoder->get_raw_event_size_bytes()); + decoder->decode(buffer.data(), buffer.data() + decoder->get_raw_event_size_bytes()); ASSERT_EQ(decoder->get_last_timestamp(), first_indexed_event_ts_us); // ------------------------------ @@ -668,7 +658,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, file_index_seek) { buffer = fes->get_latest_raw_data(); // The first event decoded must have a timestamp that is equal to the reached timestamp - decoder->decode(buffer->data(), buffer->data() + decoder->get_raw_event_size_bytes()); + decoder->decode(buffer.data(), buffer.data() + decoder->get_raw_event_size_bytes()); ASSERT_EQ(decoder->get_last_timestamp(), reached_ts); } @@ -684,135 +674,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, file_index_seek) { buffer = fes->get_latest_raw_data(); // The first event decoded must have a timestamp that is equal to the reached timestamp - decoder->decode(buffer->data(), buffer->data() + decoder->get_raw_event_size_bytes()); - ASSERT_EQ(decoder->get_last_timestamp(), reached_ts); - } - } - } -} - -TEST_F_WITH_DATASET(I_EventsStream_GTest, file_index_seek_deprecated_reset_timestamp) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Check seeking feature of the file control - - RawFileConfig config; - config.n_events_to_read_ = 10000; - - std::vector delete_index{{true, false}}; - std::vector time_shift{{true, false}}; - - for (const auto &do_delete : delete_index) { - MV_HAL_LOG_INFO() << (do_delete ? "Index building from scratch" : "Index loaded from file"); - for (const auto &dataset : datasets_) { - if (do_delete) { - std::string path; - boost::filesystem::remove(dataset + ".tmp_index"); - ASSERT_FALSE(boost::filesystem::exists(dataset + ".tmp_index")); - } - - MV_HAL_LOG_INFO() << "\tTesting dataset" << dataset; - for (const auto &do_time_shifting : time_shift) { - // Builds the device from the dataset - MV_HAL_LOG_INFO() << "\t\tTime shift:" << (do_time_shifting ? "enabled" : "disabled"); - config.do_time_shifting_ = do_time_shifting; - ASSERT_TRUE(open_dataset(dataset, config)); - - // Ensures the index have been built and one can retrieve the timestamp range - auto fes = device_->get_facility(); - ASSERT_NE(nullptr, fes); - - timestamp first_indexed_event_ts_us, last_indexed_event_ts_us; - auto index_status = fes->get_seek_range(first_indexed_event_ts_us, last_indexed_event_ts_us); - constexpr uint32_t max_trials = 1000; - uint32_t trials = 1; - while (index_status != Metavision::I_EventsStream::IndexStatus::Good && trials != max_trials) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - ++trials; - index_status = fes->get_seek_range(first_indexed_event_ts_us, last_indexed_event_ts_us); - } - - ASSERT_LT(trials, max_trials); - ASSERT_GT(last_indexed_event_ts_us, first_indexed_event_ts_us); - - auto decoder = device_->get_facility(); - auto cd_decoder = device_->get_facility>(); - ASSERT_NE(nullptr, decoder); - ASSERT_NE(nullptr, cd_decoder); - ASSERT_EQ(do_time_shifting, decoder->is_time_shifting_enabled()); - - // Start polling data - fes->start(); - - // GTest necessity only: - // Initialize the decoder (i.e. wait to reach the first decodable event) - // This is needed so that the seeking capability is validated - bool valid_event = false; - cd_decoder->add_event_buffer_callback([&](auto, auto) { valid_event = true; }); - while (!valid_event) { - // Read data from the file - ASSERT_TRUE(fes->wait_next_buffer() > 0); - auto buffer = fes->get_latest_raw_data(); - decoder->decode(buffer->data(), buffer->data() + buffer->size()); - } - - // ------------------------------ - // Check seeking at the beginning - MV_HAL_LOG_INFO() << "\t\t\tSeek first event"; - timestamp reached_ts; - ASSERT_EQ(I_EventsStream::SeekStatus::Success, fes->seek(first_indexed_event_ts_us, reached_ts)); - ASSERT_EQ(first_indexed_event_ts_us, reached_ts); - decoder->reset_timestamp(reached_ts); - ASSERT_EQ(decoder->get_last_timestamp(), reached_ts); - - ASSERT_TRUE(fes->wait_next_buffer() > 0); - // Decode a single event and check that the timestamp is correct - auto buffer = fes->get_latest_raw_data(); - - // The first event decoded must have a timestamp that is equal to the first event's timestamp - decoder->decode(buffer->data(), buffer->data() + decoder->get_raw_event_size_bytes()); - ASSERT_EQ(decoder->get_last_timestamp(), first_indexed_event_ts_us); - - // ------------------------------ - // Check seeking in the range of possible timestamps - MV_HAL_LOG_INFO() << "\t\t\tSeek in range of available timestamp"; - - std::vector targets; - const timestamp timestamp_step = (last_indexed_event_ts_us - first_indexed_event_ts_us) / 10; - for (uint32_t step = 1; step <= 10; ++step) { - targets.push_back(first_indexed_event_ts_us + step * timestamp_step); - } - - // Seeks back and forth in the file - using SizeType = std::vector::size_type; - for (SizeType i = 0; i < targets.size(); ++i) { - auto target_ts_us = i % 2 ? targets[targets.size() - i] : targets[i]; - ASSERT_EQ(I_EventsStream::SeekStatus::Success, fes->seek(target_ts_us, reached_ts)); - decoder->reset_timestamp(reached_ts); - ASSERT_LE(reached_ts, target_ts_us); - - // Read data from the file - ASSERT_TRUE(fes->wait_next_buffer() > 0); - buffer = fes->get_latest_raw_data(); - - // The first event decoded must have a timestamp that is equal to the reached timestamp - decoder->decode(buffer->data(), buffer->data() + decoder->get_raw_event_size_bytes()); - ASSERT_EQ(decoder->get_last_timestamp(), reached_ts); - } - - // ------------------------------ - // Check seeking at the end of the file - MV_HAL_LOG_INFO() << "\t\t\tSeek last event"; - ASSERT_EQ(I_EventsStream::SeekStatus::Success, fes->seek(last_indexed_event_ts_us, reached_ts)); - ASSERT_LE(reached_ts, last_indexed_event_ts_us); - decoder->reset_timestamp(reached_ts); - - // Read data from the file - ASSERT_TRUE(fes->wait_next_buffer() > 0); - buffer = fes->get_latest_raw_data(); - - // The first event decoded must have a timestamp that is equal to the reached timestamp - decoder->decode(buffer->data(), buffer->data() + decoder->get_raw_event_size_bytes()); + decoder->decode(buffer.data(), buffer.data() + decoder->get_raw_event_size_bytes()); ASSERT_EQ(decoder->get_last_timestamp(), reached_ts); } } @@ -822,7 +684,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, file_index_seek_deprecated_reset_times TEST_F_WITH_DATASET(I_EventsStream_GTest, decode_evt3_nevents_monotonous_timestamps) { // GIVEN a RAW file in EVT3 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); // AND a device configured to read by batches of n events RawFileConfig cfg; @@ -847,11 +709,11 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, decode_evt3_nevents_monotonous_timesta Metavision::timestamp previous_ts_last = 0; while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); // THEN the timestamps increase monotonously @@ -863,7 +725,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, decode_evt3_nevents_monotonous_timesta cur_raw_ptr = raw_buffer_decode_to; raw_buffer_decode_to = - std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer->data() + raw_buffer->size()); + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } } @@ -871,7 +733,7 @@ TEST_F_WITH_DATASET(I_EventsStream_GTest, decode_evt3_nevents_monotonous_timesta TEST_WITH_DATASET(EventsStream_GTest, stop_on_recording_does_not_drop_buffers) { // Read the dataset provided std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); std::unique_ptr device = Metavision::DeviceDiscovery::open_raw_file(dataset_file_path); EXPECT_TRUE(device != nullptr); @@ -886,7 +748,7 @@ TEST_WITH_DATASET(EventsStream_GTest, stop_on_recording_does_not_drop_buffers) { break; } auto ev_buffer = i_eventsstream->get_latest_raw_data(); - n_raw += ev_buffer->size(); + n_raw += ev_buffer.size(); i_eventsstream->stop(); } @@ -967,16 +829,16 @@ TYPED_TEST(I_EventsStreamT_GTest, test_log) { using EvtFormat = typename metavision_device_traits::RawEventFormat; TEncoder encoder; - std::vector data; + auto data = std::make_shared(); encoder.set_encode_event_callback( - [&data](const uint8_t *ev, const uint8_t *ev_end) { data.insert(data.end(), ev, ev_end); }); + [&data](const uint8_t *ev, const uint8_t *ev_end) { data->insert(data->end(), ev, ev_end); }); // Encode encoder.encode(this->events1_.data(), this->events1_.data() + this->events1_.size()); encoder.flush(); this->events_stream_->get_latest_raw_data(); - this->dt_->trigger_transfer(data); + this->transfer_data(data); // REMARK : as of today, in order to log we have to call // get_latest_raw_data before add_data and after diff --git a/hal_psee_plugins/test/psee_hw_layer_gtest.cpp b/hal_psee_plugins/test/psee_hw_layer_gtest.cpp index 4951250ed..cf08ff518 100644 --- a/hal_psee_plugins/test/psee_hw_layer_gtest.cpp +++ b/hal_psee_plugins/test/psee_hw_layer_gtest.cpp @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include -#include #include "metavision/utils/gtest/gtest_custom.h" @@ -31,7 +31,7 @@ class PseeBase_Gtest : virtual public ::testing::Test { TEST_F_WITH_DATASET(PseeBase_Gtest, cast_facility) { // Read the dataset provided std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); auto device = DeviceDiscovery::open_raw_file(dataset_file_path); ASSERT_TRUE(device != nullptr); diff --git a/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp b/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp index b99b044e2..a59d2a47b 100644 --- a/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp +++ b/hal_psee_plugins/test/psee_raw_file_decoder_gtest.cpp @@ -9,11 +9,11 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include #include #include #include -#include #include "metavision/utils/gtest/gtest_with_tmp_dir.h" #include "metavision/utils/gtest/gtest_custom.h" @@ -21,12 +21,10 @@ #include "metavision/sdk/base/events/event_pointcloud.h" #include "metavision/sdk/base/events/raw_event_frame_diff.h" #include "metavision/sdk/base/events/raw_event_frame_histo.h" -#include "metavision/sdk/base/utils/get_time.h" #include "metavision/hal/device/device_discovery.h" #include "metavision/hal/device/device.h" #include "metavision/hal/facilities/i_event_decoder.h" #include "metavision/hal/facilities/i_events_stream.h" -#include "metavision/hal/utils/hal_exception.h" #include "metavision/hal/facilities/i_event_frame_decoder.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" #include "devices/utils/device_system_id.h" @@ -160,7 +158,7 @@ TEST_F(PseeRawFileDecoder_Gtest, decode_evt2_data_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + decoder->decode(raw_buffer); } // THEN We decode the same data CD & triggers that are encoded in the RAW file @@ -215,19 +213,18 @@ TEST_F(PseeRawFileDecoder_Gtest, decode_evt2_data_random_split_in_buffer) { es->start(); // WHEN we stream and decode events in buffer of random size - long int bytes_polled_count; while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); - auto raw_data_to_decode_count = 2 * (raw_buffer->size() / 10) + + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 2 * (raw_buffer.size() / 10) + 1; // Ensures odd number of bytes so that we have split in middle of raw event auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -285,15 +282,15 @@ TEST_F(PseeRawFileDecoder_Gtest, decode_evt2_data_byte_by_byte) { // WHEN we stream and decode data byte by byte data while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -317,7 +314,7 @@ TEST_F(PseeRawFileDecoder_Gtest, decode_evt2_data_byte_by_byte) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_nominal) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") .string(); size_t received_cd_event_count = 0; @@ -347,7 +344,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + decoder->decode(raw_buffer); } // THEN We decode the same data CD & triggers that are encoded in the RAW file @@ -357,7 +354,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_random_split) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") .string(); size_t received_cd_event_count = 0; @@ -387,15 +384,16 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_random_split) { // WHEN we stream and decode events in buffer of random size while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); - auto raw_data_to_decode_count = 2 * (raw_buffer->size() / 10) + + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 2 * (raw_buffer.size() / 10) + 1; // Ensures odd number of bytes so that we have split in middle of raw event auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -406,7 +404,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_random_split) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_byte_by_byte) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") .string(); size_t received_cd_event_count = 0; @@ -436,15 +434,15 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_byte_by_byte) { // WHEN we stream and decode data byte by byte data while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -455,7 +453,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_data_byte_by_byte) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_nevents_monotonous_timestamps) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt21.raw") .string(); // AND a device configured to read by batches of n events @@ -481,11 +479,11 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_nevents_monotonous_ti Metavision::timestamp previous_ts_last = 0; while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); // THEN the timestamps increase monotonously @@ -495,9 +493,9 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_nevents_monotonous_ti previous_ts_last = current_ts_last; } - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } } @@ -505,7 +503,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_nevents_monotonous_ti TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_nominal) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") .string(); size_t received_cd_event_count = 0; @@ -535,7 +533,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_nominal) // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + decoder->decode(raw_buffer); } // THEN We decode the same data CD & triggers that are encoded in the RAW file @@ -545,7 +543,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_nominal) TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_random_split) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") .string(); size_t received_cd_event_count = 0; @@ -575,15 +573,16 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_random_sp // WHEN we stream and decode events in buffer of random size while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); - auto raw_data_to_decode_count = 2 * (raw_buffer->size() / 10) + + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 2 * (raw_buffer.size() / 10) + 1; // Ensures odd number of bytes so that we have split in middle of raw event auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -594,7 +593,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_random_sp TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_byte_by_byte) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") .string(); size_t received_cd_event_count = 0; @@ -624,15 +623,15 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_byte_by_b // WHEN we stream and decode data byte by byte data while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -643,7 +642,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_data_byte_by_b TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_nevents_monotonous_timestamps) { // GIVEN a RAW file in EVT21 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "standup_evt21-legacy.raw") .string(); // AND a device configured to read by batches of n events @@ -669,11 +668,11 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_nevents_monoto Metavision::timestamp previous_ts_last = 0; while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); // THEN the timestamps increase monotonously @@ -683,9 +682,9 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_nevents_monoto previous_ts_last = current_ts_last; } - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } } @@ -693,7 +692,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt21_legacy_nevents_monoto TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_nominal) { // GIVEN a RAW file in EVT3 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -722,7 +721,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + decoder->decode(raw_buffer); } // THEN We decode the same data CD & triggers that are encoded in the RAW file @@ -732,7 +731,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_random_split) { // GIVEN a RAW file in EVT3 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -761,15 +760,16 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_random_split) { // WHEN we stream and decode events in buffer of random size while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); - auto raw_data_to_decode_count = 2 * (raw_buffer->size() / 10) + + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 2 * (raw_buffer.size() / 10) + 1; // Ensures odd number of bytes so that we have split in middle of raw event auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -780,7 +780,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_random_split) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_byte_by_byte) { // GIVEN a RAW file in EVT3 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -809,15 +809,15 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_byte_by_byte) { // WHEN we stream and decode data byte by byte data while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -828,7 +828,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_data_byte_by_byte) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_nevents_monotonous_timestamps) { // GIVEN a RAW file in EVT3 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); // AND a device configured to read by batches of n events RawFileConfig cfg; @@ -853,11 +853,11 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_nevents_monotonous_tim Metavision::timestamp previous_ts_last = 0; while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); // THEN the timestamps increase monotonously @@ -867,9 +867,9 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_nevents_monotonous_tim previous_ts_last = current_ts_last; } - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } } @@ -877,7 +877,235 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_nevents_monotonous_tim TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_erc_count_evts) { // GIVEN a RAW file in EVT3 format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + + size_t cd_erc_in_total_count = 0; + size_t cd_erc_out_total_count = 0; + RawFileConfig cfg; + cfg.do_time_shifting_ = false; + std::unique_ptr device(DeviceDiscovery::open_raw_file(dataset_file_path, cfg)); + + if (!device) { + std::cerr << "Failed to open raw file." << std::endl; + FAIL(); + } + + // AND a PSEE decoder of CD count events + auto decoder = device->get_facility(); + auto erc_count_decoder = device->get_facility>(); + auto es = device->get_facility(); + + ASSERT_NE(nullptr, decoder); + ASSERT_NE(nullptr, erc_count_decoder); + ASSERT_NE(nullptr, es); + + erc_count_decoder->add_event_buffer_callback([&](auto ev_begin, auto ev_end) { + ASSERT_EQ(1, std::distance(ev_begin, ev_end)); + if (ev_begin->is_output) + cd_erc_out_total_count += ev_begin->event_count; + else + cd_erc_in_total_count += ev_begin->event_count; + }); + + es->start(); + + // WHEN we stream and decode the events in the file + while (es->wait_next_buffer() >= 0) { + auto raw_buffer = es->get_latest_raw_data(); + decoder->decode(raw_buffer); + } + + // THEN We decode the same data CD incoming count events that are encoded in the RAW file + ASSERT_EQ(18158913, cd_erc_in_total_count); + ASSERT_EQ(18095375, cd_erc_out_total_count); +} + +TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt4_data_nominal) { + // GIVEN a RAW file in EVT4 format with a known content + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt4.raw"; + + size_t received_cd_event_count = 0; + RawFileConfig cfg; + cfg.do_time_shifting_ = false; + std::unique_ptr device(DeviceDiscovery::open_raw_file(dataset_file_path, cfg)); + + if (!device) { + std::cerr << "Failed to open raw file." << std::endl; + FAIL(); + } + + // AND a PSEE decoder of CD & triggers events + auto decoder = device->get_facility(); + auto cd_decoder = device->get_facility>(); + auto es = device->get_facility(); + + ASSERT_NE(nullptr, decoder); + ASSERT_NE(nullptr, cd_decoder); + ASSERT_NE(nullptr, es); + + cd_decoder->add_event_buffer_callback( + [&](auto ev_begin, auto ev_end) { received_cd_event_count += std::distance(ev_begin, ev_end); }); + + es->start(); + + // WHEN we stream and decode the events in the file + while (es->wait_next_buffer() >= 0) { + auto raw_buffer = es->get_latest_raw_data(); + decoder->decode(raw_buffer); + } + + // THEN We decode the same data CD & triggers that are encoded in the RAW file + ASSERT_EQ(16294351, received_cd_event_count); +} + +TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt4_data_random_split) { + // GIVEN a RAW file in EVT4 format with a known content + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt4.raw"; + + size_t received_cd_event_count = 0; + RawFileConfig cfg; + cfg.do_time_shifting_ = false; + std::unique_ptr device(DeviceDiscovery::open_raw_file(dataset_file_path, cfg)); + + if (!device) { + std::cerr << "Failed to open raw file." << std::endl; + FAIL(); + } + + // AND a PSEE decoder of CD & triggers events + auto decoder = device->get_facility(); + auto cd_decoder = device->get_facility>(); + auto es = device->get_facility(); + + ASSERT_NE(nullptr, decoder); + ASSERT_NE(nullptr, cd_decoder); + ASSERT_NE(nullptr, es); + + cd_decoder->add_event_buffer_callback( + [&](auto ev_begin, auto ev_end) { received_cd_event_count += std::distance(ev_begin, ev_end); }); + + es->start(); + + // WHEN we stream and decode events in buffer of random size + while (es->wait_next_buffer() >= 0) { + auto raw_buffer = es->get_latest_raw_data(); + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 2 * (raw_buffer.size() / 10) + + 1; // Ensures odd number of bytes so that we have split in middle of raw event + auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; + + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { + decoder->decode(cur_raw_ptr, raw_buffer_decode_to); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.end()); + } + } + + // THEN We decode the same data CD & triggers that are encoded in the RAW file + ASSERT_EQ(16294351, received_cd_event_count); +} + +TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt4_data_byte_by_byte) { + // GIVEN a RAW file in EVT4 format with a known content + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt4.raw"; + + size_t received_cd_event_count = 0; + RawFileConfig cfg; + cfg.do_time_shifting_ = false; + std::unique_ptr device(DeviceDiscovery::open_raw_file(dataset_file_path, cfg)); + + if (!device) { + std::cerr << "Failed to open raw file." << std::endl; + FAIL(); + } + + // AND a PSEE decoder of CD & triggers events + auto decoder = device->get_facility(); + auto cd_decoder = device->get_facility>(); + auto es = device->get_facility(); + + ASSERT_NE(nullptr, decoder); + ASSERT_NE(nullptr, cd_decoder); + ASSERT_NE(nullptr, es); + + cd_decoder->add_event_buffer_callback( + [&](auto ev_begin, auto ev_end) { received_cd_event_count += std::distance(ev_begin, ev_end); }); + + es->start(); + + // WHEN we stream and decode data byte by byte data + while (es->wait_next_buffer() >= 0) { + auto raw_buffer = es->get_latest_raw_data(); + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 1; + auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; + + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { + decoder->decode(cur_raw_ptr, raw_buffer_decode_to); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.end()); + } + } + + // THEN We decode the same data CD & triggers that are encoded in the RAW file + ASSERT_EQ(16294351, received_cd_event_count); +} + +TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt4_nevents_monotonous_timestamps) { + // GIVEN a RAW file in EVT4 format with a known content + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "claque_doigt_evt4.raw"; + + // AND a device configured to read by batches of n events + RawFileConfig cfg; + cfg.n_events_to_read_ = 10000; + std::unique_ptr device(DeviceDiscovery::open_raw_file(dataset_file_path, cfg)); + + if (!device) { + std::cerr << "Failed to open raw file." << std::endl; + FAIL(); + } + + // AND a PSEE decoder of CD & triggers events + auto decoder = device->get_facility(); + auto es = device->get_facility(); + + ASSERT_NE(nullptr, decoder); + ASSERT_NE(nullptr, es); + + es->start(); + + // WHEN we stream and decode data byte by byte + Metavision::timestamp previous_ts_last = 0; + while (es->wait_next_buffer() >= 0) { + auto raw_buffer = es->get_latest_raw_data(); + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 1; + auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; + + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { + decoder->decode(cur_raw_ptr, raw_buffer_decode_to); + + // THEN the timestamps increase monotonously + Metavision::timestamp current_ts_last = decoder->get_last_timestamp(); + if (current_ts_last > 0) { + ASSERT_GE(current_ts_last, previous_ts_last); + previous_ts_last = current_ts_last; + } + + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.end()); + } + } +} + +TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt4_erc_count_evts) { + // GIVEN a RAW file in EVT4 format with a known content + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt4_hand.raw"; size_t cd_erc_in_total_count = 0; size_t cd_erc_out_total_count = 0; @@ -912,7 +1140,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_erc_count_evts) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + decoder->decode(raw_buffer); } // THEN We decode the same data CD incoming count events that are encoded in the RAW file @@ -923,7 +1151,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_evt3_erc_count_evts) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_histo3d_nominal) { // GIVEN a RAW file in histo3d format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "histo3d.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "histo3d.raw").string(); size_t received_event_frame_count = 0; RawFileConfig cfg; @@ -949,7 +1177,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_histo3d_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - histo_decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + histo_decoder->decode(raw_buffer.begin(), raw_buffer.end()); } // THEN We decode the same data Histogram that are encoded in the RAW file @@ -959,7 +1187,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_histo3d_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_histo3d_padding_nominal) { // GIVEN a RAW file in histo3d + padding format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "histo3d_padding.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "histo3d_padding.raw").string(); size_t received_event_frame_count = 0; RawFileConfig cfg; @@ -985,7 +1213,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_histo3d_padding_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - histo_decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + histo_decoder->decode(raw_buffer.begin(), raw_buffer.end()); } // THEN We decode the same data Histogram that are encoded in the RAW file @@ -995,7 +1223,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_histo3d_padding_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_diff3d_nominal) { // GIVEN a RAW file in histo3d + padding format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "diff3d.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "diff3d.raw").string(); size_t received_event_frame_count = 0; RawFileConfig cfg; @@ -1021,7 +1249,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_diff3d_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - diff_decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + diff_decoder->decode(raw_buffer.begin(), raw_buffer.end()); } // THEN We decode the same data Diff that are encoded in the RAW file @@ -1031,7 +1259,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_diff3d_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_nominal) { // GIVEN a RAW file in AER format with 8bits interface with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_8bits.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_8bits.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -1060,7 +1288,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + decoder->decode(raw_buffer); } // THEN We decode the same data CD & triggers that are encoded in the RAW file @@ -1070,7 +1298,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_random_split) { // GIVEN a RAW file in AER format with 8bits interface with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_8bits.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_8bits.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -1099,16 +1327,16 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_random_split) { // WHEN we stream and decode events in buffer of random size while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); - auto raw_data_to_decode_count = 2 * (raw_buffer->size() / 10) + + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 2 * (raw_buffer.size() / 10) + 1; // Ensures odd number of bytes so that we have split in middle of raw event auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -1119,7 +1347,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_random_split) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_byte_by_byte) { // GIVEN a RAW file in AER format with 8bits interface with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_8bits.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_8bits.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -1148,15 +1376,15 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_byte_by_byte) { // WHEN we stream and decode data byte by byte data while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -1167,7 +1395,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer8_data_byte_by_byte) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_nominal) { // GIVEN a RAW file in AER format with 4bits interface with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_4bits.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_4bits.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -1196,7 +1424,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + decoder->decode(raw_buffer); } // THEN We decode the same data CD & triggers that are encoded in the RAW file @@ -1206,7 +1434,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_random_split) { // GIVEN a RAW file in AER format with 4bits interface with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_4bits.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_4bits.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -1235,16 +1463,16 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_random_split) { // WHEN we stream and decode events in buffer of random size while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); - auto raw_data_to_decode_count = 2 * (raw_buffer->size() / 10) + + auto cur_raw_ptr = raw_buffer.data(); + auto raw_data_to_decode_count = 2 * (raw_buffer.size() / 10) + 1; // Ensures odd number of bytes so that we have split in middle of raw event - auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; + auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -1255,7 +1483,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_random_split) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_byte_by_byte) { // GIVEN a RAW file in AER format with 4bits interface with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_4bits.raw").string(); + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "aer_4bits.raw").string(); size_t received_cd_event_count = 0; RawFileConfig cfg; @@ -1284,15 +1512,15 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_byte_by_byte) { // WHEN we stream and decode data byte by byte data while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - auto cur_raw_ptr = raw_buffer->data(); + auto cur_raw_ptr = raw_buffer.data(); auto raw_data_to_decode_count = 1; auto raw_buffer_decode_to = cur_raw_ptr + raw_data_to_decode_count; - for (; static_cast(std::distance(raw_buffer->data(), cur_raw_ptr)) < raw_buffer->size();) { + for (; static_cast(std::distance(raw_buffer.data(), cur_raw_ptr)) < raw_buffer.size();) { decoder->decode(cur_raw_ptr, raw_buffer_decode_to); - cur_raw_ptr = raw_buffer_decode_to; - raw_buffer_decode_to = std::min(cur_raw_ptr + raw_data_to_decode_count, - raw_buffer->data() + raw_buffer->size()); + cur_raw_ptr = raw_buffer_decode_to; + raw_buffer_decode_to = + std::min(cur_raw_ptr + raw_data_to_decode_count, raw_buffer.data() + raw_buffer.size()); } } @@ -1303,7 +1531,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_aer4_data_byte_by_byte) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_mtr_nominal) { // GIVEN a RAW file in MTR format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "0101_cm_mtr12_output.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "0101_cm_mtr12_output.raw") .string(); size_t received_event_frame_count = 0; @@ -1330,7 +1558,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_mtr_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - mtr_decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + mtr_decoder->decode(raw_buffer.begin(), raw_buffer.end()); } // THEN We decode the same MTR data that are encoded in the RAW file @@ -1340,7 +1568,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_mtr_nominal) { TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_mtru_nominal) { // GIVEN a RAW file in MTRU format with a known content std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "0101_cm_mtru_output.raw") + (std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "0101_cm_mtru_output.raw") .string(); size_t received_event_frame_count = 0; @@ -1367,7 +1595,7 @@ TEST_F_WITH_DATASET(PseeRawFileDecoder_Gtest, decode_mtru_nominal) { // WHEN we stream and decode the events in the file while (es->wait_next_buffer() >= 0) { auto raw_buffer = es->get_latest_raw_data(); - mtr_decoder->decode(raw_buffer->data(), raw_buffer->data() + raw_buffer->size()); + mtr_decoder->decode(raw_buffer.begin(), raw_buffer.end()); } // THEN We decode the same MTR data that are encoded in the RAW file diff --git a/sdk/cmake/MetavisionSDKAdvancedCPackConfig.cmake b/sdk/cmake/MetavisionSDKAdvancedCPackConfig.cmake index bea62efc3..f84ee2e6e 100644 --- a/sdk/cmake/MetavisionSDKAdvancedCPackConfig.cmake +++ b/sdk/cmake/MetavisionSDKAdvancedCPackConfig.cmake @@ -78,9 +78,6 @@ if (COMPILE_PYTHON3_BINDINGS) if(metavision-sdk-${available_module}-python IN_LIST components_to_install_public) list(APPEND CPACK_COMPONENT_METAVISION-SDK-ADVANCED-PYTHON_DEPENDS metavision-sdk-${available_module}-python) endif() - if(metavision-sdk-${available_module}-extended-python IN_LIST components_to_install_public) - list(APPEND CPACK_COMPONENT_METAVISION-SDK-ADVANCED-PYTHON_DEPENDS metavision-sdk-${available_module}-extended-python) - endif() endforeach(available_module) endif(COMPILE_PYTHON3_BINDINGS) @@ -89,7 +86,7 @@ endif(COMPILE_PYTHON3_BINDINGS) ########################################## if (COMPILE_PYTHON3_BINDINGS) set(CPACK_COMPONENT_METAVISION-SDK-ADVANCED-PYTHON-SAMPLES_DESCRIPTION "Samples for Metavision SDK Advanced Python 3 libraries.\n${PACKAGE_LICENSE}") - set(CPACK_COMPONENT_METAVISION-SDK-ADVANCED-PYTHON-SAMPLES_DEPENDS metavision-open-python-samples metavision-sdk-ml-extended-python-samples) + set(CPACK_COMPONENT_METAVISION-SDK-ADVANCED-PYTHON-SAMPLES_DEPENDS metavision-open-python-samples) foreach(available_module IN LISTS METAVISION_SDK_ADVANCED_MODULES_AVAILABLE) if(metavision-sdk-${available_module}-python-samples IN_LIST components_to_install_public) list(APPEND CPACK_COMPONENT_METAVISION-SDK-ADVANCED-PYTHON-SAMPLES_DEPENDS metavision-sdk-${available_module}-python-samples) diff --git a/sdk/cmake/MetavisionSDKConfig.cmake.in b/sdk/cmake/MetavisionSDKConfig.cmake.in index f72ef9bc2..505bcba47 100644 --- a/sdk/cmake/MetavisionSDKConfig.cmake.in +++ b/sdk/cmake/MetavisionSDKConfig.cmake.in @@ -31,7 +31,7 @@ # MetavisionSDK_VERSION_PATCH - MetavisionSDK patch version number (Z in x.y.Z) # # -# Implicit dependencies such as MetavisionSDK::driver requiring +# Implicit dependencies such as MetavisionSDK::stream requiring # MetavisionSDK::base will be automatically detected and satisfied, even # if base is not specified when using find_package and if # MetavisionSDK::base is not added to target_link_libraries. @@ -39,9 +39,9 @@ # # Example to find MetavisionSDK libraries and use imported targets:: # -# find_package(MetavisionSDK 2.1.0 REQUIRED COMPONENTS base driver) +# find_package(MetavisionSDK 5.0.0 REQUIRED COMPONENTS base stream) # add_executable(foo foo.cpp) -# target_link_libraries(foo MetavisionSDK::base MetavisionSDK::driver) # or target_link_libraries(foo ${MetavisionSDK_LIBRARIES}) +# target_link_libraries(foo MetavisionSDK::base MetavisionSDK::stream) # or target_link_libraries(foo ${MetavisionSDK_LIBRARIES}) @PACKAGE_INIT@ diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/events/event_cd_vector.h b/sdk/modules/base/cpp/include/metavision/sdk/base/events/event_cd_vector.h new file mode 100644 index 000000000..6e4b55dbe --- /dev/null +++ b/sdk/modules/base/cpp/include/metavision/sdk/base/events/event_cd_vector.h @@ -0,0 +1,79 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_BASE_EVENT_CD_VECTOR_H +#define METAVISION_SDK_BASE_EVENT_CD_VECTOR_H + +#include +#include + +#include "metavision/sdk/base/utils/timestamp.h" + +namespace Metavision { + +/// @brief Class representing Vectorized 2D CD (Contrast Detection) events: +/// @details vector_mask represents 32 potentially triggered events in a single lane as a 32bit value. +/// Each set bit represents a triggered event at pos(base_x + vector_mask[i], y) +class EventCDVector { +public: + + /// @brief Default constructor + EventCDVector() = default; + + /// @brief Constructor from Event2d + inline EventCDVector( + uint16_t base_x, uint16_t y, + bool polarity, + uint32_t vector_mask, + timestamp event_timestamp + ) : + base_x(base_x), y(y), + polarity(polarity), + vector_mask(vector_mask), + event_timestamp(event_timestamp) + {} + + inline bool operator==(const EventCDVector &rhs) const { + return ( + (polarity == rhs.polarity) && + (base_x == rhs.base_x) && (y == rhs.y) && + (vector_mask == rhs.vector_mask) && + (event_timestamp == rhs.event_timestamp) + ); + } + + /// @brief function operator<< that returns std::ostream & + friend std::ostream &operator<<(std::ostream &output, const EventCDVector &rhs) { + output << "EventCDVector: ("; + + output + << rhs.base_x << ", " + << rhs.y << ", " + << (int)rhs.polarity << ", " + << rhs.vector_mask << ", " + << rhs.event_timestamp; + + output << ")"; + return output; + } + + uint16_t base_x, y; + bool polarity; + uint32_t vector_mask; + timestamp event_timestamp; + +}; + +} // namespace Metavision + +// METAVISION_DEFINE_EVENT_TRAIT(Metavision::EventCDVector, 13, "CDVector") + +#endif // METAVISION_SDK_BASE_EVENT_CD_VECTOR_H \ No newline at end of file diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_diff.h b/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_diff.h index 0ff0bdf96..223e0b623 100644 --- a/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_diff.h +++ b/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_diff.h @@ -54,14 +54,6 @@ class RawEventFrameDiff { /// @brief Copy constructor RawEventFrameDiff(const RawEventFrameDiff &d) : cfg_(d.cfg_), diff_(d.diff_) {} - [[deprecated( - "'RawEventFrameDiff(const RawEventFrameDiffConfig &, std::unique_ptr>)' constructor " - "is deprecated since v4.3.0 and will be removed in future releases, " - "please use 'RawEventFrameDiff(const RawEventFrameDiffConfig &, const std::vector&)' " - "instead.")]] RawEventFrameDiff(const RawEventFrameDiffConfig &cfg, - std::unique_ptr> data) : - RawEventFrameDiff(cfg, *data) {} - /// @brief Resets the event frame configuration and sets all values to 0. /// @throws invalid_argument if bit_size is outside the supported range of [2;8]. void reset(unsigned height, unsigned width, unsigned bit_size = 8) { diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_histo.h b/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_histo.h index fe6d73317..0394595a3 100644 --- a/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_histo.h +++ b/sdk/modules/base/cpp/include/metavision/sdk/base/events/raw_event_frame_histo.h @@ -60,14 +60,6 @@ class RawEventFrameHisto { /// @brief Copy constructor RawEventFrameHisto(const RawEventFrameHisto &h) : cfg_(h.cfg_), histo_(h.histo_) {} - [[deprecated("'RawEventFrameHisto(const RawEventFrameHistoConfig &, std::unique_ptr>)' " - "constructor " - "is deprecated since v4.3.0 and will be removed in future releases, " - "please use 'RawEventFrameHisto(const RawEventFrameHistoConfig &, const std::vector&)' " - "instead.")]] RawEventFrameHisto(const RawEventFrameHistoConfig &cfg, - std::unique_ptr> data) : - RawEventFrameHisto(cfg, *data) {} - /// @brief Resets the event frame configuration and sets all values to 0. /// @throws invalid_argument if either bit size is zero or if their sum is more than 8 void reset(unsigned height, unsigned width, unsigned channel_bit_neg = 4, unsigned channel_bit_pos = 4, diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/detail/log_impl.h b/sdk/modules/base/cpp/include/metavision/sdk/base/utils/detail/log_impl.h index 914661352..f60b363fd 100644 --- a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/detail/log_impl.h +++ b/sdk/modules/base/cpp/include/metavision/sdk/base/utils/detail/log_impl.h @@ -27,10 +27,11 @@ class LoggingOperation { static constexpr LogLevel Level = LogLevel::Debug; LoggingOperation(const LogOptions & /**/ = LogOptions(), const std::string & /**/ = std::string(), - const std::string & /**/ = std::string(), int = 0, const std::string & /**/ = std::string()) {} + const std::filesystem::path & /**/ = std::string(), int = 0, + const std::string & /**/ = std::string()) {} - const std::string &file() { - static std::string s; + const std::filesystem::path &file() { + static std::filesystem::path s; return s; } @@ -38,8 +39,8 @@ class LoggingOperation { return std::string(); } - std::string file() const { - return std::string(); + std::filesystem::path file() const { + return std::filesystem::path(); } int line() const { @@ -74,18 +75,18 @@ class LoggingOperation { namespace detail { template -LoggingOperation log(const std::string &file, int line, const std::string &function) { +LoggingOperation log(const std::filesystem::path &file, int line, const std::string &function) { return LoggingOperation(getLogOptions(), "", file, line, function); } template -LoggingOperation log(const std::string &file, int line, const std::string &function, +LoggingOperation log(const std::filesystem::path &file, int line, const std::string &function, const std::string &prefixFmt) { return LoggingOperation(getLogOptions(), prefixFmt, file, line, function); } template -LoggingOperation log(const std::string &file, int line, const std::string &function, +LoggingOperation log(const std::filesystem::path &file, int line, const std::string &function, const char *const prefixFmt) { return LoggingOperation(getLogOptions(), std::string(prefixFmt), file, line, function); } @@ -134,8 +135,8 @@ std::string getPaddedLevelLabel(const LogLevel &level, const LogLevelNameMap &la std::string getLevelName(const LogLevel &level, const LogLevelNameMap &labels, bool level_prefix_padding); template -std::string getLogPrefixFormatString(bool level_prefix_padding, const std::string &prefixFmt, const std::string &file, - int line, const std::string &function) { +std::string getLogPrefixFormatString(bool level_prefix_padding, const std::string &prefixFmt, + const std::filesystem::path &file, int line, const std::string &function) { size_t pos; std::string s = prefixFmt; std::string token; @@ -149,17 +150,7 @@ std::string getLogPrefixFormatString(bool level_prefix_padding, const std::strin } token = ""; if ((pos = s.find(token)) != std::string::npos) { - std::string basename; -#ifdef _WIN32 - const char *const p = strrchr(file.c_str(), '\\'); -#else - const char *const p = strrchr(file.c_str(), '/'); -#endif - if (p) - basename = std::string(p + 1); - else - basename = file; - s.replace(pos, token.size(), basename); + s.replace(pos, token.size(), file.filename().string()); } token = ""; if ((pos = s.find(token)) != std::string::npos) { @@ -218,8 +209,8 @@ template constexpr LogLevel LoggingOperation::Level; template -LoggingOperation::LoggingOperation(const LogOptions &opts, const std::string &prefixFmt, const std::string &file, - int line, const std::string &function) : +LoggingOperation::LoggingOperation(const LogOptions &opts, const std::string &prefixFmt, + const std::filesystem::path &file, int line, const std::string &function) : streambuf_(new detail::concurrent_ostreambuf(opts.getStream().rdbuf())), stream_(new std::ostream(streambuf_.get())), addSpaceBetweenTokens_(true), @@ -254,7 +245,7 @@ std::string LoggingOperation::function() const { } template -std::string LoggingOperation::file() const { +std::filesystem::path LoggingOperation::file() const { return file_; } diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/log.h b/sdk/modules/base/cpp/include/metavision/sdk/base/utils/log.h index 47d526d76..316a93bc7 100644 --- a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/log.h +++ b/sdk/modules/base/cpp/include/metavision/sdk/base/utils/log.h @@ -12,6 +12,7 @@ #ifndef METAVISION_SDK_BASE_LOG_H #define METAVISION_SDK_BASE_LOG_H +#include #include #include #include @@ -248,7 +249,7 @@ class LoggingOperation { /// @note The replacement in the prefix format only occurs once, i.e. each token is searched only once and not /// replaced multiple times. LoggingOperation(const LogOptions &opts = LogOptions(), const std::string &prefixFmt = std::string(), - const std::string &file = std::string(), int line = 0, + const std::filesystem::path &file = std::string(), int line = 0, const std::string &function = std::string()); /// @brief Copy constructor @@ -288,7 +289,7 @@ class LoggingOperation { void disableEndOfLineAtDestruction(); /// @brief Returns the name of the file associated to this logging operation - std::string file() const; + std::filesystem::path file() const; /// @brief Returns the line associated to this logging operation int line() const; @@ -326,7 +327,8 @@ class LoggingOperation { bool addSpaceBetweenTokens_; bool addEndLine_; bool should_output_; - std::string prefix_, file_, function_; + std::string prefix_, function_; + std::filesystem::path file_; int line_; }; diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/object_pool.h b/sdk/modules/base/cpp/include/metavision/sdk/base/utils/object_pool.h index a2aff6be1..26b2c7102 100644 --- a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/object_pool.h +++ b/sdk/modules/base/cpp/include/metavision/sdk/base/utils/object_pool.h @@ -13,7 +13,6 @@ #define METAVISION_SDK_BASE_OBJECT_POOL_H #include -#include #include #include #include @@ -57,6 +56,10 @@ class ObjectPool { }; public: + /// @brief The type of the stored object + using value_type = T; + + /// @brief The type of the smart pointer used to store the object using ptr_type = typename std::conditional, std::unique_ptr>::type; diff --git a/sdk/modules/base/cpp/src/log.cpp b/sdk/modules/base/cpp/src/log.cpp index c4a826286..6b24d897a 100644 --- a/sdk/modules/base/cpp/src/log.cpp +++ b/sdk/modules/base/cpp/src/log.cpp @@ -276,10 +276,10 @@ constexpr LogLevel LoggingOperation::Level; namespace detail { template<> -LoggingOperation log(const std::string &file, int line, const std::string &function, - const std::string &prefixFmt) { +LoggingOperation log(const std::filesystem::path &file, int line, + const std::string &function, const std::string &prefixFmt) { // when in release, this should return an "object" on which all operations are in fact no-op - return LoggingOperation(LogOptions(), std::string(), std::string(), 0, std::string()); + return LoggingOperation(LogOptions(), std::string(), std::filesystem::path(), 0, std::string()); } } // namespace detail diff --git a/sdk/modules/base/cpp/tests/object_pool_gtest.cpp b/sdk/modules/base/cpp/tests/object_pool_gtest.cpp index 66aef8dfe..e4dc3db09 100644 --- a/sdk/modules/base/cpp/tests/object_pool_gtest.cpp +++ b/sdk/modules/base/cpp/tests/object_pool_gtest.cpp @@ -118,7 +118,7 @@ TEST(ObjectPool_GTest, bounded_overflow) { while (!release_thread.joinable()) {} std::unique_lock lock(acquire_success_mutex); - auto ret = acquire_success_cond.wait_for(lock, std::chrono::seconds(1), [&]() { return acquire_success; }); + auto ret = acquire_success_cond.wait_for(lock, std::chrono::milliseconds(1), [&]() { return acquire_success; }); ASSERT_FALSE(ret); // WHEN a buffer is given back in the pool diff --git a/sdk/modules/core/cmake/MetavisionSDK_coreCPackConfig.cmake b/sdk/modules/core/cmake/MetavisionSDK_coreCPackConfig.cmake index 74b96f792..24ccc5a08 100644 --- a/sdk/modules/core/cmake/MetavisionSDK_coreCPackConfig.cmake +++ b/sdk/modules/core/cmake/MetavisionSDK_coreCPackConfig.cmake @@ -21,18 +21,18 @@ set(CPACK_COMPONENT_METAVISION-SDK-CORE-LIB_DEPENDS metavision-sdk-base-lib) # Runtime (apps) set(CPACK_COMPONENT_METAVISION-SDK-CORE-BIN_DESCRIPTION "Binaries for the Metavision SDK Core applications.\n${OPEN_PACKAGE_LICENSE}") -set(CPACK_COMPONENT_METAVISION-SDK-CORE-BIN_DEPENDS metavision-sdk-core-lib metavision-sdk-driver-lib) +set(CPACK_COMPONENT_METAVISION-SDK-CORE-BIN_DEPENDS metavision-sdk-core-lib metavision-sdk-stream-lib) # Development package set(CPACK_COMPONENT_METAVISION-SDK-CORE-DEV_DESCRIPTION "Development (C++) files for Metavision SDK Core library.\n${OPEN_PACKAGE_LICENSE}") set(CPACK_COMPONENT_METAVISION-SDK-CORE-DEV_DEPENDS metavision-sdk-core-lib metavision-sdk-base-dev) list(APPEND CPACK_DEBIAN_METAVISION-SDK-CORE-DEV_PACKAGE_DEPENDS "libopencv-dev") -list(APPEND CPACK_DEBIAN_METAVISION-SDK-CORE-DEV_PACKAGE_DEPENDS "libboost-dev" "libboost-filesystem-dev" "libboost-timer-dev") +list(APPEND CPACK_DEBIAN_METAVISION-SDK-CORE-DEV_PACKAGE_DEPENDS "libboost-dev" "libboost-timer-dev") string(REPLACE ";" ", " CPACK_DEBIAN_METAVISION-SDK-CORE-DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_METAVISION-SDK-CORE-DEV_PACKAGE_DEPENDS}") # Samples of metavision-sdk-core set(CPACK_COMPONENT_METAVISION-SDK-CORE-SAMPLES_DESCRIPTION "Samples for Metavision SDK Core library.\n${OPEN_PACKAGE_LICENSE}") -set(CPACK_COMPONENT_METAVISION-SDK-CORE-SAMPLES_DEPENDS metavision-sdk-base-dev metavision-sdk-core-dev metavision-sdk-driver-dev metavision-sdk-ui-dev) +set(CPACK_COMPONENT_METAVISION-SDK-CORE-SAMPLES_DEPENDS metavision-sdk-base-dev metavision-sdk-core-dev metavision-sdk-stream-dev metavision-sdk-ui-dev) # Pure python library if (COMPILE_PYTHON3_BINDINGS) diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/base_frame_generation_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/base_frame_generation_algorithm.h index 67929a893..f05d2b994 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/base_frame_generation_algorithm.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/base_frame_generation_algorithm.h @@ -76,12 +76,13 @@ class BaseFrameGenerationAlgorithm { /// event source, and the color corresponding to the given @p palette (3 channels by default) /// @param accumulation_time_us Time range of events to update the frame with (in us) /// @param palette The Prophesee's color palette to use + /// @param flags A combination of Parameters /// @note Even if there's no events, a frame filled with the background color will be generated /// @throw invalid_argument if @p frame does not have the expected type (CV_8U or CV_8UC3) template static void generate_frame_from_events(EventIt it_begin, EventIt it_end, cv::Mat &frame, const uint32_t accumulation_time_us = 0, - const Metavision::ColorPalette &palette = default_palette()); + const Metavision::ColorPalette &palette = default_palette(), int flags = 0); /// @brief Sets the color used to generate the frame /// @param bg_color Color used as background, when no events were received for a pixel diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/contrast_map_generation_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/contrast_map_generation_algorithm.h new file mode 100644 index 000000000..3f74c9e65 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/contrast_map_generation_algorithm.h @@ -0,0 +1,66 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_CONTRAST_MAP_GENERATION_ALGORITHM_H +#define METAVISION_SDK_CORE_CONTRAST_MAP_GENERATION_ALGORITHM_H + +#include +#include "metavision/sdk/base/events/event_cd.h" + +namespace Metavision { + +/// @brief Class to generate a contrast map from a stream of events +class ContrastMapGenerationAlgorithm { +public: + /// @brief Constructor + /// @param width Width of the input event stream. + /// @param height Height of the input event stream. + /// @param contrast_on Contrast value for ON events. + /// @param contrast_off Contrast value for OFF events. If non-positive, the contrast is set to the inverse of + /// the @p contrast_on value. + ContrastMapGenerationAlgorithm(unsigned int width, unsigned int height, float contrast_on = 1.2f, + float contrast_off = -1); + + /// @brief Processes a range of events + /// @tparam InputIt Iterator type. + /// @param it_begin Iterator pointing to the first event to process. + /// @param it_end Iterator pointing to the end of the range of events to process. + template + void process_events(InputIt it_begin, InputIt it_end); + + /// @brief Generates the contrast map and resets the internal state + /// @param contrast_map Output contrast map, swapped with the one maintained internally. + void generate(cv::Mat_ &contrast_map); + + /// @brief Generates the tonemapped contrast map and resets the internal state + /// @param contrast_map_tonnemapped Output tonemapped contrast map. + /// @param tonemapping_factor Tonemapping factor. + /// @param tonemapping_bias Tonemapping bias. + void generate(cv::Mat_ &contrast_map_tonnemapped, float tonemapping_factor, float tonemapping_bias); + + /// @brief Resets the internal state + void reset(); + +private: + void process_event(const EventCD &e); + + const unsigned int width_; + const unsigned int height_; + const std::array contrasts_; + + cv::Mat_ states_; +}; + +} // namespace Metavision + +#include "metavision/sdk/core/algorithms/detail/contrast_map_generation_algorithm_impl.h" + +#endif // METAVISION_SDK_CORE_CONTRAST_MAP_GENERATION_ALGORITHM_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/base_frame_generation_algorithm_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/base_frame_generation_algorithm_impl.h index 26c7bdd16..f914c4627 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/base_frame_generation_algorithm_impl.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/base_frame_generation_algorithm_impl.h @@ -42,11 +42,13 @@ inline cv::Vec3b rgb(const cv::Vec3b &v) { template void BaseFrameGenerationAlgorithm::generate_frame_from_events(EventIt it_begin, EventIt it_end, cv::Mat &frame, const uint32_t accumulation_time_us, - const Metavision::ColorPalette &palette) { + const Metavision::ColorPalette &palette, int flags) { const cv::Vec4b bg_color = get_bgra_color(palette, Metavision::ColorType::Background); const std::array off_on_colors{get_bgra_color(palette, Metavision::ColorType::Negative), get_bgra_color(palette, Metavision::ColorType::Positive)}; - int flags = (palette != Metavision::ColorPalette::Gray ? Parameters::BGR : Parameters::GRAY); + if (flags == 0) { + flags = (palette != Metavision::ColorPalette::Gray ? Parameters::BGR : Parameters::GRAY); + } // Process the entire range of events if the accumulation time is set to zero, or if there's no events. // Otherwise, find the first event to process in the desired time interval [t-dt, t[ diff --git a/sdk/modules/driver/cpp/src/erc_module.cpp b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/contrast_map_generation_algorithm_impl.h similarity index 69% rename from sdk/modules/driver/cpp/src/erc_module.cpp rename to sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/contrast_map_generation_algorithm_impl.h index e3de9d3c2..ad474f5be 100644 --- a/sdk/modules/driver/cpp/src/erc_module.cpp +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/contrast_map_generation_algorithm_impl.h @@ -9,34 +9,18 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include - -#include "metavision/sdk/driver/erc_module.h" +#ifndef METAVISION_SDK_CORE_CONTRAST_MAP_GENERATION_ALGORITHM_IMPL_H +#define METAVISION_SDK_CORE_CONTRAST_MAP_GENERATION_ALGORITHM_IMPL_H namespace Metavision { -ErcModule::ErcModule(I_ErcModule *erc) : pimpl_(erc) {} - -ErcModule::~ErcModule() {} - -bool ErcModule::enable(bool b) { - return pimpl_->enable(b); -} - -bool ErcModule::is_enabled() { - return (pimpl_->is_enabled()); -} - -void ErcModule::set_cd_event_rate(uint32_t events_per_sec) { - pimpl_->set_cd_event_rate(events_per_sec); -} - -uint32_t ErcModule::get_cd_event_rate() { - return (pimpl_->get_cd_event_rate()); -} - -I_ErcModule *ErcModule::get_facility() const { - return pimpl_; +template +void ContrastMapGenerationAlgorithm::process_events(InputIt it_begin, InputIt it_end) { + for (auto it = it_begin; it != it_end; ++it) { + process_event(*it); + } } } // namespace Metavision + +#endif // METAVISION_SDK_CORE_CONTRAST_MAP_GENERATION_ALGORITHM_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_diff_generation_algorithm_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_diff_generation_algorithm_impl.h index 86667813f..8983c27ae 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_diff_generation_algorithm_impl.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_diff_generation_algorithm_impl.h @@ -12,23 +12,56 @@ #ifndef METAVISION_SDK_CORE_EVENT_FRAME_DIFF_GENERATION_ALGORITHM_IMPL_H #define METAVISION_SDK_CORE_EVENT_FRAME_DIFF_GENERATION_ALGORITHM_IMPL_H +#include "metavision/sdk/core/algorithms/event_frame_diff_generation_algorithm.h" + namespace Metavision { template -void EventFrameDiffGenerationAlgorithm::process_events(InputIt it_begin, InputIt it_end) { - auto &diff = frame_.get_data(); - for (auto it = it_begin; it != it_end; ++it) { - const unsigned int idx = it->x + it->y * frame_.get_config().width; - int8_t &sum_polarities = diff[idx]; - const bool should_rollover = - (sum_polarities == min_val_ && it->p == 0) || (sum_polarities == max_val_ && it->p == 1); - if (!should_rollover) { - sum_polarities += (it->p == 0 ? -1 : 1); - } else if (allow_rollover_) { - sum_polarities = (it->p == 0 ? max_val_ : min_val_); - } else { // sum_polarities is saturated - } - } +EventFrameDiffGenerationAlgorithm::EventFrameDiffGenerationAlgorithm(unsigned int width, unsigned int height, + unsigned int bit_size, + bool allow_rollover, + timestamp min_generation_period_us) : + allow_rollover_(allow_rollover), + min_generation_period_us_(min_generation_period_us), + frame_(height, width, bit_size), + processor_(width, height, -(1 << (bit_size - 1)), (1 << (bit_size - 1)) - 1, allow_rollover) { + reset_wrapper(); +} + +template +void EventFrameDiffGenerationAlgorithm::process_events(InputIt it_begin, InputIt it_end) { + processor_.process_events(0, it_begin, it_end, diff_wrapper_); +} + +template +void EventFrameDiffGenerationAlgorithm::generate(RawEventFrameDiff &frame) { + const auto &cfg = frame_.get_config(); + frame.reset(cfg.height, cfg.width, cfg.bit_size); // Prepare next accumulating frame + frame.swap(frame_); // Swap internal event frame with provided one + reset_wrapper(); +} + +template +bool EventFrameDiffGenerationAlgorithm::generate(timestamp ts_event_frame, RawEventFrameDiff &event_frame) { + if (is_ts_prev_set_ && ts_event_frame - ts_prev_ < min_generation_period_us_) + return false; + is_ts_prev_set_ = true; + ts_prev_ = ts_event_frame; + generate(event_frame); + return true; +} + +template +void EventFrameDiffGenerationAlgorithm::reset() { + frame_.reset(); + reset_wrapper(); + is_ts_prev_set_ = false; +} + +template +void EventFrameDiffGenerationAlgorithm::reset_wrapper() { + diff_wrapper_.create(processor_.get_output_shape(), processor_.get_output_type(), + reinterpret_cast(frame_.get_data().data()), false); } } // namespace Metavision diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_histo_generation_algorithm_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_histo_generation_algorithm_impl.h index 1f1bb384e..306874410 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_histo_generation_algorithm_impl.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_frame_histo_generation_algorithm_impl.h @@ -12,23 +12,64 @@ #ifndef METAVISION_SDK_CORE_EVENT_FRAME_HISTO_GENERATION_ALGORITHM_IMPL_H #define METAVISION_SDK_CORE_EVENT_FRAME_HISTO_GENERATION_ALGORITHM_IMPL_H +#include "metavision/sdk/core/algorithms/event_frame_histo_generation_algorithm.h" + namespace Metavision { template -void EventFrameHistoGenerationAlgorithm::process_events(InputIt it_begin, InputIt it_end) { - const auto &cfg = frame_unpacked_.get_config(); - auto &histo = frame_unpacked_.get_data(); - for (auto it = it_begin; it != it_end; ++it) { - const unsigned int idx = it->p + (it->x + it->y * cfg.width) * 2; - const uint8_t sum_max = (it->p == 0 ? sum_max_neg_ : sum_max_pos_); - uint8_t &sum_events = histo[idx]; - if (sum_events <= sum_max - 1) { - ++sum_events; - } else { // sum_events is saturated +EventFrameHistoGenerationAlgorithm::EventFrameHistoGenerationAlgorithm(unsigned width, unsigned height, + unsigned channel_bit_neg, + unsigned channel_bit_pos, bool packed, + timestamp min_generation_period_us) : + cfg_({width, height, {channel_bit_neg, channel_bit_pos}, packed}), + min_generation_period_us_(min_generation_period_us), + frame_unpacked_(height, width, channel_bit_neg, channel_bit_pos, false), + processor_(width, height, (1 << channel_bit_neg) - 1, (1 << channel_bit_pos) - 1) { + if (channel_bit_neg <= 0 || channel_bit_pos <= 0 || channel_bit_neg + channel_bit_pos > 8) + throw std::runtime_error("Incorrect input channel_bit_neg and channel_bit_pos."); +} + +template +void EventFrameHistoGenerationAlgorithm::process_events(InputIt it_begin, InputIt it_end) { + processor_.process_events(it_begin, it_end, frame_unpacked_); +} + +template +void EventFrameHistoGenerationAlgorithm::generate(RawEventFrameHisto &frame) { + if (cfg_.packed) { + frame.reset(cfg_.height, cfg_.width, cfg_.channel_bit_size[0], cfg_.channel_bit_size[1], + cfg_.packed); // Prepare target frame + auto &histo_out = frame.get_data(); + auto &histo_unpacked = frame_unpacked_.get_data(); + for (unsigned int npixels = cfg_.width * cfg_.height, idx_px = 0; idx_px < npixels; ++idx_px) { + const uint8_t bitval_neg = histo_unpacked[2 * idx_px]; + const uint8_t bitval_pos = histo_unpacked[2 * idx_px + 1]; + histo_out[idx_px] = (bitval_pos << cfg_.channel_bit_size[0]) | (bitval_neg); } + frame_unpacked_.reset(); // Prepare next accumulating frame + } else { + frame.reset(cfg_.height, cfg_.width, cfg_.channel_bit_size[0], cfg_.channel_bit_size[1], + cfg_.packed); // Prepare next accumulating frame + frame.swap(frame_unpacked_); // Swap internal event frame with provided one } } +template +bool EventFrameHistoGenerationAlgorithm::generate(timestamp ts_event_frame, RawEventFrameHisto &event_frame) { + if (is_ts_prev_set_ && ts_event_frame - ts_prev_ < min_generation_period_us_) + return false; + is_ts_prev_set_ = true; + ts_prev_ = ts_event_frame; + generate(event_frame); + return true; +} + +template +void EventFrameHistoGenerationAlgorithm::reset() { + frame_unpacked_.reset(); + is_ts_prev_set_ = false; +} + } // namespace Metavision #endif // METAVISION_SDK_CORE_EVENT_FRAME_HISTO_GENERATION_ALGORITHM_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_rescaler_algorithm_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_rescaler_algorithm_impl.h new file mode 100644 index 000000000..a2bebe4e0 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/event_rescaler_algorithm_impl.h @@ -0,0 +1,33 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DETAIL_EVENT_RESCALER_ALGORITHM_IMPL_H +#define METAVISION_SDK_CORE_DETAIL_EVENT_RESCALER_ALGORITHM_IMPL_H + +#include "metavision/sdk/core/algorithms/event_rescaler_algorithm.h" + +namespace Metavision { + +template +OutputIt EventRescalerAlgorithm::process_events(InputIt begin, InputIt end, OutputIt out_begin) const { + for (auto it = begin; it != end; ++it) { + auto ev = *it; + ev.x = static_cast(ev.x * scale_width_ + offset_width_); + ev.y = static_cast(ev.y * scale_height_ + offset_height_); + *out_begin = ev; + ++out_begin; + } + return out_begin; +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_DETAIL_EVENT_RESCALER_ALGORITHM_IMPL_H diff --git a/sdk/modules/driver/cpp/src/event_trail_filter_module.cpp b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/events_integration_algorithm_impl.h similarity index 69% rename from sdk/modules/driver/cpp/src/event_trail_filter_module.cpp rename to sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/events_integration_algorithm_impl.h index fb6b28b15..1edfb13fd 100644 --- a/sdk/modules/driver/cpp/src/event_trail_filter_module.cpp +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/events_integration_algorithm_impl.h @@ -9,24 +9,23 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/event_trail_filter_module.h" +#ifndef METAVISION_SDK_CORE_EVENTS_INTEGRATION_ALGORITHM_IMPL_H +#define METAVISION_SDK_CORE_EVENTS_INTEGRATION_ALGORITHM_IMPL_H -namespace Metavision { - -EventTrailFilterModule::EventTrailFilterModule(I_EventTrailFilterModule *noise_filter) : pimpl_(noise_filter) {} - -EventTrailFilterModule::~EventTrailFilterModule() {} - -std::set EventTrailFilterModule::get_available_types() const { - return pimpl_->get_available_types(); -} +#include "metavision/sdk/core/utils/fast_math_functions.h" -bool EventTrailFilterModule::enable(bool state) { - return pimpl_->enable(state); -} +namespace Metavision { -I_EventTrailFilterModule *EventTrailFilterModule::get_facility() const { - return pimpl_; +template +void EventsIntegrationAlgorithm::process_events(InputIt it_begin, InputIt it_end) { + for (auto it = it_begin; it != it_end; ++it) { + integrate_event(*it); + } + if (it_begin != it_end) { + last_t_ = std::prev(it_end)->t; + } } } // namespace Metavision + +#endif // METAVISION_SDK_CORE_EVENTS_INTEGRATION_ALGORITHM_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/file_producer_algorithm_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/file_producer_algorithm_impl.h deleted file mode 100644 index 2c2cd4074..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/file_producer_algorithm_impl.h +++ /dev/null @@ -1,417 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_DETAIL_FILE_PRODUCER_ALGORITHM_IMPL_H -#define METAVISION_SDK_CORE_DETAIL_FILE_PRODUCER_ALGORITHM_IMPL_H - -#include "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/base/utils/generic_header.h" - -namespace Metavision { - -template -template -inline void FileProducerAlgorithmT::process_events(OutputIt d_first, timestamp ts) { - // using Event = typename std::iterator_traits::value_type; - // decltype(*d_first) Event; - if (version_ >= 2) { - process_output( - ts, d_first, Event::read_event, - [](void *data, timestamp delta_ts) { return static_cast(data)->ts + delta_ts; }, - [](void *data, int increment) { return static_cast(data) + increment; }); - } else { - process_output( - ts, d_first, Event::read_event_v1, - [](void *data, timestamp delta_ts) { - return static_cast(data)->ts + delta_ts; - }, - [](void *data, int increment) { return static_cast(data) + increment; }); - } -} - -template -inline timestamp FileProducerAlgorithmT::get_time_at(timestamp time_window, bool backward) { - if (time_last_event_ < 0) { - // Need to parse all the file to get the time of the last event (can't just jump - // directly to the end because we would miss the overflows - if (version_ >= 2) { - loop_through_file(Event::read_event, [](void *data, uint64_t increment) { - return static_cast(data) + increment; - }); - } else { - loop_through_file(Event::read_event_v1, [](void *data, uint64_t increment) { - return static_cast(data) + increment; - }); - } - } - return (backward) ? std::max(time_first_event_, time_last_event_ - time_window) : - std::min(time_last_event_, time_first_event_ + time_window); -} - -template -inline void FileProducerAlgorithmT::initialize() { - if (current_event_ < n_tot_events_) { - file_->read(&last_buffer_[0], ev_size_); - if (version_ >= 2) { - time_first_event_ = static_cast(last_data_)->ts + delta_ts_overflow_; - } else { - time_first_event_ = static_cast(last_data_)->ts + delta_ts_overflow_; - } - } - - time_start_event_ = time_first_event_; - time_last_event_read_ = time_first_event_; -} - -template -inline void FileProducerAlgorithmT::start_at_time(timestamp start_time) { - std::function get_time; - std::function read_event; - std::function increment_data; - - if (version_ >= 2) { - get_time = [](void *data, timestamp delta_ts) { - return static_cast(data)->ts + delta_ts; - }; - read_event = Event::read_event; - increment_data = [](void *data, uint64_t increment) { - return static_cast(data) + increment; - }; - } else { - get_time = [](void *data, timestamp delta_ts) { - return static_cast(data)->ts + delta_ts; - }; - read_event = Event::read_event_v1; - increment_data = [](void *data, uint64_t increment) { - return static_cast(data) + increment; - }; - } - - if (time_last_event_ < 0) { - // Need to parse all the file to get the time of the last event (can't just jump - // directly to the end because we would miss the overflows - loop_through_file(read_event, increment_data); - } - - if (start_time <= time_first_event_) { - position_start_event = position_first_event_; - start_event_ = 0; - origin_ = start_time; - } else if (start_time > time_last_event_) { - position_start_event = (uint64_t)position_first_event_ + ev_size_ * n_tot_events_; - start_event_ = n_tot_events_; - origin_ = 0; // start_time; - } else { - // Binary search - - uint64_t start_ev = 0; - uint64_t end_ev = n_tot_events_ - 1; - - if (events_overflows.size() > 0) { - n_times_overflows_ = start_time / MAX_TIMESTAMP_32; - - if (n_times_overflows_ > 0) { - start_ev = events_overflows[n_times_overflows_ - 1]; - } - - delta_ts_overflow_ = n_times_overflows_ * OVERFLOW_LENGTH; - - if (n_times_overflows_ < events_overflows.size()) { - end_ev = events_overflows[n_times_overflows_]; - } - } - uint64_t curr_ev; - if (events_from_ram_) { - while (start_ev < end_ev - 1) { - curr_ev = (start_ev + end_ev) / 2; - last_data_ = (&vrawevents_[times_event_in_vrawevents_ * curr_ev]); - if (get_time(last_data_, delta_ts_overflow_) >= start_time) { - end_ev = curr_ev; - } else { - start_ev = curr_ev; - } - } - } else { - while (start_ev < end_ev - 1) { - curr_ev = (start_ev + end_ev) / 2; - file_->seekg((uint64_t)position_first_event_ + ev_size_ * curr_ev); - file_->read(&last_buffer_[0], ev_size_); - if (get_time(last_data_, delta_ts_overflow_) >= start_time) { - end_ev = curr_ev; - } else { - start_ev = curr_ev; - } - } - } - start_event_ = end_ev; - position_start_event = (uint64_t)position_first_event_ + ev_size_ * start_event_; - origin_ = start_time; - } - - current_event_ = start_event_; - - if (events_from_ram_) { - if (current_event_ < n_tot_events_) { - last_data_ = &vrawevents_[start_event_ * times_event_in_vrawevents_]; - } - } else { - file_->seekg(position_start_event); - if (current_event_ < n_tot_events_) { - file_->read(&last_buffer_[0], ev_size_); - } - } - time_start_event_ = get_time(last_data_, delta_ts_overflow_); - time_last_event_read_ = time_first_event_; -} - -template -template -inline void FileProducerAlgorithmT::process_output(timestamp ts, OutputIt d_first, - const FunctionRead &read_event, const FunctionTime &get_time, - const FunctionIncrement &increment_data) { - // Fill the buffer with current events - while (current_event_ < n_tot_events_ && get_time(last_data_, delta_ts_overflow_) + delta_ts_loop_ - origin_ < ts) { - // Read the current event - Event ev = read_event(last_data_, delta_ts_overflow_ + delta_ts_loop_ - origin_); - - if (time_last_event_read_ - get_time(last_data_, delta_ts_overflow_) >= MAX_TIMESTAMP_32 - threshold_) { - // Looped! - if (time_last_event_ < 0) { - events_overflows.push_back(current_event_); - } - ++n_times_overflows_; - delta_ts_overflow_ = n_times_overflows_ * OVERFLOW_LENGTH; - - ev = read_event(last_data_, delta_ts_overflow_ + delta_ts_loop_ - origin_); - } - - *d_first = ev; - ++d_first; - - time_last_event_read_ = get_time(last_data_, delta_ts_overflow_); - - ++current_event_; - - // If we have to loop and we arrived at the last element, restart from the beginning - if (current_event_ == n_tot_events_) { // End of file - if (time_last_event_ < 0) { - time_last_event_ = time_last_event_read_; - } - - if (time_last_event_ + loop_delay_ - origin_ > get_max_loop_length()) { - set_max_loop_length(time_last_event_ + loop_delay_ - origin_); - } - - if (!loop_) { - return; - } - ++n_loop; - current_event_ = start_event_; - n_times_overflows_ = time_start_event_ / MAX_TIMESTAMP_32; - delta_ts_overflow_ = n_times_overflows_ * OVERFLOW_LENGTH; - time_last_event_read_ = time_start_event_; - - delta_ts_loop_ = n_loop * get_max_loop_length(); - - if (events_from_ram_) { - int n = sizeof(ev_size_) / sizeof(typename decltype(vrawevents_)::value_type); - last_data_ = &vrawevents_[start_event_ * n]; // TODO put start_event_ * size instead - } else { - file_->seekg(position_start_event); - } - } - // no need to check if cur_ev_ < ev_num (if ev_num == 0 we do not enter the while, - // and if cur_ev_ was == ev_num_ then in the previous if we set it to 0) - if (events_from_ram_) { - last_data_ = increment_data(last_data_, 1); - } else { - file_->read(&last_buffer_[0], ev_size_); - } - } -} - -template -template -inline void FileProducerAlgorithmT::loop_through_file(const FunctionRead &read_event, - const FunctionIncrement &increment_data) { - MV_SDK_LOG_INFO() << Log::no_space << "Looping through file " << filename_ << ": this may take some time ..."; - - if (events_from_ram_) { - void *data = (&vrawevents_[0]); // going to first event - timestamp last_time = time_first_event_; - - events_overflows.clear(); - for (uint64_t curr_ev = 1; curr_ev < n_tot_events_; ++curr_ev) { - data = increment_data(data, 1); - - Event ev = read_event(data, 0); - if (last_time - ev.t >= MAX_TIMESTAMP_32 - threshold_) { - events_overflows.push_back(curr_ev); - } - last_time = ev.t; - } - - time_last_event_ = last_time + events_overflows.size() * OVERFLOW_LENGTH; - - } else { - std::streampos current_position = file_->tellg(); // Get the current position in the file - - uint64_t curr_ev = current_event_; - - std::vector buffer(ev_size_); - void *data = static_cast(&buffer[0]); - - file_->seekg(position_first_event_); // Reset the position at the first event - file_->read(&buffer[0], ev_size_); // Read the first event - - timestamp last_time = time_first_event_; - - events_overflows.clear(); - for (curr_ev = 1; curr_ev < n_tot_events_; ++curr_ev) { - file_->read(&buffer[0], ev_size_); // read data from file - - Event ev = read_event(data, 0); - if (last_time - ev.t >= MAX_TIMESTAMP_32 - threshold_) { - events_overflows.push_back(curr_ev); - } - - last_time = ev.t; - } - - time_last_event_ = last_time + events_overflows.size() * OVERFLOW_LENGTH; - - file_->seekg(current_position); // Reset the position - } - - MV_SDK_LOG_INFO() << "Total length of file is" << Log::no_space << time_last_event_ << "us"; -} - -template -inline FileProducerAlgorithmT::FileProducerAlgorithmT(std::string filename, bool loop, timestamp loop_delay) : - file_(new std::ifstream(filename.c_str(), std::ios::binary)), - filename_(filename), - loop_(loop), - loop_delay_(loop_delay) { - if (!file_->is_open()) { - throw std::runtime_error("Could not open file " + filename_); - } - - // Get size and type of the events - unsigned char ev_type, ev_size; - // Parse the header, if present - GenericHeader header_parser(*file_); - - // If no header was found, consider the file to be an old file without - // event information at the beginning and thus only containing Event2ds - if (header_parser.empty()) { - ev_type = 0; - ev_size = 8; - } else { - ev_type = 0; - ev_size = 8; - // Read file infos: the first two characters are the info on event type and size - if (file_) - file_->read((char *)&ev_type, 1); - if (file_) - file_->read((char *)&ev_size, 1); - } - ev_size_ = ev_size; // Size of the raw event (in bytes --> ex if the RawEvent is a structure of 64 bit, ev_size_ - // would be 8) - - // allocate reading buffer - last_buffer_.reserve(ev_size_); - - // Look for the version, if any - auto value = header_parser.get_field("Version"); - if (!value.empty()) - version_ = std::stoi(value); - - value = header_parser.get_field("Width"); - width_ = value.empty() ? 304 : std::stoi(value); - - value = header_parser.get_field("Height"); - height_ = value.empty() ? 240 : std::stoi(value); - - date_ = header_parser.get_date(); - - last_data_ = static_cast(&last_buffer_[0]); - - // Determine the number of events in file - position_first_event_ = file_->tellg(); // Get the current position in the file - file_->seekg(0, std::ios::end); // Go to the end of the file - n_tot_events_ = (file_->tellg() - position_first_event_) / (long long)ev_size_; // Compute the number of events - file_->seekg(position_first_event_); // Reset the position at the first event - - if (n_tot_events_ == 0) { - MV_SDK_LOG_WARNING() << "No events found in file" << filename_; - } - - start_event_ = 0; - current_event_ = start_event_; - position_start_event = position_first_event_; - - times_event_in_vrawevents_ = sizeof(ev_size_) / sizeof(typename decltype(vrawevents_)::value_type); - initialize(); -} - -template -inline FileProducerAlgorithmT::~FileProducerAlgorithmT() { - file_->close(); -} - -template -inline bool FileProducerAlgorithmT::is_done() { - return current_event_ >= n_tot_events_; -} - -template -inline uint64_t FileProducerAlgorithmT::get_n_tot_ev() const { - return n_tot_events_; -} - -template -inline void FileProducerAlgorithmT::reset_max_loop_length() { - set_max_loop_length(0); -} - -template -inline void FileProducerAlgorithmT::load_to_ram() { - events_from_ram_ = true; - file_->seekg(position_start_event); - file_->read(&last_buffer_[0], ev_size_); - vrawevents_.clear(); - while (*file_) { - uint8_t *p = static_cast(last_data_); - vrawevents_.insert(vrawevents_.end(), p, p + times_event_in_vrawevents_); - - file_->read(&last_buffer_[0], ev_size_); - } - last_data_ = (&vrawevents_[0]); -} - -template -inline int FileProducerAlgorithmT::get_width() const { - return width_; -} - -template -inline int FileProducerAlgorithmT::get_height() const { - return height_; -} - -template -inline std::string FileProducerAlgorithmT::get_date() const { - return date_; -} - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_DETAIL_FILE_PRODUCER_ALGORITHM_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_diff_generation_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_diff_generation_algorithm.h index 026034e41..dbe977ce9 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_diff_generation_algorithm.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_diff_generation_algorithm.h @@ -14,6 +14,7 @@ #include "metavision/sdk/base/events/event_cd.h" #include "metavision/sdk/base/events/raw_event_frame_diff.h" +#include "metavision/sdk/core/preprocessors/hardware_diff_processor.h" namespace Metavision { @@ -22,6 +23,8 @@ namespace Metavision { /// This class implements the algorithm for producing diff event frames from a stream of events. This algorithm /// computes, at each pixel, the sum of polarities of all processed events. /// Generated event frames are stored using row-major convention. +/// @tparam InputIt The type of the input iterator for the range of events. +template class EventFrameDiffGenerationAlgorithm { public: /// @brief Constructor for the EventFrameDiffGenerationAlgorithm class. @@ -47,10 +50,8 @@ class EventFrameDiffGenerationAlgorithm { } /// @brief Processes a range of events and updates the sum of polarities at each pixel. - /// @tparam InputIt The type of the input iterator for the range of events. /// @param it_begin An iterator pointing to the beginning of the events range. /// @param it_end An iterator pointing to the end of the events range. - template void process_events(InputIt it_begin, InputIt it_end); /// @brief Retrieves the diff event frame aggregating the events processed so far, and resets the @@ -74,12 +75,15 @@ class EventFrameDiffGenerationAlgorithm { void reset(); private: + void reset_wrapper(); + const bool allow_rollover_; - const int8_t min_val_, max_val_; const timestamp min_generation_period_us_; bool is_ts_prev_set_ = false; timestamp ts_prev_ = -1; + HardwareDiffProcessor processor_; RawEventFrameDiff frame_; + Tensor diff_wrapper_; }; } // namespace Metavision diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_histo_generation_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_histo_generation_algorithm.h index b96ecb91e..6409e436e 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_histo_generation_algorithm.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_frame_histo_generation_algorithm.h @@ -12,8 +12,9 @@ #ifndef METAVISION_SDK_CORE_EVENT_FRAME_HISTO_GENERATION_ALGORITHM_H #define METAVISION_SDK_CORE_EVENT_FRAME_HISTO_GENERATION_ALGORITHM_H -#include "metavision/sdk/base/events/event_cd.h" #include "metavision/sdk/base/events/raw_event_frame_histo.h" +#include "metavision/sdk/base/utils/timestamp.h" +#include "metavision/sdk/core/preprocessors/hardware_histo_processor.h" namespace Metavision { @@ -25,6 +26,8 @@ namespace Metavision { /// polarities. The histogram values will saturate if more events than the maximum representable integers are received /// at a given pixel for a given polarity. Generated event frames are stored using row-major convention with interleaved /// channels for each polarity. +/// @tparam InputIt The type of the input iterator for the range of events to process. +template class EventFrameHistoGenerationAlgorithm { public: /// @brief Constructor for the EventFrameHistoGenerationAlgorithm class. @@ -50,10 +53,8 @@ class EventFrameHistoGenerationAlgorithm { } /// @brief Processes a range of events and updates the sum of events at each pixel & polarity. - /// @tparam InputIt The type of the input iterator for the range of events. /// @param it_begin An iterator pointing to the beginning of the events range. /// @param it_end An iterator pointing to the end of the events range. - template void process_events(InputIt it_begin, InputIt it_end); /// @brief Retrieves the histo event frame aggregating events since the last call to @p generate, and resets the @@ -79,7 +80,7 @@ class EventFrameHistoGenerationAlgorithm { void reset(); private: - const uint8_t sum_max_neg_, sum_max_pos_; + HardwareHistoProcessor processor_; const RawEventFrameHistoConfig cfg_; const timestamp min_generation_period_us_; bool is_ts_prev_set_ = false; diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_rescaler_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_rescaler_algorithm.h new file mode 100644 index 000000000..a468ba28a --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/event_rescaler_algorithm.h @@ -0,0 +1,55 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_EVENT_RESCALER_ALGORITHM_H +#define METAVISION_SDK_CORE_EVENT_RESCALER_ALGORITHM_H + +#include +#include + +namespace Metavision { + +/// @brief Base class to operate a rescaling of events locations in both horizontal and vertical directions +class EventRescalerAlgorithm { +public: + /// @brief Constructor + /// @param scale_width The horizontal scale for events + /// @param scale_height The vertical scale for events + EventRescalerAlgorithm(float scale_width, float scale_height) : + scale_width_(scale_width), + scale_height_(scale_height), + offset_width_((scale_width < 1.f) ? 0.f : 0.5f), + offset_height_((scale_height < 1.f) ? 0.f : 0.5f) { + if (scale_width <= 0.f || scale_height <= 0) + throw std::runtime_error("Provided W/H scales should be > 0. Got " + std::to_string(scale_width) + " and " + + std::to_string(scale_height)); + } + + /// @brief Processes the input events and fills the output iterator with rescaled events + /// @tparam InputIt The input event iterator type + /// @tparam OutputIt The output event iterator type (typically, a vector inserter) + /// @param begin Iterator pointing to the first event in the stream + /// @param end Iterator pointing to the past-the-end element in the stream + /// @param out_begin Iterator to the first rescaled event + /// @return The iterator to the past-the-last rescaled event + template + OutputIt process_events(InputIt begin, InputIt end, OutputIt out_begin) const; + +protected: + const float scale_width_, scale_height_; + const float offset_width_, offset_height_; +}; + +} // namespace Metavision + +#include "metavision/sdk/core/algorithms/detail/event_rescaler_algorithm_impl.h" + +#endif // METAVISION_SDK_CORE_EVENT_RESCALER_ALGORITHM_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/events_integration_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/events_integration_algorithm.h new file mode 100644 index 000000000..dfd596dec --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/events_integration_algorithm.h @@ -0,0 +1,77 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_EVENTS_INTEGRATION_ALGORITHM_H +#define METAVISION_SDK_CORE_EVENTS_INTEGRATION_ALGORITHM_H + +#include +#include "metavision/sdk/base/events/event_cd.h" + +namespace Metavision { + +/// @brief Class to integrate events into a grayscale frame +class EventsIntegrationAlgorithm { +public: + /// @brief Constructor + /// @param width Width of the input event stream. + /// @param height Height of the input event stream. + /// @param decay_time Time constant for the exponential decay of the integrated grayscale values. + /// @param contrast_on Contrast value for ON events. + /// @param contrast_off Contrast value for OFF events. If non-positive, the contrast is set to the inverse of + /// the @p contrast_on value. + /// @param tonemapping_max_ev_count Maximum number of events to consider for tonemapping to 8-bits range. + /// @param gaussian_blur_kernel_radius Radius of the Gaussian blur kernel. If non-positive, no blur is applied. + /// @param diffusion_weight Weight for slowly diffusing 4-neighboring intensities into the central ones, to smooth + /// reconstructed intensities in the case of static camera. Clamped to [0; 0.25], 0 meaning no diffusion and 0.25 + /// meaning ignoring central intensity. + EventsIntegrationAlgorithm(unsigned int width, unsigned int height, timestamp decay_time = 1'000'000, + float contrast_on = 1.2f, float contrast_off = -1, int tonemapping_max_ev_count = 5, + int gaussian_blur_kernel_radius = 1, float diffusion_weight = 0.f); + + /// @brief Processes a range of events + /// @tparam InputIt Iterator type. + /// @param it_begin Iterator pointing to the first event to process. + /// @param it_end Iterator pointing to the end of the range of events to process. + template + void process_events(InputIt it_begin, InputIt it_end); + + /// @brief Generates the grayscale frame at the timestamp of the last received event. + void generate(cv::Mat &grayscale_frame); + + /// @brief Resets the internal state + void reset(); + +private: + void integrate_event(const EventCD &e); + void diffuse_intensities(); + + const unsigned int width_; + const unsigned int height_; + const int gaussian_blur_kernel_radius_; + const float diffusion_weight_; + const timestamp decay_time_; + const std::array log_contrast_; + const float tonemapping_factor_; + const std::vector exp_decay_lut_; + + struct PxState { + timestamp last_t = 0; + float logI = 0; + }; + std::vector states_; + timestamp last_t_; +}; + +} // namespace Metavision + +#include "metavision/sdk/core/algorithms/detail/events_integration_algorithm_impl.h" + +#endif // METAVISION_SDK_CORE_EVENTS_INTEGRATION_ALGORITHM_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/file_producer_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/file_producer_algorithm.h deleted file mode 100644 index 8f56adf49..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/file_producer_algorithm.h +++ /dev/null @@ -1,154 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_FILE_PRODUCER_ALGORITHM_H -#define METAVISION_SDK_CORE_FILE_PRODUCER_ALGORITHM_H - -#include -#include -#include -#include -#include -#include -#include - -#include "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/base/utils/timestamp.h" -#include "metavision/sdk/base/events/event2d.h" - -namespace Metavision { - -template -class FileProducerAlgorithmT { -public: - /// @brief Builds a new FileProducerAlgorithmT object - /// @param filename Name of the file to read data from - /// @param loop If true, the reading from the file will be looped - /// @param loop_delay Time interval (in us) between two consecutive loops - FileProducerAlgorithmT(std::string filename, bool loop = false, timestamp loop_delay = 0); - - /// @brief Destructor - ~FileProducerAlgorithmT(); - - /// @brief Processes events until a given timestamp - template - inline void process_events(OutputIt d_first, timestamp ts); - - /// @brief If all events have been processed, returns true - bool is_done(); - - /// @brief Gets the timestamp in a given time window - /// @param time_window Time difference (in us) with the first (or last) event in the file - /// @param backward If true, search will be from the end of the file (thus giving time last event - time_window) - inline timestamp get_time_at(timestamp time_window, bool backward); - - /// @brief Starts reproducing the file from a given time - /// @param start_time Start time - inline void start_at_time(timestamp start_time); - - /// @brief Gets the total number of events in the file - uint64_t get_n_tot_ev() const; - - /// @brief Resets the loop length to zero - static void reset_max_loop_length(); - - /// @brief Loads file events to ram - void load_to_ram(); - - /// @brief Gets the width of the sensor producer that recorded the data - /// @return Width of the sensor - int get_width() const; - - /// @brief Gets the height of the sensor producer that recorded the data - /// @return Height of the sensor - int get_height() const; - - /// @brief Gets the date - /// @return String of the form YYYY-MM-DD h:m:s (example: 2017-03-08 13:36:44 ) (UTC time) - /// @note If the date was not found in the header of the file, an empty string is returned - std::string get_date() const; - -protected: - inline void initialize(); - -private: - static timestamp &get_max_loop_length() { - static timestamp max_loop_length = 0; - return max_loop_length; - } - - static void set_max_loop_length(timestamp t) { - get_max_loop_length() = t; - } - - template - inline void process_output(timestamp ts, OutputIt d_first, const FunctionRead &read_event, - const FunctionTime &get_time, const FunctionIncrement &increment_data); - - template - inline void loop_through_file(const FunctionRead &read_event, const FunctionIncrement &increment_data); - - // File info - std::unique_ptr file_; - std::string filename_; - - size_t ev_size_; // Size of a single event stored in the file - - std::streampos position_first_event_; // Position (in the file) of the first event - std::streampos position_start_event; // Position (in the file) of the start event (may be different - // from the position_first_event_ if the function start_at_time is called) - - uint64_t start_event_ = 0; // First event to play (may be different than 0 if the function start_at_time is called) - uint64_t n_tot_events_ = 0; // Tot number of events - uint64_t current_event_ = 0; - timestamp time_last_event_read_ = 0; - - timestamp time_first_event_ = 0, time_last_event_ = -1; - timestamp time_start_event_ = 0; // May be different than time_first_event_ (f the function start_at_time is called) - - timestamp origin_ = 0; - - // OVERFLOW HANDLING - static constexpr timestamp MAX_TIMESTAMP_32 = (1LL << 32) - 1; - static constexpr timestamp threshold_ = (1LL << 30); // check only at the two highest bits - static constexpr timestamp OVERFLOW_LENGTH = MAX_TIMESTAMP_32 + 1; - std::vector events_overflows; // Keep trace of the first events after timestamp overflow - unsigned int n_times_overflows_ = 0; // number of times we have looped the timestamp - timestamp delta_ts_overflow_ = 0; // delta timestamp due to the overflow - - // LOOP HANDLING - bool loop_; - timestamp delta_ts_loop_ = 0; - unsigned int n_loop = 0; // Current loop number - timestamp loop_delay_; // Time between loops - - // READING FROM FILE - void *last_data_; - int version_ = 0; - std::vector last_buffer_; - - // READING FROM RAM - bool events_from_ram_ = false; - std::vector vrawevents_; - int times_event_in_vrawevents_ = 0; // number of elements of the vector vrawevents_ a single event occupies - - int width_ = 0, height_ = 0; - - std::string date_; -}; - -using FileProducerAlgorithm = FileProducerAlgorithmT; - -} // namespace Metavision - -#include "detail/file_producer_algorithm_impl.h" - -#endif // METAVISION_SDK_CORE_FILE_PRODUCER_ALGORITHM_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/stream_logger_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/stream_logger_algorithm.h index 513a32512..98c4094c6 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/stream_logger_algorithm.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/stream_logger_algorithm.h @@ -12,7 +12,7 @@ #ifndef METAVISION_SDK_CORE_STREAM_LOGGER_ALGORITHM_H #define METAVISION_SDK_CORE_STREAM_LOGGER_ALGORITHM_H -#include +#include #include #include #include @@ -32,11 +32,11 @@ class StreamLoggerAlgorithm { public: /// @brief Builds a new StreamLogger object with given geometry - /// @param filename Name of the file to write into. If the file already exists, its previous content will be + /// @param file_path Path of the file to write into. If the file already exists, its previous content will be /// lost. /// @param width Width of the producer /// @param height Height of the producer - inline StreamLoggerAlgorithm(const std::string &filename, std::size_t width, std::size_t height); + inline StreamLoggerAlgorithm(const std::filesystem::path &file_path, std::size_t width, std::size_t height); /// @brief Default destructor ~StreamLoggerAlgorithm() = default; @@ -57,10 +57,10 @@ class StreamLoggerAlgorithm { inline std::int32_t get_split_time_seconds() const; /// @brief Changes the destination file of the logger. - /// @param filename Name of the file to write into. + /// @param file_path Name of the file to write into. /// @param reset_ts If we are currently recording, /// the timestamp used in the last call to update will be considered as timestamp zero - inline void change_destination(const std::string &filename, bool reset_ts = true); + inline void change_destination(const std::filesystem::path &file_path, bool reset_ts = true); /// @brief Exports the information in the input buffer into the StreamLogger /// @tparam InputIt Read-Only input event iterator type. Works for iterators over buffers of @ref Event2d @@ -75,13 +75,9 @@ class StreamLoggerAlgorithm { inline void close(); protected: - /// @brief Changes the destination file internally - /// @param filename Name of the file to write into - inline void set_filename(const std::string &filename); - - /// @brief Returns the StreamLogger file name + /// @brief Returns the StreamLogger file path /// @note If the system is working in split mode, it returns the file used in each iteration - inline std::string get_filename() const; + inline std::filesystem::path get_file_path() const; /// @brief Splits the current file, if the timestamp reach the timeout /// @param ts Current timestamp @@ -91,9 +87,7 @@ class StreamLoggerAlgorithm { std::size_t width_{0}; std::size_t height_{0}; std::size_t split_counter_{0}; - std::string filename_{}; - std::string filename_base_{}; - std::string filename_ext_{}; + std::filesystem::path file_path_{}; std::ofstream output_{}; bool enable_{false}; bool header_written_{false}; @@ -104,11 +98,9 @@ class StreamLoggerAlgorithm { std::vector buffer_{}; }; -inline StreamLoggerAlgorithm::StreamLoggerAlgorithm(const std::string &filename, std::size_t width, +inline StreamLoggerAlgorithm::StreamLoggerAlgorithm(const std::filesystem::path &file_path, std::size_t width, std::size_t height) : - width_(width), height_(height) { - set_filename(filename); -} + width_(width), height_(height), file_path_(file_path) {} inline void StreamLoggerAlgorithm::enable(bool state, bool reset_ts, std::int32_t split_time_seconds) { const auto split_enabled = split_time_seconds != InvalidTimestamp; @@ -132,10 +124,10 @@ inline void StreamLoggerAlgorithm::enable(bool state, bool reset_ts, std::int32_ output_.close(); } - output_.open(get_filename(), std::ios::binary); + output_.open(get_file_path(), std::ios::binary); if (output_.fail()) { throw std::runtime_error( - "Could not open file '" + get_filename() + + "Could not open file '" + get_file_path().string() + " to record. Make sure it is a valid filename and that you have permissions to write it."); } header_written_ = false; @@ -153,13 +145,13 @@ std::int32_t StreamLoggerAlgorithm::get_split_time_seconds() const { return split_timestamp_secs_; } -inline void StreamLoggerAlgorithm::change_destination(const std::string &filename, bool reset_ts) { +inline void StreamLoggerAlgorithm::change_destination(const std::filesystem::path &file_path, bool reset_ts) { const auto previous_state = enable_; if (enable_) { StreamLoggerAlgorithm::enable(false); } - set_filename(filename); + file_path_ = file_path; split_counter_ = 0; StreamLoggerAlgorithm::enable(previous_state, reset_ts, split_timestamp_secs_); } @@ -168,21 +160,16 @@ inline void StreamLoggerAlgorithm::close() { output_.close(); } -inline void StreamLoggerAlgorithm::set_filename(const std::string &filename) { - boost::filesystem::path path(filename); - filename_ = filename; - filename_base_ = path.stem().string(); - filename_ext_ = path.extension().string(); -} - -inline std::string StreamLoggerAlgorithm::get_filename() const { +inline std::filesystem::path StreamLoggerAlgorithm::get_file_path() const { if (split_timestamp_us_ != InvalidTimestamp) { - std::ostringstream split_filename; - split_filename << filename_base_ << "_" << std::setw(4) << std::setfill('0') << std::to_string(split_counter_) - << filename_ext_; - return split_filename.str(); + std::filesystem::path split_file = file_path_.parent_path() / file_path_.stem(); + std::ostringstream split_num_sstr; + split_num_sstr << std::setw(4) << std::setfill('0') << std::to_string(split_counter_); + split_file += split_num_sstr.str(); + split_file.replace_extension(file_path_.extension()); + return split_file; } else { - return filename_; + return file_path_; } } @@ -196,7 +183,7 @@ void StreamLoggerAlgorithm::split_file(timestamp ts) { output_.close(); } - output_.open(get_filename(), std::ios::binary); + output_.open(get_file_path(), std::ios::binary); header_written_ = false; initial_timestamp_ = last_timestamp_; } diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/time_surface_producer_algorithm.h b/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/time_surface_producer_algorithm.h deleted file mode 100644 index 877423571..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/time_surface_producer_algorithm.h +++ /dev/null @@ -1,78 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_TIME_SURFACE_PRODUCER_ALGORITHM_H -#define METAVISION_SDK_CORE_TIME_SURFACE_PRODUCER_ALGORITHM_H - -#include -#include - -#include "metavision/sdk/core/algorithms/async_algorithm.h" -#include "metavision/sdk/core/utils/mostrecent_timestamp_buffer.h" - -namespace Metavision { - -/// @brief Class that produces a @ref MostRecentTimestampBuffer (a.k.a. time surface) from events -/// -/// This algorithm is asynchronous in the sense that it can be configured to produce a time surface every N events, -/// every N microseconds or a mixed condition of both (see @ref AsyncAlgorithm). -/// -/// Like in other asynchronous algorithms, in order to retrieve the produced time surface, the user needs to set a -/// callback that will be called when the above condition is fulfilled. However, as opposed to other algorithms, -/// the user doesn't have here the capacity to take ownership of the produced time surface (using a swap mechanism -/// for example). Indeed, swapping the time surface would make the producer lose the whole history. If the user needs -/// to use the time surface out of the output callback, then a copy must be done. -/// -/// @tparam CHANNELS Number of channels to use for producing the time surface. Only two values are possible for now: 1 -/// or 2. When a 1-channel time surface is used, events with different polarities are stored all together while they are -/// stored separately when using a 2-channels time surface. -template -class TimeSurfaceProducerAlgorithm : public AsyncAlgorithm> { -public: - static_assert(CHANNELS == 1 || CHANNELS == 2, "The timesurface producer is only compatible with 1 or 2 channels"); - - using OutputCb = std::function; - - /// @brief Constructs a new time surface producer - /// @param width Sensor's width - /// @param height Sensor's height - TimeSurfaceProducerAlgorithm(int width, int height); - - /// @brief Sets a callback to retrieve the produced time surface - /// - /// A constant reference of the internal time surface is passed to the callback, allowing to process - /// (i.e. read only) it inside the callback. If the time surface needs to be accessed from outside the callback, - /// then a copy must be done. - /// - /// @param cb The callback called when the time surface is ready - void set_output_callback(const OutputCb &cb); - -private: - friend class AsyncAlgorithm>; - - /// @brief Updates the time surface with the input events - /// @tparam InputIt Type of the iterators pointing to the events - /// @param it_begin Iterator pointing to the beginning of the events buffer - /// @param it_end Iterator pointing to the end of the events buffer - template - inline void process_online(InputIt it_begin, InputIt it_end); - - /// @brief Calls the output callback when the time surface is ready (the output condition is satisfied) - void process_async(const timestamp processing_ts, const size_t n_processed_events); - - MostRecentTimestampBuffer time_surface_; ///< Time surface updated internally - OutputCb output_cb_; ///< Callback called when the time surface is ready -}; -} // namespace Metavision - -#include "metavision/sdk/core/algorithms/detail/time_surface_producer_algorithm_impl.h" - -#endif // METAVISION_SDK_CORE_TIME_SURFACE_PRODUCER_ALGORITHM_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/events/event_bbox.h b/sdk/modules/core/cpp/include/metavision/sdk/core/events/event_bbox.h index 39b17620e..7b3c7687d 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/events/event_bbox.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/events/event_bbox.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_ML_EVENT_BBOX_H -#define METAVISION_SDK_ML_EVENT_BBOX_H +#ifndef METAVISION_SDK_CORE_EVENT_BBOX_H +#define METAVISION_SDK_CORE_EVENT_BBOX_H #include #include diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/events/event_tracked_box.h b/sdk/modules/core/cpp/include/metavision/sdk/core/events/event_tracked_box.h new file mode 100644 index 000000000..c911f43c0 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/events/event_tracked_box.h @@ -0,0 +1,105 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_EVENT_TRACKED_BOX_H +#define METAVISION_SDK_CORE_EVENT_TRACKED_BOX_H + +#include + +#include "metavision/sdk/base/utils/timestamp.h" +#include "metavision/sdk/base/utils/detail/struct_pack.h" +#include "metavision/sdk/base/events/detail/event_traits.h" + +namespace Metavision { + +/// @brief Class representing a spatio-temporal tracked bounding-box event. +struct EventTrackedBox { + /// @brief Constructor + /// @param t Timestamp + /// @param x X coordinate of the top-left corner of the box + /// @param y Y coordinate of the top-left corner of the box + /// @param w Box's Width + /// @param h Box's height + /// @param class_id Box's class label identifier + /// @param track_id Track identifier + /// @param class_confidence Confidence score of the detection + inline EventTrackedBox(timestamp t = 0, float x = 0.f, float y = 0.f, float w = 0.f, float h = 0.f, + unsigned int class_id = 0, unsigned int track_id = 0, float class_confidence = 0) noexcept : + t(t), + x(x), + y(y), + w(w), + h(h), + class_id(class_id), + track_id(track_id), + class_confidence(class_confidence), + tracking_confidence(class_confidence), + last_detection_update_time(t), + nb_detections(1) {} + + /// @brief Writes the tracked box into a csv format + /// @param output Stream to write the tracked box + /// @param sep The separator to use between attributes + void write_csv_line(std::ostream &output, char sep = ' ') const { + output << t << sep << class_id << sep << track_id << sep << x << sep << y << sep << w << sep << h << sep + << class_confidence << sep << tracking_confidence << sep << last_detection_update_time << sep + << nb_detections << std::endl; + } + + /// @brief Serializes an EventBbox into a stream + /// @param output Stream + /// @param e EventBbox to be serialized + /// @return Stream provided as input + friend std::ostream &operator<<(std::ostream &output, const EventTrackedBox &e) { + output << "EventTrackedBox: (" + << "t: " << e.t << " " + << "x: " << e.x << " " + << "y: " << e.y << " " + << "w: " << e.w << " " + << "h: " << e.h << " " + << "class_id: " << e.class_id << " " + << "track_id: " << e.track_id << " " + << "class_confidence: " << e.class_confidence << " " + << "tracking_confidence: " << e.tracking_confidence << " " + << "last_detection_update_time: " << e.last_detection_update_time << " " + << "nb_detections: " << e.nb_detections << ")"; + return output; + } + + /// @brief Updates the last detection timestamp and compute a new track confidence value + /// @param t Timestamp of the new detection + /// @param detection_confidence Detection confidence value + /// @param similarity_box_track Weight applied on the detection to compute track detection + inline void set_last_detection_update(timestamp t, float detection_confidence = 0.5f, + float similarity_box_track = 1.0f) { + last_detection_update_time = t; + class_confidence = detection_confidence; + tracking_confidence += detection_confidence * similarity_box_track; + tracking_confidence = std::min(tracking_confidence, 1.f); + } + + // attributes + timestamp t; ///< Timestamp of the box + float x; ///< X position of the bounding box + float y; ///< Y position of the bounding box + float w; ///< Width of the bounding box + float h; ///< Height of the bounding box + unsigned int class_id; ///< bounding box's class id + int track_id; ///< Track identifier + float class_confidence; ///< Confidence of the detection + float tracking_confidence; ///< Confidence computed from previous detection and matching + timestamp last_detection_update_time; ///< Time of last update of the detection. + int nb_detections; ///< Number of time this box have been seen +}; + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_EVENT_TRACKED_BOX_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/algorithm_stage.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/algorithm_stage.h deleted file mode 100644 index 8e6e4985f..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/algorithm_stage.h +++ /dev/null @@ -1,193 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_ALGORITHM_STAGE_H -#define METAVISION_SDK_CORE_ALGORITHM_STAGE_H - -#include "metavision/sdk/core/pipeline/base_stage.h" - -namespace Metavision { - -/// @brief Stage that wraps an algorithm in the consuming callback -/// -/// The easiest way to use this stage is to use @ref Pipeline::add_algorithm_stage, rather -/// than trying to instantiate it yourself. -/// -/// Be mindful of the order of the template arguments, the output event type is given first, because most of the time -/// the InputEventType is EventCD, while the OutputEventType varies. -/// -/// @tparam Algorithm the type of wrapped algorithm -/// @tparam OutputEventType optionally, the type of event produced by this stage in @ref produce -/// @tparam InputEventType optionally, the type of event consumed by this stage in the consuming callback -template -class AlgorithmStage : public BaseStage { - using InputEventBuffer = std::vector; - using InputEventBufferPool = SharedObjectPool; - using InputEventBufferPtr = typename InputEventBufferPool::ptr_type; - using OutputEventBuffer = std::vector; - using OutputEventBufferPool = SharedObjectPool; - using OutputEventBufferPtr = typename OutputEventBufferPool::ptr_type; - -public: - /// @brief Constructor - /// @param algo The wrapped algorithm for which process will be called - AlgorithmStage(std::unique_ptr &&algo) : algo_(std::move(algo)), enabled_(true) { - init(); - } - - /// @brief Constructor - /// - /// Overload constructor available when the type of event consumed is the same as the type - /// of events produced. - /// - /// @sa @ref enable, @ref disable, @ref set_enabled. - template::value>> - AlgorithmStage(std::unique_ptr &&algo, bool enabled = true) : algo_(std::move(algo)), enabled_(enabled) { - init(); - } - - /// @brief Constructor - /// - /// Overload constructor that simplifies setting the previous stage. - /// - /// @param algo The wrapped algorithm for which process will be called - /// @param prev_stage The previous stage of this stage - AlgorithmStage(std::unique_ptr &&algo, BaseStage &prev_stage) : - BaseStage(prev_stage), - algo_(std::move(algo)), - event_buffer_pool_(OutputEventBufferPool::make_bounded()), - enabled_(true) { - init(); - } - - /// @brief Constructor - /// - /// Overload constructor that simplifies setting the previous stage and is only available when the type of event - /// consumed is the same as the type of events produced. - /// - /// @param algo The wrapped algorithm for which process will be called - /// @param prev_stage The previous stage of this stage - /// @param enabled true if the algorithm is enabled by default, false otherwise - /// @sa @ref enable, @ref disable, @ref set_enabled. - template::value>> - AlgorithmStage(std::unique_ptr &&algo, BaseStage &prev_stage, bool enabled = true) : - BaseStage(prev_stage), - algo_(std::move(algo)), - event_buffer_pool_(OutputEventBufferPool::make_bounded()), - enabled_(enabled) { - init(); - } - - /// @brief Returns the wrapped algorithm - /// @return @p Algorithm & the wrapped algorithm - Algorithm &algo() { - return *algo_; - } - - /// @brief Returns the wrapped algorithm - /// @return @p Algorithm & the wrapped algorithm - const Algorithm &algo() const { - return *algo_; - } - - /// @brief Enables calling the process function of the algorithm in the consuming callback - /// - /// When the algorithm is enabled, the (default) consuming callback calls process on the - /// consumed data and produces as output, the output of the algorithm. - /// When the algorithm is disabled, this stage acts as a passthrough and directly produces the - /// consumed data. - /// Therefore, to avoid mistakes, this function is only available if the type of output event (produced) - /// is the same as the type of input events (consumed). - template::value>> - void enable() { - enabled_ = true; - } - - /// @brief Disables calling the process function of the algorithm in the consuming callback - /// - /// When the algorithm is enabled, the (default) consuming callback calls process on the - /// consumed data and produces as output, the output of the algorithm. - /// When the algorithm is disabled, this stage acts as a passthrough and directly produces the - /// consumed data. - /// Therefore, to avoid mistakes, this function is only available if the type of output event (produced) - /// is the same as the type of input events (consumed). - template::value>> - void disable() { - enabled_ = false; - } - - /// @brief Enable/disables calling the process function of the algorithm in the consuming callback - /// - /// This does the same as calling @ref enable or @ref disable according to the value of @p enabled. - /// @param enabled True if the algorithm should be enabled, false otherwise - template::value>> - void set_enabled(bool enabled) { - enabled_ = enabled; - } - - /// @brief Returns the status of the wrapped algorithm - /// @return true if the algorithm is enabled, false otherwise - template::value>> - bool is_enabled() const { - return enabled_; - } - -private: - void init() { - set_consuming_callback([this](const boost::any &data) { - try { - auto buffer = boost::any_cast(data); - auto out_buffer = event_buffer_pool_.acquire(); - out_buffer->clear(); - if (enabled_) - process(buffer->cbegin(), buffer->cend(), std::back_inserter(*out_buffer), std::true_type()); - else - process(buffer->cbegin(), buffer->cend(), std::back_inserter(*out_buffer), std::false_type()); - produce(out_buffer); - } catch (boost::bad_any_cast &) {} - }); - } - - template - std::enable_if_t::value, void> process(InputIt begin, InputIt end, - OutputIt d_begin, T) { - algo_->process_events(begin, end, d_begin); - } - - template - std::enable_if_t::value, void> - process(InputIt begin, InputIt end, OutputIt d_begin, std::true_type) { - algo_->process_events(begin, end, d_begin); - } - - template - std::enable_if_t::value, void> - process(InputIt begin, InputIt end, OutputIt d_begin, std::false_type) { - std::copy(begin, end, d_begin); - } - - std::unique_ptr algo_; - OutputEventBufferPool event_buffer_pool_; - std::atomic enabled_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_ALGORITHM_STAGE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/base_stage.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/base_stage.h deleted file mode 100644 index 4086d835f..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/base_stage.h +++ /dev/null @@ -1,348 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_BASE_STAGE_H -#define METAVISION_SDK_CORE_BASE_STAGE_H - -#include -#include -#include -#include -#include -#include -#include - -#include "metavision/sdk/base/events/event_cd.h" -#include "metavision/sdk/base/utils/object_pool.h" - -namespace Metavision { - -class Pipeline; - -/// @brief Base class for all stages added in the pipeline -/// -/// A stage can produce and/or consume data. -/// When data are produced by a stage, they are forwarded to the next stages, -/// so that they can consume these data and also produce some data on their own. -/// -/// The consumption of data is handled by the consuming callback which, by default, -/// does nothing with the data. -/// You can customize this behavior by calling @ref set_consuming_callback function. -/// -/// The production of data is triggered by calling @ref produce, which will -/// call the consuming callback of the next stages. The notion of previous/next stage is -/// defined by either passing the previous stage in the constructor or by calling -/// @ref set_previous_stage. -/// It can also be expressed by customizing the consuming callback of a previous stage by -/// calling @ref set_consuming_callback. -/// -/// Note that when data are produced, each producing callback is not executed synchronously. -/// Instead, the callback execution is scheduled to run either on the main thread (by default) -/// or on its own (dedicated) processing thread. -/// In any case, the callbacks of a stage are never called concurrently : the callbacks will be -/// either run synchronously in the main thread, or synchronously in a dedicated processing thread -/// @ref detach. This holds true for all consuming callbacks of a stage. -class BaseStage { -public: - /// @brief Convenience alias for a typical buffer of events - using EventBuffer = std::vector; - /// @brief Convenience alias for a pool of buffer of events - using EventBufferPool = SharedObjectPool; - /// @brief Convenience alias for a pointer to a buffer of events allocated in a pool - using EventBufferPtr = EventBufferPool::ptr_type; - -protected: - /// @brief Constructor - /// @param detachable If this stage can be detached (i.e. can run on its own thread) - inline BaseStage(bool detachable = true); - - /// @brief Constructor - /// - /// The @p prev_stage is used to setup the consuming callback - /// that will be called when the previous stage produces data. - /// When the previous stage produces data, it will call the consuming - /// callback (@ref set_consuming_callback) of this stage. - /// This behavior is automatically handled by this constructor. - /// If you need to customize the consuming callback of one (or all) of the previous stages, - /// you should use @ref set_consuming_callback instead. - /// - /// @param prev_stage the stage that is executed before the created one - /// @param detachable If this stage can be detached (i.e. can run on its own thread) - inline BaseStage(BaseStage &prev_stage, bool detachable = true); - -public: - /// @brief Destructor - inline virtual ~BaseStage(); - - /// @brief Sets the previous stage of this stage - /// - /// When called, this will setup each stage of the @p prev_stage to - /// call the default consuming callback of this stage when data is produced. - /// If you need to customize the consuming callback that should be called for - /// a previous stage, you should use @ref set_consuming_callback instead. - /// - /// @param prev_stage the previous stage of this stage - inline void set_previous_stage(BaseStage &prev_stage); - - /// @brief Gets the previous stages of this stage - /// @return The previous stages - /// @warning The reference to the set of previous stages can be invalidated by subsequent - /// calls to @ref set_previous_stage or @ref set_consuming_callback. - /// The returned value won't change once the associated pipeline is started. - inline const std::unordered_set &previous_stages() const; - - /// @brief Gets the next stages of this stage - /// @return The next stages - /// @warning The reference to the set of next stages can be invalidated by subsequent - /// calls to @ref set_previous_stage or @ref set_consuming_callback. - /// The returned value won't change once the associated pipeline is started. - inline const std::unordered_set &next_stages() const; - - /// @brief Enum class representing the status of a stage - enum class Status { - /// if the stage has not yet been started - Inactive, - /// if the stage is started - Started, - /// if the stage has completed its work - Completed, - /// if the stage has been cancelled - Cancelled, - }; - - /// @brief Returns the status of the stage - /// @return Status the status of the stage - inline Status status() const; - - /// @brief Enum class representing the type of a notification sent from a stage - enum class NotificationType { - /// change of status - Status, - }; - - /// @brief Sets the (generic) receiving callback for any previous stages - /// - /// Whenever a stage wants to notify other stages of changes (e.g. status update, etc), - /// it can do so by calling @ref notify. - /// When a notification is emitted at a stage, the receiving callback for each of the - /// following stages is scheduled to be run with the corresponding type and data. - /// This function sets the callback that will be scheduled when a notification - /// is emitted by any previous @p stage. - /// - /// @param cb The callback that will be called when a notification is emitted from - /// one of the previous stages - inline void set_receiving_callback( - const std::function &cb); - - /// @brief Sets the (generic) receiving callback for any previous stages - /// - /// Convenience overload to be used when the receiving callback does not need to receive the emitting stage - /// as an argument. - /// - /// @param cb The callback that will be called when a notification is emitted from - /// one of the previous stages - /// - /// @sa @ref set_receiving_callback(const std::function &cb) - inline void set_receiving_callback(const std::function &cb); - - /// @brief Sets the (specific) receiving callback for a previous stage - /// - /// When a notification is emitted at a stage, the receiving callback for each of the - /// following stages is scheduled to be run with the corresponding type and data. - /// This function sets the callback that will be scheduled when a notification is emitted - /// by a specific @p prev_stage. - /// - /// According to the stage that produced the data, the generic consuming callback - /// will be called if no specific consuming callback has been set. - /// According to the stage that emitted the notification, the generic receiving callback - /// will be called if no specific receiving callback has been set. - /// - /// @param prev_stage the previous stage for which the @p cb is set - /// @param cb The callback that will be called when a notification is sent from - /// one of the previous stages - /// - /// @sa @ref set_receiving_callback(const std::function &cb) - inline void set_receiving_callback(BaseStage &prev_stage, - const std::function &cb); - - /// @brief Sets the starting callback - /// - /// The starting callback is called the first time @ref Pipeline::run or @ref Pipeline::step is called. - /// This callback should set up a stage so that it can produce and/or consume data : - /// for example, it can start a producing thread or configure an algorithm with - /// parameters that were not known during construction. - /// - /// @warning This callback must not block, it can however create a thread to schedule some work - /// to be done during the time the pipeline is run. - /// - /// @param cb The callback that will be called when this stage is started - /// by the pipeline via @ref Pipeline::run or @ref Pipeline::step - /// - inline void set_starting_callback(const std::function &cb); - - /// @brief Sets the stopping callback - /// - /// @param cb The callback that will be called when this stage is being stopped - /// either because the previous stages have completed or when the pipeline is cancelled - /// via @ref Pipeline::cancel - /// - inline void set_stopping_callback(const std::function &cb); - - /// @brief Sets the setup callback - /// - /// The setup callback is called just after a valid reference to the pipeline has been set to the stage. The setup - /// callback allows the stage to setup everything needing a valid reference to the pipeline (e.g. setting pre and - /// post step callbacks). - /// - /// @param cb The callback that will be called when this stage has been set a valid reference to the pipeline - inline void set_setup_callback(const std::function &cb); - - /// @brief Sets the (generic) consuming callback for any previous stage - /// - /// When data is produced at a stage, the consuming callback for each of the - /// following steps is scheduled to be run with the produced data. - /// This function sets the callback that will be scheduled when data - /// is produced by any previous @p stage. - /// - /// The role of a consuming callback is, often, to produce data for next stages to consume. - /// If you don't set a consuming callback, the data produced by a previous stage will not be used - /// and, in particular, no data will be produced for following stages to consume. - /// Therefore, for a stage to be useful, one of the @ref set_consuming_callback function must be called. - /// - /// @param cb The callback that will be called by the producing callback of a - /// previous stage - /// - inline void set_consuming_callback(const std::function &cb); - - /// @brief Sets the (generic) consuming callback for any previous stage - /// - /// Convenience overload to be used when the receiving callback does not need to receive the emitting stage - /// as an argument. - /// - /// @param cb The callback that will be called by the producing callback of a - /// previous stage - /// - /// @sa @ref set_consuming_callback(const std::function &cb) - /// - inline void set_consuming_callback(const std::function &cb); - - /// @brief Sets the (specific) consuming callback for a previous stage - /// - /// When data is produced at a stage, the consuming callback for each of the - /// following steps is scheduled to be run with the produced data. - /// This function sets the callback that will be scheduled when data - /// is produced by a specific @p prev_stage. - /// - /// According to the stage that produced the data, the generic consuming callback - /// will be called if no specific consuming callback has been set. - /// - /// @param prev_stage the previous stage for which the @p cb is set - /// @param cb The callback to be called when data is produced by @ref produce - /// - /// @sa @ref set_consuming_callback(const std::function &cb) - /// - inline void set_consuming_callback(BaseStage &prev_stage, const std::function &cb); - - /// @brief Detaches this thread and schedules the execution of any callback on - /// its own dedicated processing thread of the pipeline - /// - /// When @ref detach is called, the stage will now schedules the execution of - /// any callback (the default or custom consuming callback set - /// for this stage on any previous stages) on its own dedicated processing thread. - /// A stage can be detached or undetached as long as the pipeline has not been started. - /// - /// @return true if stage has been detached (if it schedules the execution of callbacks on its own processing - /// thread) and false otherwise - inline bool detach(); - - /// @brief Gets the detached status of this stage - /// @return true if stage is detached (if it schedules the execution of callbacks on its own processing thread) - /// and false if stage schedules the execution of its callback on the main thread - inline bool is_detached() const; - - /// @brief Returns the associated pipeline - /// Throws std::runtime_error if no pipeline has been set yet. - /// @return @ref Pipeline "Pipeline&" the pipeline that owns this stage - /// @warning The function throws if no pipeline has been associated (i.e. if the stage was not created by the - /// pipeline nor added to it). - inline Pipeline &pipeline(); - - /// @brief Returns the associated pipeline - /// Throws std::runtime_error if no pipeline has been set yet. - /// @return @ref Pipeline "Pipeline&" the pipeline that owns this stage - /// @warning The function throws if no pipeline has been associated (i.e. if the stage was not created by the - /// pipeline nor added to it). - inline const Pipeline &pipeline() const; - -protected: - /// @brief Notifies next stages of a change - /// - /// This schedules the execution of all the receiving callbacks - /// - /// @param type The notification type - /// @param data The associated notification data - inline void notify(const NotificationType &type, const boost::any &data); - - /// @brief Produces data - /// - /// This schedules the execution of all the producing callbacks - /// - /// @param data The produced data - inline void produce(const boost::any &data); - - /// @brief Sets the stage status and notify next stages when it is done - /// - /// This function should be called whenever the stage will never produce any more data - /// A stage is done when it has the status @ref Status::Completed or - /// - /// @ref Status::Cancelled and it has finished scheduling tasks to be - /// processed by following stages. - inline void complete(); - -private: - std::atomic status_{Status::Inactive}; - std::atomic done_{false}, detachable_{true}, run_on_main_thread_{true}; - std::atomic current_prod_id_{0}; - - mutable std::mutex mutex_; - Pipeline *pipeline_ = nullptr; - std::unordered_set prev_stages_, next_stages_; - - std::mutex cbs_mutex_; - std::function starting_cb_ = [] {}; - std::function stopping_cb_ = [] {}; - std::function setup_cb_ = [] {}; - std::unordered_map> consuming_cbs_; - std::unordered_map> - receiving_cbs_; - - inline void start(); - inline void stop(); - inline void cancel(); - inline bool is_done() const; - - inline void set_pipeline(Pipeline &pipeline); - inline bool set_status(const Status &status); - - inline void signal(); - inline void consume(BaseStage &prev_stage, const boost::any &data); - inline void receive(BaseStage &prev_stage, const NotificationType &type, const boost::any &data); - - friend class Pipeline; -}; - -} // namespace Metavision - -#include "detail/base_stage_impl.h" - -#endif // METAVISION_SDK_CORE_BASE_STAGE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/base_stage_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/base_stage_impl.h deleted file mode 100644 index 018ac8c89..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/base_stage_impl.h +++ /dev/null @@ -1,296 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_DETAIL_BASE_STAGE_IMPL_H -#define METAVISION_SDK_CORE_DETAIL_BASE_STAGE_IMPL_H - -#include - -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/pipeline/pipeline.h" - -namespace Metavision { - -BaseStage::BaseStage(bool detachable) : detachable_(detachable) { - consuming_cbs_[nullptr] = [](BaseStage &, const boost::any &) {}; - receiving_cbs_[nullptr] = [](BaseStage &, const NotificationType &, const boost::any &) {}; -} - -BaseStage::BaseStage(BaseStage &prev_stage, bool detachable) : BaseStage(detachable) { - set_previous_stage(prev_stage); -} - -BaseStage::~BaseStage() {} - -void BaseStage::set_previous_stage(BaseStage &prev_stage) { - std::lock_guard lock(mutex_); - prev_stage.next_stages_.insert(this); - prev_stages_.insert(&prev_stage); -} - -const std::unordered_set &BaseStage::previous_stages() const { - std::lock_guard lock(mutex_); - return prev_stages_; -} - -const std::unordered_set &BaseStage::next_stages() const { - std::lock_guard lock(mutex_); - return next_stages_; -} - -BaseStage::Status BaseStage::status() const { - return status_; -} - -bool BaseStage::set_status(const Status &status) { - if (status_.exchange(status) != status) { - notify(NotificationType::Status, status); - return true; - } - return false; -} - -void BaseStage::complete() { - set_status(Status::Completed); - // we only set done_ = true only after notification tasks are queued - // to make sure they are processed - done_ = true; - // then we make sure next stages wake up and notice this task is done - signal(); -} - -void BaseStage::cancel() { - set_status(Status::Cancelled); - // we only set done_ = true only after notification tasks are queued - // to make sure they are processed - done_ = true; - // then we make sure next stages wake up and notice this task is done - signal(); -} - -bool BaseStage::is_done() const { - return done_; -} - -void BaseStage::start() { - if (set_status(Status::Started)) { - std::function cb; - { - std::lock_guard lock(cbs_mutex_); - cb = starting_cb_; - } - cb(); - } -} - -void BaseStage::stop() { - // no need to set any status, it will have been done independently via - // set_status(Status::Completed) or set_status(Status::Cancelled) - std::function cb; - { - std::lock_guard lock(cbs_mutex_); - cb = stopping_cb_; - } - cb(); -} - -void BaseStage::set_receiving_callback( - const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - receiving_cbs_[nullptr] = cb; -} - -void BaseStage::set_receiving_callback(const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - receiving_cbs_[nullptr] = [cb](BaseStage &, const NotificationType &type, const boost::any &data) { - cb(type, data); - }; -} - -void BaseStage::set_receiving_callback(BaseStage &prev_stage, - const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - receiving_cbs_[&prev_stage] = [cb](BaseStage &, const NotificationType &type, const boost::any &data) { - cb(type, data); - }; -} - -void BaseStage::set_starting_callback(const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - starting_cb_ = cb; -} - -void BaseStage::set_stopping_callback(const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - stopping_cb_ = cb; -} - -void BaseStage::set_setup_callback(const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - setup_cb_ = cb; -} - -void BaseStage::set_consuming_callback(const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - consuming_cbs_[nullptr] = cb; -} - -void BaseStage::set_consuming_callback(const std::function &cb) { - std::lock_guard lock(cbs_mutex_); - consuming_cbs_[nullptr] = [cb](BaseStage &, const boost::any &data) { cb(data); }; -} - -void BaseStage::set_consuming_callback(BaseStage &prev_stage, const std::function &cb) { - std::lock_guard lock(mutex_); - std::lock_guard lock2(cbs_mutex_); - consuming_cbs_[&prev_stage] = [cb](BaseStage &, const boost::any &data) { cb(data); }; - prev_stage.next_stages_.insert(this); - prev_stages_.insert(&prev_stage); -} - -void BaseStage::produce(const boost::any &data) { - Pipeline *pipeline; - std::unordered_set next_stages; - { - std::lock_guard lock(mutex_); - pipeline = pipeline_; - next_stages = next_stages_; - } - if (!pipeline) - return; - - // If the pipeline has been cancelled, we can't produce anything - if (pipeline->status() == Pipeline::Status::Cancelled) - return; - - for (auto *stage : next_stages) { - pipeline->schedule( - *stage, [this, stage, data] { stage->consume(*this, data); }, stage->current_prod_id_++, true, - stage->run_on_main_thread_); - }; -} - -void BaseStage::consume(BaseStage &prev_stage, const boost::any &data) { - std::function cb; - { - std::lock_guard lock(cbs_mutex_); - auto it = consuming_cbs_.find(&prev_stage); - if (it != consuming_cbs_.end()) { - cb = it->second; - } else { - cb = consuming_cbs_[nullptr]; - } - } - cb(prev_stage, data); -} - -void BaseStage::signal() { - Pipeline *pipeline; - std::unordered_set next_stages; - { - std::lock_guard lock(mutex_); - pipeline = pipeline_; - next_stages = next_stages_; - } - if (!pipeline) - return; - - // send dummy notification task - for (auto *stage : next_stages) { - pipeline->schedule( - *stage, [] {}, stage->current_prod_id_++, true, stage->run_on_main_thread_); - }; -} - -void BaseStage::notify(const NotificationType &type, const boost::any &data) { - Pipeline *pipeline; - std::unordered_set next_stages; - { - std::lock_guard lock(mutex_); - pipeline = pipeline_; - next_stages = next_stages_; - } - if (!pipeline) - return; - - for (auto *stage : next_stages) { - pipeline->schedule( - *stage, [this, stage, type, data] { stage->receive(*this, type, data); }, stage->current_prod_id_++, false, - stage->run_on_main_thread_); - }; -} - -void BaseStage::receive(BaseStage &prev_stage, const NotificationType &type, const boost::any &data) { - std::function cb; - { - std::lock_guard lock(cbs_mutex_); - auto it = receiving_cbs_.find(&prev_stage); - if (it != receiving_cbs_.end()) { - cb = it->second; - } else { - cb = receiving_cbs_[nullptr]; - } - } - cb(prev_stage, type, data); -} - -bool BaseStage::detach() { - std::lock_guard lock(mutex_); - if (!pipeline_ || pipeline_->status() != Pipeline::Status::Started) { - if (detachable_) { - run_on_main_thread_ = false; - return true; - } - } - return false; -} - -bool BaseStage::is_detached() const { - return !run_on_main_thread_; -} - -void BaseStage::set_pipeline(Pipeline &pipeline) { - { - std::lock_guard lock(mutex_); - if (pipeline_ && pipeline_->status() == Pipeline::Status::Started) { - throw std::runtime_error("BaseStage : associated pipeline cannot be changed once started"); - } - if (pipeline.status() == Pipeline::Status::Started) { - throw std::runtime_error("BaseStage : pipeline already started"); - } - pipeline_ = &pipeline; - } - - std::function cb; - { - std::lock_guard lock(cbs_mutex_); - cb = setup_cb_; - } - cb(); -} - -Pipeline &BaseStage::pipeline() { - std::lock_guard lock(mutex_); - if (!pipeline_) - throw std::runtime_error("BaseStage : no pipeline associated"); - return *pipeline_; -} - -const Pipeline &BaseStage::pipeline() const { - std::lock_guard lock(mutex_); - if (!pipeline_) - throw std::runtime_error("BaseStage : no pipeline associated"); - return *pipeline_; -} - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_DETAIL_BASE_STAGE_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/frame_composition_stage_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/frame_composition_stage_impl.h deleted file mode 100644 index 538c66069..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/frame_composition_stage_impl.h +++ /dev/null @@ -1,238 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_DETAIL_FRAME_COMPOSITION_STAGE_IMPL_H -#define METAVISION_SDK_CORE_DETAIL_FRAME_COMPOSITION_STAGE_IMPL_H - -namespace Metavision { - -inline bool FrameCompositionStage::SourceInfo::can_copy(timestamp next_frame_ts, timestamp max_ts_range) { - return ts_last_frame_saved - next_frame_ts < max_ts_range; -} - -inline void FrameCompositionStage::SourceInfo::add_frame(timestamp ts, FrameCompositionStage::FramePtr &ptr, - timestamp next_frame_ts, timestamp max_ts_range) { - if (can_copy(next_frame_ts, max_ts_range)) { - saved_frames_queue_.push({ts, ptr->clone()}); - } else { - references_to_input_frames_queue_.push({ts, ptr}); - } -} - -inline void FrameCompositionStage::SourceInfo::update_with_past_ptr(FrameCompositionStage::FramePtr &ptr) { - if (ptr) { - // In this case just update the reference of last frame received: - // this is because we don't know yet if this frame is the one that will be used to update the - // composed image or another one more recent (it all depends on the update frequency of this source - // compared to the update frequency of the composer) - // REMARK: keeping the reference to the frame will in fact block this pointer of the input pool - // (that is ok if the input pool has a size >= 2, which we can safely assume) - ptr_to_last_frame_received = ptr; - } -} - -bool FrameCompositionStage::SourceInfo::update_with_current_ptr(FrameCompositionStage::FramePtr &ptr, - timestamp source_next_frame_ts, - timestamp composer_next_frame_ts, - timestamp max_ts_range) { - // Update info: - ptr_to_last_frame_received = nullptr; // release shared pointer of the source frame pool (if any) - ts_last_frame_saved = source_next_frame_ts; - - if (ptr) { - if (source_next_frame_ts == composer_next_frame_ts) { - // Instead of saving the image (or storing the ptr) in the queue, we can directly update the - // composed image, thus avoiding the copy (or avoiding to block the ptr from the input pool) - return true; - } else { - // We have to copy/store this frame, it will be used to generate one of the next composed frames - add_frame(source_next_frame_ts, ptr, composer_next_frame_ts, max_ts_range); - } - } // No need to handle the else condition: if ptr is a nullptr, then just by updating variable ts_last_frame_saved - // (done above) then the composed frame will automatically keep last sub-image of this source (cf code of method - // update_composed_image() in class FrameCompositionStage) - return false; -} - -void FrameCompositionStage::SourceInfo::update_with_future_ptr(FrameCompositionStage::FramePtr &ptr, timestamp ptr_ts, - timestamp source_next_frame_ts, timestamp frame_period, - timestamp composer_next_frame_ts, - timestamp max_ts_range) { - // In this case the last frame received is the one we need to copy/store to update frame at time - // source_next_frame_ts - if (ptr_to_last_frame_received) { - add_frame(source_next_frame_ts, ptr_to_last_frame_received, composer_next_frame_ts, max_ts_range); - } - - // We're not going to have any frame between source_next_frame_ts and ptr_ts, so we can keep increasing - // source_next_frame_ts until it becomes greater than or equal to ptr_ts - while (ptr_ts > source_next_frame_ts) { - source_next_frame_ts += frame_period; - } - - // When arriving here there are two possibilities: - // 1) ptr_ts == source_next_frame_ts: in this case we can copy the image / store the ptr - // in the queue - // 2) ptr_ts < source_next_frame_ts: in this case just store the reference - if (ptr_ts == source_next_frame_ts) { - // No need to check the return value of the following call, because we already know that it will - // return false (because we pass -1 as third parameter). We do indeed an extra check that we don't need - // (check if source_next_frame_ts == -1 - cf code of method update_with_current_ptr()), but that's the cost - // to have a common method to make the code more readable - update_with_current_ptr(ptr, source_next_frame_ts, -1, max_ts_range); - } else { - ptr_to_last_frame_received = ptr; - // Update ts_last_frame_saved to (source_next_frame_ts - frame_period) and not source_next_frame_ts because in - // this case we still haven't found the frame to display for t = source_next_frame_ts - ts_last_frame_saved = source_next_frame_ts - frame_period; - } -} - -FrameCompositionStage::FrameCompositionStage(int fps, timestamp max_ts_range, const cv::Vec3b &bg_color) : - frame_period_(static_cast(1.e6 / fps + 0.5)), - next_frame_ts_(static_cast(1.e6 / fps + 0.5)), - max_ts_range_(max_ts_range), - frame_composer_(bg_color), - output_frame_pool_(FramePool::make_bounded()) { - set_consuming_callback([](const boost::any &data) { - MV_SDK_LOG_WARNING() << "For this stage to work properly, you need to call add_previous_frame_stage\n" - << "for each stage that produces frame to be composed."; - }); - set_receiving_callback([this](BaseStage &stage, const BaseStage::NotificationType &type, const boost::any &data) { - if (type == BaseStage::NotificationType::Status) { - set_stage_status(stage, data); - } - }); -} - -void FrameCompositionStage::add_previous_frame_stage(BaseStage &prev_frame_stage, int x, int y, int width, int height, - bool enable_crop, - const FrameComposer::GrayToColorOptions &gray_to_color_options) { - FrameComposer::ResizingOptions resize_o(width, height, enable_crop); - const int ref = frame_composer_.add_new_subimage_parameters(x, y, resize_o, gray_to_color_options); - stages_map_[&prev_frame_stage] = ref; - sources_info_map_[ref] = SourceInfo(); - set_consuming_callback(prev_frame_stage, [this, ref](const boost::any &data) { consume_frame(ref, data); }); -} - -FrameComposer &FrameCompositionStage::frame_composer() { - return frame_composer_; -} - -void FrameCompositionStage::consume_frame(int frame_ref, const boost::any &data) { - try { - auto ts_frame_ptr = boost::any_cast(data); - - SourceInfo &source_info = sources_info_map_[frame_ref]; - timestamp source_next_frame_ts = source_info.ts_last_frame_saved + frame_period_; - - if (ts_frame_ptr.first < source_next_frame_ts) { - source_info.update_with_past_ptr(ts_frame_ptr.second); - // We can return directly, because in this case we already know that there is no new composed - // image to generate - return; - } else if (ts_frame_ptr.first == source_next_frame_ts) { - if (source_info.update_with_current_ptr(ts_frame_ptr.second, source_next_frame_ts, next_frame_ts_, - max_ts_range_)) { - frame_composer_.update_subimage(frame_ref, *(ts_frame_ptr.second)); - } - } else { // .i.e. ts_frame_ptr.first > source_next_frame_ts - source_info.update_with_future_ptr(ts_frame_ptr.second, ts_frame_ptr.first, source_next_frame_ts, - frame_period_, next_frame_ts_, max_ts_range_); - } - - // Update and produce composed frames as long as we have all updates - while (got_all_updates()) { - update_composed_image(); // No need to check return value of this method because we already know that - // have all updates - produce_composed_frame(); - } - } catch (boost::bad_any_cast &c) { MV_SDK_LOG_ERROR() << c.what(); } -} - -void FrameCompositionStage::set_stage_status(BaseStage &stage, const boost::any &data) { - try { - auto status = boost::any_cast(data); - if (status == Status::Completed) { - SourceInfo &source_info = sources_info_map_[stages_map_[&stage]]; - source_info.finished_producing = true; - - // In this case, if we had a pointer stored in source_info.ptr_to_last_frame_received, - // we update the last frame saved: - if (source_info.ptr_to_last_frame_received) { - source_info.add_frame(source_info.ts_last_frame_saved + frame_period_, - source_info.ptr_to_last_frame_received, next_frame_ts_, max_ts_range_); - } - - // If all sources have finished producing, then we can update all the remaining - // composed images: - for (auto &p : sources_info_map_) { - if (!p.second.finished_producing) { - return; - } - } - - // If we arrive here it means all sources have finished producing: we can keep updating and produce the - // composed image until all input frames received have been consumed - while (update_composed_image()) { - produce_composed_frame(); - } - } - } catch (boost::bad_any_cast &c) { MV_SDK_LOG_ERROR() << c.what(); } -} - -inline bool FrameCompositionStage::update_composed_image() { - bool still_have_frames_to_consume = false; - for (auto &p : sources_info_map_) { - if (!p.second.saved_frames_queue_.empty()) { - still_have_frames_to_consume = true; // Regardless of whether or not we enter the if condition below, if - // we arrive here it means the queue is not empty, i.e. we didn't - // consume all the frames of the source - auto &next_frame_saved_in_queue = p.second.saved_frames_queue_.front(); - if (next_frame_saved_in_queue.first == next_frame_ts_) { - frame_composer_.update_subimage(p.first, next_frame_saved_in_queue.second); - p.second.saved_frames_queue_.pop(); - continue; // No need to look in the queue with the shared ptr: skip to next source - } - } - if (!p.second.references_to_input_frames_queue_.empty()) { - still_have_frames_to_consume = true; // Regardless of whether or not we enter the if condition below, if - // we arrive here it means the queue is not empty, i.e. we didn't - // consume all the frames of the source - auto &next_in_queue = p.second.references_to_input_frames_queue_.front(); - if (next_in_queue.first == next_frame_ts_) { - frame_composer_.update_subimage(p.first, *(next_in_queue.second)); - p.second.references_to_input_frames_queue_.pop(); - } - } - } - return still_have_frames_to_consume; -} - -inline void FrameCompositionStage::produce_composed_frame() { - produced_frame_ptr_ = output_frame_pool_.acquire(); - frame_composer_.get_full_image().copyTo(*produced_frame_ptr_); - produce(std::make_pair(next_frame_ts_, produced_frame_ptr_)); - next_frame_ts_ += frame_period_; -} - -inline bool FrameCompositionStage::got_all_updates() { - for (auto &p : sources_info_map_) { - if (p.second.ts_last_frame_saved < next_frame_ts_ && !p.second.finished_producing) { - return false; - } - } - return true; -} - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_DETAIL_FRAME_COMPOSITION_STAGE_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/pipeline_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/pipeline_impl.h deleted file mode 100644 index 3ae840f37..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/detail/pipeline_impl.h +++ /dev/null @@ -1,512 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_DETAIL_PIPELINE_IMPL_H -#define METAVISION_SDK_CORE_DETAIL_PIPELINE_IMPL_H - -#include -#include -#include -#include - -#include "metavision/sdk/core/pipeline/pipeline.h" -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/pipeline/algorithm_stage.h" - -namespace Metavision { - -struct Task { - Task(const std::function &task = std::function(), size_t id = 0, bool optional = true, - BaseStage *stage_ptr = nullptr) : - task(task), id(id), optional(optional), stage_ptr(stage_ptr) {} - - bool empty() const { - return !static_cast(task); - } - - void operator()() const { - task(); - } - - bool operator<(const Task &t) const { - return id > t.id; - } - - std::function task; - size_t id; - bool optional; - BaseStage *stage_ptr; -}; - -class TaskQueue { -public: - TaskQueue() : cancel_{false} {} - - void push(const Task &task) { - { - std::lock_guard lock(mutex_); - tasks_.push(task); - } - cond_.notify_all(); - } - - Task pop() { - Task t; - { - std::unique_lock lock(mutex_); - cond_.wait(lock, [this]() { return !tasks_.empty() || cancel_; }); - if (!tasks_.empty()) { - t = tasks_.top(); - tasks_.pop(); - } - } - return t; - } - - void cancel() { - { - std::lock_guard lock(mutex_); - cancel_ = true; - } - cond_.notify_one(); - } - - void clear() { - std::lock_guard lock(mutex_); - while (!tasks_.empty()) - tasks_.pop(); - } - - bool empty() const { - std::lock_guard lock(mutex_); - return tasks_.empty(); - } - - size_t size() const { - std::lock_guard lock(mutex_); - return tasks_.size(); - } - -private: - std::atomic cancel_{false}; - mutable std::mutex mutex_; - std::condition_variable cond_; - std::priority_queue tasks_; -}; - -class Pipeline::TaskScheduler { -public: - TaskScheduler() : running_(false), exited_(false), main_tasks_(std::make_unique()) {} - - ~TaskScheduler() {} - - void complete_stage_if_done(BaseStage &stage, bool decrement_num_task = false) { - bool stage_done = false; - { - std::lock_guard lock(stage_tasks_mutex_); - if (decrement_num_task) - --stages_num_tasks_[&stage]; - if (stages_num_tasks_[&stage] == 0 && !stage.previous_stages().empty()) { - stage_done = are_previous_stages_done(stage); - } - } - if (stage_done) { - stage.complete(); - } - } - - void schedule(BaseStage &stage, const Task &task, bool schedule_on_main_thread = true) { - if (!running_) - return; - if (schedule_on_main_thread) { - if (std::this_thread::get_id() != main_thread_id_) { - { - std::lock_guard lock(stage_tasks_mutex_); - ++stages_num_tasks_[&stage]; - } - main_tasks_->push(task); - } else { - task(); - complete_stage_if_done(*task.stage_ptr); - } - } else { - { - std::lock_guard lock(stage_tasks_mutex_); - ++stages_num_tasks_[&stage]; - } - size_t id = 0; - { - std::lock_guard lock(processing_map_id_mutex_); - auto it = processing_map_id_.find(&stage); - if (processing_map_id_.find(&stage) == processing_map_id_.end()) { - id = processing_map_id_[&stage] = processing_current_map_id_++; - } else { - id = it->second; - } - } - processing_tasks_[id]->push(task); - } - } - - // no need for concurrent access checks or double start logic protection : this function - // can only be called from Pipeline::start() which already does the controls - void init(bool main_thread_will_have_tasks, size_t num_processing_threads) { - running_ = true; - - main_thread_will_have_tasks_ = main_thread_will_have_tasks; - processing_tasks_.resize(num_processing_threads); - for (auto &q : processing_tasks_) - q = std::make_unique(); - processing_threads_.resize(num_processing_threads); - } - - void start() { - size_t num_processing_threads = processing_threads_.size(); - for (size_t i = 0; i < num_processing_threads; ++i) { - processing_threads_[i] = std::thread([this, i]() { - while (running_) { - // This will get an already queued task or wait for one to be scheduled - // This will also return an empty task if a call to cancel() or exit() is - // made on the pipeline by the user or one of the other threads that - // exited the processing loop (when running_ = false) - Task task = processing_tasks_[i]->pop(); - if (!task.empty()) { - if (!exited_ || !task.optional) { - task(); - } - } - - if (task.stage_ptr) { - complete_stage_if_done(*task.stage_ptr, true); - } - } - cancel(); - }); - } - } - - // no need for concurrent access checks or double start logic protection : this function - // can only be called from Pipeline::stop() which already does the controls - void stop() { - for (auto &thread : processing_threads_) { - if (thread.joinable()) - thread.join(); - } - } - - bool is_running() const { - return running_; - } - - // no need for concurrent access checks, this function is thread safe - bool step() { - if (!running_) - return false; - - if (main_thread_will_have_tasks_) { - if (main_tasks_->empty()) { - // We have to be careful to not try to pop a task unless there really - // is one to pop, otherwise we could block forever - std::this_thread::yield(); - } else { - // This will get an already queued task or wait for one to be scheduled - // This will also return an empty task if a call to cancel() or exit() is - // made on the pipeline by the user or one of the other threads that - // exited the processing loop (when running_ = false) - Task task = main_tasks_->pop(); - if (!task.empty()) { - if (!exited_ || !task.optional) { - task(); - } - } - - if (task.stage_ptr) { - complete_stage_if_done(*task.stage_ptr, true); - } - } - } else if (processing_tasks_.empty()) { - // We have no tasks to process at all - cancel(); - return false; - } else { - std::this_thread::yield(); - } - return true; - } - - // no need for concurrent access checks, this function is thread safe - void cancel() { - running_ = false; - main_tasks_->cancel(); - for (auto &q : processing_tasks_) - q->cancel(); - } - - // no need for concurrent access checks, this function is thread safe - void exit() { - exited_ = true; - // process mandatory tasks while queues are not empty - while (running_ && !empty()) { - step(); - } - cancel(); - } - - bool empty() const { - if (!main_tasks_->empty()) - return false; - for (auto &q : processing_tasks_) { - if (!q->empty()) - return false; - } - return true; - } - - void set_main_thread_id(std::thread::id id) { - main_thread_id_ = id; - } - - std::thread::id main_thread_id() const { - return main_thread_id_; - } - -private: - bool are_previous_stages_done(const BaseStage &stage) { - bool done = true; - const auto &prev_stage_ptrs = stage.previous_stages(); - for (auto &prev_stage_ptr : prev_stage_ptrs) { - // previous stage must have completed and finished scheduling all tasks - if (prev_stage_ptr->status() != BaseStage::Status::Completed || !prev_stage_ptr->is_done()) { - done = false; - break; - } - } - return done; - } - - std::atomic running_; - std::atomic exited_; - std::unique_ptr main_tasks_; - std::thread::id main_thread_id_; - - std::mutex processing_map_id_mutex_; - size_t processing_current_map_id_ = 0; - std::unordered_map processing_map_id_; - - std::vector> processing_tasks_; - std::vector processing_threads_; - - mutable std::mutex stage_tasks_mutex_; - bool main_thread_will_have_tasks_; - std::unordered_map stages_num_tasks_; -}; - -Pipeline::Pipeline(bool auto_detach) : - auto_detach_stages_(auto_detach), scheduler_(std::make_unique()) {} - -Pipeline::~Pipeline() { - cancel(); - step(); -} - -inline void Pipeline::check_if_started() { - if (status_ == Status::Started) - throw std::runtime_error("Pipeline : Can't modify pipeline after it has started!"); -} - -template -Stage &Pipeline::add_stage(std::unique_ptr &&stage) { - check_if_started(); - return static_cast(add_stage_priv(std::move(stage))); -} - -template -Stage &Pipeline::add_stage(std::unique_ptr &&stage, BaseStage &prev_stage) { - check_if_started(); - stage->set_previous_stage(prev_stage); - return static_cast(add_stage_priv(std::move(stage))); -} - -template && !is_same_type, int>> -AlgorithmStage & - Pipeline::add_algorithm_stage(std::unique_ptr &&algo) { - check_if_started(); - auto stage = std::make_unique>(std::move(algo)); - return static_cast &>(add_stage_priv(std::move(stage))); -} - -template && is_same_type, int>> -AlgorithmStage & - Pipeline::add_algorithm_stage(std::unique_ptr &&algo, bool enabled) { - check_if_started(); - auto stage = std::make_unique>(std::move(algo), enabled); - return static_cast &>(add_stage_priv(std::move(stage))); -} - -template && !is_same_type, int>> -AlgorithmStage & - Pipeline::add_algorithm_stage(std::unique_ptr &&algo, BaseStage &prev_stage) { - check_if_started(); - auto stage = - std::make_unique>(std::move(algo), prev_stage); - return static_cast &>(add_stage_priv(std::move(stage))); -} - -template && is_same_type, int>> -AlgorithmStage & - Pipeline::add_algorithm_stage(std::unique_ptr &&algo, BaseStage &prev_stage, bool enabled) { - check_if_started(); - auto stage = std::make_unique>(std::move(algo), - prev_stage, enabled); - return static_cast &>(add_stage_priv(std::move(stage))); -} - -BaseStage &Pipeline::add_stage_priv(std::unique_ptr &&stage) { - stage->set_pipeline(*this); - if (auto_detach_stages_) { - stage->detach(); - } - stages_.emplace_back(std::move(stage)); - return *stages_.back(); -} - -void Pipeline::remove_stage(BaseStage &stage) { - check_if_started(); - auto it = std::find_if(stages_.begin(), stages_.end(), - [&stage](const std::unique_ptr &p) { return p.get() == &stage; }); - if (it != stages_.end()) { - stages_.erase(it); - } - - for (auto &s : stages_) { - s->prev_stages_.erase(&stage); - s->next_stages_.erase(&stage); - } -} - -size_t Pipeline::count() const { - return stages_.size(); -} - -bool Pipeline::empty() const { - return stages_.empty(); -} - -Pipeline::Status Pipeline::status() const { - return status_; -} - -void Pipeline::start() { - if (scheduler_->main_thread_id() == std::thread::id()) { - scheduler_->set_main_thread_id(std::this_thread::get_id()); - } - bool main_thread_will_have_tasks = false; - int num_processing_threads = 0; - for (auto &stage : stages_) { - // producing only stages don't count - const auto &prev_stages = stage->previous_stages(); - if (!prev_stages.empty()) { - if (stage->is_detached()) { - ++num_processing_threads; - } else { - main_thread_will_have_tasks = true; - } - } - } - scheduler_->init(main_thread_will_have_tasks, num_processing_threads); - for (auto &stage : stages_) { - stage->start(); - } - scheduler_->start(); -} - -void Pipeline::stop() { - for (auto &stage_ptr : stages_) { - stage_ptr->stop(); - } - scheduler_->exit(); - scheduler_->stop(); - if (status_ != Status::Cancelled) { - status_ = Status::Completed; - } -} - -bool Pipeline::step() { - std::lock_guard lock(mutex_); - if (status_ == Status::Inactive) { - status_ = Status::Started; - start(); - } - - bool done = true; - for (auto &stage_ptr : stages_) { - if (!stage_ptr->is_done()) { - done = false; - break; - } - } - - bool ret = true; - if (status_ == Status::Cancelled || done) { - stop(); - ret = false; - } else { - for (const auto &pre_cb : pre_step_cbs_) - pre_cb(); - - ret = scheduler_->step(); - - for (const auto &post_cb : post_step_cbs_) - post_cb(); - } - - return ret; -} - -void Pipeline::run() { - if (status_ == Status::Started) - return; - - while (step()) {} -} - -void Pipeline::cancel() { - // can be called concurrently, no need for a mutex - status_ = Status::Cancelled; - for (auto &stage_ptr : stages_) { - if (stage_ptr->status() != BaseStage::Status::Completed) { - stage_ptr->cancel(); - } - } -} - -void Pipeline::add_pre_step_callback(const StepCallback &cb) { - std::lock_guard lock(mutex_); - pre_step_cbs_.emplace_back(cb); -} - -void Pipeline::add_post_step_callback(const StepCallback &cb) { - std::lock_guard lock(mutex_); - post_step_cbs_.emplace_back(cb); -} - -void Pipeline::schedule(BaseStage &stage, const std::function &task, size_t task_id, bool optional, - bool schedule_on_main_thread) { - scheduler_->schedule(stage, {task, task_id, optional, &stage}, schedule_on_main_thread); -} - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_DETAIL_PIPELINE_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/frame_composition_stage.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/frame_composition_stage.h deleted file mode 100644 index dd21f69d7..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/frame_composition_stage.h +++ /dev/null @@ -1,144 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_FRAME_COMPOSITION_STAGE_H -#define METAVISION_SDK_CORE_FRAME_COMPOSITION_STAGE_H - -#include - -#include "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/utils/frame_composer.h" - -namespace Metavision { - -/// @brief Class for composing a frame out of multiple frames. -/// -/// It connects stages together to display side by side their image streams at a fixed refresh rate. Each sub-frame -/// coming from the input stages is rendered to its specified coordinates in the composed output frame. -/// -/// The FPS given by the user determines at which frequency the full image must be updated (in the data's clock, not in -/// the system's one). However, input stages are not necessarily synchronous and might have different output -/// frequencies. This class acts like a synchronizer and displays at each multiple of dt = 1/FPS only the most recent -/// sub-image for each input stage. -/// -/// Nullptrs images can be used as temporal markers, so that input stages can let the class know there are no -/// available data to display for this input at time ts. In that case, the corresponding part in the whole image won't -/// be updated. -class FrameCompositionStage : public BaseStage { -public: - using FramePool = SharedObjectPool; - using FramePtr = FramePool::ptr_type; - using Input = std::pair; - using Output = std::pair; - -public: - FrameCompositionStage(int fps, timestamp max_ts_range = 5000000, const cv::Vec3b &bg_color = cv::Vec3b(0, 0, 0)); - - /// @brief Sets up the frame composer to put the frame produced by @p prev_frame_stage at the given location - /// @param prev_frame_stage Stage producing the frames - /// @param x X-position of the top-left corner of the image in the composition - /// @param y Y-position of the top-left corner of the image in the composition - /// @param width Width of the (possibly scaled) frame inside the composed frame - /// @param height Height of the (possibly scaled) frame inside the composed frame - /// @param enable_crop Whether to enable cropping the image to the specified width and height (maintains the center) - /// @param gray_to_color_options Options used to rescale and/or apply a colormap on the grayscale image - void add_previous_frame_stage( - BaseStage &prev_frame_stage, int x, int y, int width, int height, bool enable_crop = false, - const FrameComposer::GrayToColorOptions &gray_to_color_options = FrameComposer::GrayToColorOptions()); - - /// @brief Gets the underlying frame composer algorithm - /// @return @ref FrameComposer & the frame composer algorithm - FrameComposer &frame_composer(); - -private: - struct SourceInfo { - // Member that will be set to true when the source has finished producing frames - bool finished_producing = false; - - // Reference to the last frame received from the source - FramePtr ptr_to_last_frame_received = nullptr; - - // Queue containing the copied frames - std::queue> saved_frames_queue_; - - // More recent timestamp for which both: - // - an update of the composed frame is required (i.e. multiple of the composer's period), and - // - the needed information has been received from the source - timestamp ts_last_frame_saved = 0; - - // Queue containing the references to the input frames received (the ones that have not been copied) - std::queue> references_to_input_frames_queue_; - - // Returns true if we can copy the next frame received - bool can_copy(timestamp next_frame_ts, timestamp max_ts_range); - - // Adds frame - void add_frame(timestamp ts, FrameCompositionStage::FramePtr &ptr, timestamp next_frame_ts, - timestamp max_ts_range); - - // Function called when we receive a frame with a timestamp t < source_next_frame_ts - void update_with_past_ptr(FrameCompositionStage::FramePtr &ptr); - - // Function called when we receive a frame with a timestamp t == source_next_frame_ts - // Returns true if we can directly update the composed image - bool update_with_current_ptr(FrameCompositionStage::FramePtr &ptr, timestamp source_next_frame_ts, - timestamp composer_next_frame_ts, timestamp max_ts_range); - - // Function called when we receive a frame with a timestamp t > source_next_frame_ts - void update_with_future_ptr(FrameCompositionStage::FramePtr &ptr, timestamp ptr_ts, - timestamp source_next_frame_ts, timestamp frame_period, - timestamp composer_next_frame_ts, timestamp max_ts_range); - }; - - /// @brief Processes a new frame coming from a given stage - /// - /// @param frame_ref ID referring to a sub-image of the frame composer - /// @param data Timestamped shared_pointer of a new frame - void consume_frame(int frame_ref, const boost::any &data); - - void set_stage_status(BaseStage &stage, const boost::any &data); - - /// @brief Updates the composed image stored in the frame composer - /// - /// REMARK : this method makes the assumption that we are capable of updating the frame for ts next_frame_ts_, i.e. - /// each input source has either provided the update for next_frame_ts_ (or greater), or finished - /// producing - /// - /// @return true if there still are frames to consume, false otherwise - bool update_composed_image(); - - /// @brief Produces the composed image (which has to be ready - i.e. already updated) - void produce_composed_frame(); - - /// @brief Checks if we received the update for next_frame_ts_ from all sources - /// - /// @return true if composer is ready to generate frame for next_frame_ts_ - bool got_all_updates(); - - const timestamp frame_period_; - timestamp next_frame_ts_; - const timestamp max_ts_range_; - std::unordered_map stages_map_; //< Index map using BaseStage pointer as key - - FrameComposer frame_composer_; - - std::unordered_map sources_info_map_; - - FramePool output_frame_pool_; - FramePtr produced_frame_ptr_; -}; - -} // namespace Metavision - -#include "detail/frame_composition_stage_impl.h" - -#endif // METAVISION_SDK_CORE_FRAME_COMPOSITION_STAGE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/frame_generation_stage.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/frame_generation_stage.h deleted file mode 100644 index 2e019f645..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/frame_generation_stage.h +++ /dev/null @@ -1,84 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_FRAME_GENERATION_STAGE_H -#define METAVISION_SDK_CORE_FRAME_GENERATION_STAGE_H - -#include -#include -#include - -#include "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/algorithms/periodic_frame_generation_algorithm.h" - -namespace Metavision { - -/// @brief Stage that generates an OpenCV frame out of @ref EventCD events. -class FrameGenerationStage : public BaseStage { -public: - using FramePool = SharedObjectPool; - using FramePtr = FramePool::ptr_type; - using Output = std::pair; - - /// @brief Constructor - /// @param width Width of the frame. - /// @param height Height of the frame. - /// @param accumulation_time_ms Accumulation time (in ms) - /// @param fps The fps at which to generate the frames. The time reference used is the one from the input events - /// @param palette The Prophesee's color palette to use - /// @note If the fps is zero, @p accumulation_time_ms will be used instead as reference time to generate frames - FrameGenerationStage(int width, int height, uint32_t accumulation_time_ms = 10, double fps = 0., - const Metavision::ColorPalette &palette = BaseFrameGenerationAlgorithm::default_palette()) : - // using a queue of 2 frames to not pre-compute too many frames in advance - // which uses a lot of memory, and makes real-time interactions weird (due to the - // interaction operating on frames which will be displayed only much later) - frame_pool_(FramePool::make_bounded(2)) { - const uint32_t accumulation_time_us = accumulation_time_ms * 1000; - algo_ = std::make_unique(width, height, accumulation_time_us, fps, palette); - algo_->set_output_callback([this](const timestamp ts, cv::Mat &f) { - crt_frame_ptr_ = frame_pool_.acquire(); - cv::swap(f, *crt_frame_ptr_); - - produce(std::make_pair(ts, crt_frame_ptr_)); - }); - - set_consuming_callback([this](const boost::any &data) { consume_cd_events(data); }); - } - - /// @brief Constructor - /// @param prev_stage Previous stage. - /// @param width Width of the frame. - /// @param height Height of the frame. - /// @param fps Target of frames to generate per second. - FrameGenerationStage(BaseStage &prev_stage, int width, int height, int fps) : - FrameGenerationStage(width, height, fps) { - set_previous_stage(prev_stage); - } - -private: - void consume_cd_events(const boost::any &data) { - try { - auto buffer = boost::any_cast(data); - algo_->process_events(buffer->cbegin(), buffer->cend()); - } catch (boost::bad_any_cast &c) { MV_SDK_LOG_ERROR() << c.what(); } - } - - // Frames - FramePtr crt_frame_ptr_; - FramePool frame_pool_; - - std::unique_ptr algo_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_FRAME_GENERATION_STAGE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/pipeline.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/pipeline.h deleted file mode 100644 index 1b059c339..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/pipeline.h +++ /dev/null @@ -1,265 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_PIPELINE_H -#define METAVISION_SDK_CORE_PIPELINE_H - -#include -#include -#include -#include -#include -#include -#include - -#include "metavision/sdk/base/events/event_cd.h" - -namespace Metavision { - -class BaseStage; -template -class AlgorithmStage; - -template -constexpr bool is_base_stage = std::is_base_of::value; - -template -constexpr bool is_same_type = std::is_same::value; - -/// @brief Class that represents a pipeline of processing units (stages) and controls their execution -class Pipeline { - class TaskScheduler; - -public: - /// @brief Constructor - /// @param auto_detach If true, each stage added to the pipeline will automatically be detached (@ref - /// BaseStage::detach) - inline Pipeline(bool auto_detach = false); - - /// @brief Destructor - /// - /// The destructor ensures that the pipeline is stopped by calling @ref cancel - inline ~Pipeline(); - - /// @brief Adds a stage to the pipeline - /// @note The ownership of the stage is transferred to the pipeline. - /// If you need to further interact with this stage, use the returned reference to the stage. - /// @param stage Stage to add - /// @return @ref Stage "Stage&" The added stage - template::value>> - Stage &add_stage(std::unique_ptr &&stage); - - /// @brief Adds a stage to the pipeline - /// - /// Convenience overload - /// - /// This function does the same as the more verbose equivalent : - /// pipeline.add_stage(stage); - /// stage->set_previous_stage(prev_stage); - /// - /// @param stage Stage to add - /// @param prev_stage Previous stage - /// @return @ref Stage "Stage&" The added stage - template::value>> - Stage &add_stage(std::unique_ptr &&stage, BaseStage &prev_stage); - - /// @brief Adds a stage that wraps an algorithm as the consuming callback to the pipeline - /// - /// Convenience overload - /// - /// This function creates an instance of @ref AlgorithmStage and adds it to the pipeline. - /// - /// @warning Be mindful of the order of the template arguments: the output event type is given first, because most - /// of the time the InputEventType is EventCD, while the OutputEventType varies. - /// - /// @tparam OutputEventType Type of events produced by this stage, defaults to @ref EventCD - /// @tparam InputEventType Type of events consumed by this stage, defaults to @ref EventCD - /// @tparam Algorithm Type of algorithm wrapped in this stage, its type is inferred from the arguments - /// @param algo Wrapped algorithm - /// @return @ref AlgorithmStage "AlgorithmStage&" the created stage - template< - typename OutputEventType = EventCD, typename InputEventType = EventCD, typename Algorithm, - typename std::enable_if_t && !is_same_type, int> = 0> - AlgorithmStage &add_algorithm_stage(std::unique_ptr &&algo); - - /// @brief Adds a stage that wraps an algorithm as the consuming callback to the pipeline - /// - /// Convenience overload only available if InputEventType == OutputEventType. - /// - /// This function creates an instance of @ref AlgorithmStage and adds it to the pipeline. - /// - /// @warning Be mindful of the order of the template arguments: the output event type is given first, because most - /// of the time the InputEventType is EventCD, while the OutputEventType varies. - /// - /// @tparam OutputEventType Type of events produced by this stage, defaults to @ref EventCD - /// @tparam InputEventType Type of events consumed by this stage, defaults to @ref EventCD - /// @tparam Algorithm Type of algorithm wrapped in this stage, its type is inferred from the arguments - /// @param algo Wrapped algorithm - /// @param enabled If the stage is enabled by default - /// @return @ref AlgorithmStage "AlgorithmStage&" the created stage - template< - typename OutputEventType = EventCD, typename InputEventType = EventCD, typename Algorithm, - typename std::enable_if_t && is_same_type, int> = 0> - AlgorithmStage &add_algorithm_stage(std::unique_ptr &&algo, - bool enabled = true); - - /// @brief Adds a stage that wraps an algorithm as the consuming callback to the pipeline - /// - /// Convenience overload that also allows setting the previous stage. - /// - /// This function creates an instance of @ref AlgorithmStage and adds it to the pipeline. - /// - /// @warning Be mindful of the order of the template arguments: the output event type is given first, because most - /// of the time the InputEventType is EventCD, while the OutputEventType varies. - /// - /// @tparam OutputEventType Type of events produced by this stage, defaults to @ref EventCD - /// @tparam InputEventType Type of events consumed by this stage, defaults to @ref EventCD - /// @tparam Algorithm Type of algorithm wrapped in this stage, its type is inferred from the arguments - /// @param algo Wrapped algorithm - /// @param prev_stage Previous stage of this stage - /// @return @ref AlgorithmStage "AlgorithmStage&" the created stage - template< - typename OutputEventType = EventCD, typename InputEventType = EventCD, typename Algorithm, - typename std::enable_if_t && !is_same_type, int> = 0> - AlgorithmStage &add_algorithm_stage(std::unique_ptr &&algo, - BaseStage &prev_stage); - - /// @brief Adds a stage that wraps an algorithm as the consuming callback to the pipeline - /// - /// Convenience overload that also allows setting the previous stage and is only available if InputEventType == - /// OutputEventType. - /// - /// This function creates an instance of @ref AlgorithmStage and adds it to the pipeline. - /// - /// @warning Be mindful of the order of the template arguments: the output event type is given first, because most - /// of the time the InputEventType is EventCD, while the OutputEventType varies. - /// - /// @tparam OutputEventType Type of events produced by this stage, defaults to @ref EventCD - /// @tparam InputEventType Type of events consumed by this stage, defaults to @ref EventCD - /// @tparam Algorithm Type of algorithm wrapped in this stage, its type is inferred from the arguments - /// @param algo Wrapped algorithm - /// @param prev_stage Previous stage of this stage - /// @param enabled If the stage is enabled by default, ignored if @p InputEventType != @p OutputEventType - /// @return @ref AlgorithmStage "AlgorithmStage&" the created stage - template< - typename OutputEventType = EventCD, typename InputEventType = EventCD, typename Algorithm, - typename std::enable_if_t && is_same_type, int> = 0> - AlgorithmStage & - add_algorithm_stage(std::unique_ptr &&algo, BaseStage &prev_stage, bool enabled = true); - - /// @brief Removes a stage from the pipeline - /// - /// This has no effect if the stage was not already added to the pipeline. - /// @param stage Stage to remove - /// @note This function will also remove the stage from the list of previous and next stages - /// of any other stage in the pipeline. In particular, this means that proper care must be taken by the caller - /// to make sure the consuming callbacks of the stages affected by this removal are connected to another stage - /// in the pipeline with e.g @ref BaseStage::set_previous_stage or @ref BaseStage::set_consuming_callback - /// before the pipeline is started, as in the following example : - /// @code{.cpp} - /// Pipeline p; - /// auto& s1 = p.add_stage(std::make_unique()); - /// auto& s2 = p.add_stage(std::make_unique(), s1); - /// auto& s3 = p.add_stage(std::make_unique(), s2); - /// p.remove_stage(s2); - /// s3.set_previous_stage(s1); // without this line, s3 will wait forever since its previous stage has been - /// // removed and will not produce any data - /// @endcode - inline void remove_stage(BaseStage &stage); - - /// @brief Returns the number of stages inside the pipeline - /// @return size_t the number of stages inside the pipeline - inline size_t count() const; - - /// @brief Checks if the pipeline does not contain any stage - /// @return true if the pipeline is empty, false otherwise - inline bool empty() const; - - /// @brief Enum class representing the status of the pipeline - enum class Status { - /// if the stage has not yet been started - Inactive, - /// if the pipeline has been started - Started, - /// if the pipeline has been cancelled with @ref cancel - Cancelled, - /// if the pipeline has finished running - Completed - }; - - /// @brief Gets the status of the pipeline - /// @return @ref Status the status of the pipeline - inline Status status() const; - - /// @brief Executes a step of the pipeline - /// - /// This actually runs one of the scheduled callback on the main thread. - /// The processing threads runs on their own, but can be blocked by the main - /// thread if one stage needs to run on the main thread. - /// - /// @return true if the step was successful, false if the pipeline has no remaining steps to run - inline bool step(); - - /// @brief Runs the pipeline - /// - /// This will block until the execution of all the stages callbacks have been - /// executed. - /// This can be halted by calling @ref cancel. - /// - /// This is functionally equivalent to the following loop on a Pipeline p : - /// while (p.step()) {} - inline void run(); - - /// @brief Cancels the pipeline execution - /// - /// This will prevent any stage from producing any more data and will - /// cancel all scheduled callbacks, therefore immediately exiting the pipeline. - inline void cancel(); - - /// @brief A Callback called before of after the pipeline steps - /// @warning a StepCallback is not allowed to add another step callback otherwise the pipeline will deadlock - using StepCallback = std::function; - - /// @brief Adds a callback that will be called before the pipeline steps - /// @param cb The callback to call - /// @warning This method cannot be called from a step callback - inline void add_pre_step_callback(const StepCallback &cb); - - /// @brief Adds a callback that will be called after the pipeline steps - /// @param cb The callback to call - /// @warning This method cannot be called from a step callback - inline void add_post_step_callback(const StepCallback &cb); - -private: - inline BaseStage &add_stage_priv(std::unique_ptr &&stage); - inline void check_if_started(); - - inline void start(); - inline void stop(); - inline void schedule(BaseStage &stage, const std::function &task, size_t task_id, bool optional, - bool schedule_on_main_thread = true); - - bool auto_detach_stages_ = false; - std::mutex mutex_; - std::atomic status_{Status::Inactive}; - std::vector> stages_; - std::vector pre_step_cbs_; - std::vector post_step_cbs_; - std::unique_ptr scheduler_; - - friend class BaseStage; -}; - -} // namespace Metavision - -#include "detail/pipeline_impl.h" - -#endif // METAVISION_SDK_CORE_PIPELINE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/stage.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/stage.h deleted file mode 100644 index adde864f8..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/stage.h +++ /dev/null @@ -1,54 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_STAGE_H -#define METAVISION_SDK_CORE_STAGE_H - -#include -#include -#include -#include -#include -#include - -#include "metavision/sdk/core/pipeline/base_stage.h" - -namespace Metavision { - -/// @brief Simple stage that can be customized -/// -/// This class can be used to create a stage instance to be customized via -/// @ref set_consuming_callback, @ref set_starting_callback, @ref set_stopping_callback etc. -/// This can be an alternative to the creation of a new class inheriting @ref BaseStage. -class Stage : public BaseStage { -public: - /// @brief Constructor - /// @param detachable If this stage can be detached (i.e. can run on its own thread) - inline Stage(bool detachable = true) : BaseStage(detachable) {} - - /// @brief Constructor - /// - /// The @p prev_stage is used to setup the consuming callback - /// that will be called when the previous stage produces data. - /// When the previous stage produces data, it will call the consuming - /// callback (@ref set_consuming_callback) of this stage. - /// This behavior is automatically handled by this constructor. - /// If you need to customize the consuming callback of one (or all) of the previous stages, - /// you should use @ref set_consuming_callback instead. - /// - /// @param prev_stage the stage that is executed before the created one - /// @param detachable If this stage can be detached (i.e. can run on its own thread) - inline Stage(BaseStage &prev_stage, bool detachable = true) : BaseStage(prev_stage, detachable) {} -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_STAGE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/stream_logging_stage.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/stream_logging_stage.h deleted file mode 100644 index e9485f77d..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/stream_logging_stage.h +++ /dev/null @@ -1,72 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_STREAM_LOGGING_STAGE_H -#define METAVISION_SDK_CORE_STREAM_LOGGING_STAGE_H - -#include -#include -#include - -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/algorithms/stream_logger_algorithm.h" -#include "metavision/sdk/core/algorithms/stream_logger_algorithm.h" - -namespace Metavision { - -/// @brief Stage that runs @ref StreamLoggerAlgorithm -template -class StreamLoggingStage : public BaseStage { -public: - using EventBuffer = std::vector; - using EventBufferPool = SharedObjectPool; - using EventBufferPtr = typename EventBufferPool::ptr_type; - - /// @brief Constructor - /// @param filename Name of the output file - /// @param width Width of the frame - /// @param height Height of the frame - StreamLoggingStage(const std::string &filename, int width, int height) : - algo_(filename, static_cast(width), static_cast(height)) { - set_starting_callback([this] { algo_.enable(true); }); - set_stopping_callback([this] { algo_.enable(false); }); - set_consuming_callback([this](const boost::any &data) { - try { - auto buffer = boost::any_cast(data); - if (!buffer->empty()) - algo_.process_events(buffer->begin(), buffer->end(), buffer->back().t); - } catch (boost::bad_any_cast &) {} - }); - } - - /// @brief Constructor - /// @param prev_stage Previous Stage - /// @param filename Name of the output file - /// @param width Width of the frame - /// @param height Height of the frame - StreamLoggingStage(BaseStage &prev_stage, const std::string &filename, int width, int height) : - StreamLoggingStage(filename, width, height) { - set_previous_stage(prev_stage); - } - - /// @brief Gets algo - /// @return Algorithm class associated to this stage - StreamLoggerAlgorithm &algo() { - return algo_; - } - -private: - StreamLoggerAlgorithm algo_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_STREAM_LOGGING_STAGE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/video_writing_stage.h b/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/video_writing_stage.h deleted file mode 100644 index 78c4996ed..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/pipeline/video_writing_stage.h +++ /dev/null @@ -1,87 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_VIDEO_WRITING_STAGE_H -#define METAVISION_SDK_CORE_VIDEO_WRITING_STAGE_H - -#include -#include -#include -#include - -#include "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/algorithms/stream_logger_algorithm.h" - -namespace Metavision { - -/// @brief Stage that writes the input frames to a video file. -class VideoWritingStage : public BaseStage { -public: - using FramePool = SharedObjectPool; - using FramePtr = FramePool::ptr_type; - using FrameData = std::pair; - - /// @brief Constructor - /// @param filename Name of the output file. - /// @param width Width of the frame. - /// @param height Height of the frame. - /// @param fps Frames per second of the output video. - /// @param codec Codec used by OpenCV to encode the video. - /// @param colored If true the incoming frames are expected to be color frames, otherwise grayscale. - VideoWritingStage(const std::string &filename, int width, int height, int fps, const std::string &codec = "MJPG", - bool colored = true) { - if (codec.size() != 4) { - throw std::runtime_error("VideoWritingStage : codec must be a 4 letter word."); - } - -#if (CV_MAJOR_VERSION == 3 && CV_MINOR_VERSION >= 3) || CV_MAJOR_VERSION >= 4 - video_writer_.open(filename, cv::VideoWriter::fourcc(codec[0], codec[1], codec[2], codec[3]), fps, - cv::Size(width, height), colored); -#else - video_writer_.open(filename, CV_FOURCC(codec[0], codec[1], codec[2], codec[3]), fps, cv::Size(width, height), - colored); -#endif - - set_consuming_callback([this](const boost::any &data) { - try { - auto res = boost::any_cast(data); - video_writer_ << *(res.second); - } catch (boost::bad_any_cast &c) { MV_SDK_LOG_ERROR() << c.what(); } - }); - } - - /// @brief Constructor - /// @param prev_stage Previous stage. - /// @param filename Name of the output file. - /// @param width Width of the frame. - /// @param height Height of the frame. - /// @param fps Frames per second of the output video. - /// @param codec Codec used by OpenCV to encode the video. - /// @param colored If true the incoming frames are expected to be color frames, otherwise grayscale. - VideoWritingStage(BaseStage &prev_stage, const std::string &filename, int width, int height, int fps, - const std::string &codec = "MJPG", bool colored = true) : - VideoWritingStage(filename, width, height, fps, codec, colored) { - set_previous_stage(prev_stage); - } - - /// @brief Destructor - ~VideoWritingStage() { - video_writer_.release(); - } - -private: - cv::VideoWriter video_writer_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_VIDEO_WRITING_STAGE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/diff_processor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/diff_processor_impl.h new file mode 100644 index 000000000..0ce691e09 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/diff_processor_impl.h @@ -0,0 +1,66 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DETAIL_DIFF_PROCESSOR_IMPL_H +#define METAVISION_SDK_CORE_DETAIL_DIFF_PROCESSOR_IMPL_H + +#include "metavision/sdk/core/preprocessors/diff_processor.h" + +namespace Metavision { + +template +DiffProcessor::DiffProcessor(int event_input_width, int event_input_height, float max_incr_per_pixel, + float clip_value_after_normalization, float width_scale, float height_scale) : + EventPreprocessor(TensorShape({{"C", 1}, {"H", event_input_height}, {"W", event_input_width}}), + BaseType::FLOAT32), + clip_value_after_normalization_(clip_value_after_normalization), + width_(event_input_width) { + if (max_incr_per_pixel == 0.f) + throw std::invalid_argument("max_incr_per_pixel can't be 0"); + if (clip_value_after_normalization <= 0.f) + throw std::invalid_argument("clip_value_after_normalization must be > 0"); + + increment_ = 1.f / max_incr_per_pixel; + if (width_scale <= 0.f || height_scale <= 0.f) + throw std::runtime_error("Scaling factors for width and height should be > 0. Got " + + std::to_string(width_scale) + " and " + std::to_string(height_scale)); + + // Further normalize the increment_ to make up for adding more events per frame cell (when there is a previous + // rescaling of events) + increment_ *= width_scale * height_scale; +} + +template +void DiffProcessor::compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, + Tensor &tensor) const { + assert(tensor.type() == BaseType::FLOAT32); + auto buff = tensor.data(); + const auto buff_size = tensor.shape().get_nb_values(); + for (auto it = begin; it != end; ++it) { + const auto &ev = *it; + assert((ev.p == 0) || (ev.p == 1)); + assert(ev.t >= cur_frame_start_ts); + assert(ev.x >= 0); + assert(ev.x < width_); + assert(ev.y >= 0); + assert(ev.y < get_dim(this->output_tensor_shape_, "H")); + const int idx = ev.x + width_ * ev.y; + assert(idx >= 0); + assert(idx < static_cast(buff_size)); + const int p = 2 * ev.p - 1; + buff[idx] = std::max(-clip_value_after_normalization_, + std::min(clip_value_after_normalization_, buff[idx] + increment_ * p)); + } +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_DETAIL_DIFF_PROCESSOR_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_cube_processor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_cube_processor_impl.h new file mode 100644 index 000000000..4ce376609 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_cube_processor_impl.h @@ -0,0 +1,108 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DETAIL_EVENT_CUBE_PROCESSOR_IMPL_H +#define METAVISION_SDK_CORE_DETAIL_EVENT_CUBE_PROCESSOR_IMPL_H + +#include "metavision/sdk/core/preprocessors/event_cube_processor.h" + +#include + +namespace Metavision { + +template +EventCubeProcessor::EventCubeProcessor(timestamp delta_t, int event_input_width, int event_input_height, + int num_utbins, bool split_polarity, float max_incr_per_pixel, + float clip_value_after_normalization, float width_scale, + float height_scale) : + EventPreprocessor(TensorShape({{"C", 1}, {"H", event_input_height}, {"W", event_input_width}}), + BaseType::FLOAT32), + width_(event_input_width), + // Further normalize to make up for adding more events per cell (when there is a previous rescaling of events) + normalization_factor_(1.f / max_incr_per_pixel * width_scale * height_scale), + split_polarity_(split_polarity), + num_polarities_(split_polarity_ ? 2 : 1), + num_utbins_(num_utbins), + clip_value_after_normalization_(clip_value_after_normalization), + num_utbins_over_delta_t_(static_cast(num_utbins) / delta_t), + w_h_(event_input_width * event_input_height), + w_h_p_(w_h_ * num_polarities_) { + if (num_utbins <= 0) + throw std::runtime_error("num_utbins should be >0. Got " + std::to_string(num_utbins)); + if (max_incr_per_pixel <= 0) + throw std::runtime_error("max_incr_per_pixel should be >0. Got " + std::to_string(max_incr_per_pixel)); + if (width_scale <= 0.f || height_scale <= 0.f) + throw std::runtime_error("Scaling factors for width and height should be > 0. Got " + + std::to_string(width_scale) + " and " + std::to_string(height_scale)); + if (clip_value_after_normalization_ <= 0.f) + throw std::runtime_error("Clip value after nrmalization should be >0. Got " + + std::to_string(clip_value_after_normalization_)); + + const auto network_num_channels_ = num_polarities_ * num_utbins_; + set_dim(this->output_tensor_shape_, "C", network_num_channels_); +} + +template +void EventCubeProcessor::set_value(float *buff, const std::size_t buff_size, const int bin, const int p, + const int x, const int y, const float val) const { + const int idx = x + (y * width_) + p * (w_h_) + bin * (w_h_p_); + assert(idx >= 0); + assert(idx < static_cast(buff_size)); + if (clip_value_after_normalization_ != 0.f) { + buff[idx] = + std::max(-clip_value_after_normalization_, std::min(clip_value_after_normalization_, buff[idx] + val)); + } else { + buff[idx] += val; + } +} + +template +void EventCubeProcessor::compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, + Tensor &tensor) const { + assert(tensor.type() == BaseType::FLOAT32); + auto buff = tensor.data(); + const auto buff_size = tensor.shape().get_nb_values(); + assert(buff_size == this->output_tensor_shape_.get_nb_values()); + for (auto it = begin; it != end; ++it) { + auto &ev = *it; + assert((ev.p == 0) || (ev.p == 1)); + assert(ev.t >= cur_frame_start_ts); + assert(ev.x >= 0); + assert(ev.x < get_dim(this->output_tensor_shape_, "W")); + assert(ev.y >= 0); + assert(ev.y < get_dim(this->output_tensor_shape_, "H")); + + const float ti_star = ((ev.t - cur_frame_start_ts) * num_utbins_over_delta_t_) - 0.5f; + const int lbin = floor(ti_star); + const int rbin = lbin + 1; + + float left_value = std::max(0.f, 1.f - std::abs(lbin - ti_star)); + float right_value = 1.f - left_value; + + const int p = split_polarity_ ? ev.p : 0; + if (!split_polarity_) { + const int pol = ev.p ? ev.p : -1; + left_value *= pol; + right_value *= pol; + } + + if ((lbin >= 0) && (lbin < num_utbins_)) { + set_value(buff, buff_size, lbin, p, ev.x, ev.y, left_value * normalization_factor_); + } + if (rbin < num_utbins_) { + set_value(buff, buff_size, rbin, p, ev.x, ev.y, right_value * normalization_factor_); + } + } +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_DETAIL_EVENT_CUBE_PROCESSOR_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_preprocessor_factory_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_preprocessor_factory_impl.h new file mode 100644 index 000000000..2736cf6af --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_preprocessor_factory_impl.h @@ -0,0 +1,120 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DETAIL_EVENT_PREPROCESSOR_FACTORY_IMPL_H +#define METAVISION_SDK_CORE_DETAIL_EVENT_PREPROCESSOR_FACTORY_IMPL_H + +#include + +#include "metavision/sdk/core/preprocessors/event_preprocessor_type.h" +#include "metavision/sdk/core/preprocessors/json_parser.h" + +#include "metavision/sdk/core/preprocessors/diff_processor.h" +#include "metavision/sdk/core/preprocessors/event_cube_processor.h" +#include "metavision/sdk/core/preprocessors/hardware_diff_processor.h" +#include "metavision/sdk/core/preprocessors/hardware_histo_processor.h" +#include "metavision/sdk/core/preprocessors/histo_processor.h" +#include "metavision/sdk/core/preprocessors/time_surface_processor.h" + +#include "metavision/sdk/core/preprocessors/event_preprocessor_factory.h" + +namespace Metavision { + +namespace EventPreprocessorFactory { + +template +std::unique_ptr> + create(const std::unordered_map &proc_params, + const TensorShape &tensor_shape) { + const int evt_height = get_dim(tensor_shape, "H"); + const int evt_width = get_dim(tensor_shape, "W"); + const EventPreprocessorType processing_type = std::get(proc_params.at("type")); + switch (processing_type) { + case EventPreprocessorType::DIFF: { + const float max_incr_per_pixel = std::get(proc_params.at("max_incr_per_pixel")); + if (max_incr_per_pixel <= 0.f) + throw std::runtime_error("max_incr_per_pixel must be strictly greater than 0"); + const float clip_value_after_normalization = std::get(proc_params.at("clip_value_after_normalization")); + if (clip_value_after_normalization < 0.f) + throw std::runtime_error("clip_value_after_normalization must be equal or greater than zero"); + const float scale_width = + proc_params.count("scale_width") ? std::get(proc_params.at("scale_width")) : 1.f; + const float scale_height = + proc_params.count("scale_height") ? std::get(proc_params.at("scale_height")) : 1.f; + return std::make_unique>(evt_width, evt_height, max_incr_per_pixel, + clip_value_after_normalization, scale_width, scale_height); + } + case EventPreprocessorType::HISTO: { + const float max_incr_per_pixel = std::get(proc_params.at("max_incr_per_pixel")); + if (max_incr_per_pixel <= 0.f) + throw std::runtime_error("max_incr_per_pixel must be strictly greater than 0"); + const float clip_value_after_normalization = std::get(proc_params.at("clip_value_after_normalization")); + if (clip_value_after_normalization < 0.f) + throw std::runtime_error("clip_value_after_normalization must be equal or greater than zero"); + const float use_CHW = std::get(proc_params.at("use_CHW")); + const float scale_width = + proc_params.count("scale_width") ? std::get(proc_params.at("scale_width")) : 1.f; + const float scale_height = + proc_params.count("scale_height") ? std::get(proc_params.at("scale_height")) : 1.f; + return std::make_unique>(evt_width, evt_height, max_incr_per_pixel, + clip_value_after_normalization, use_CHW, scale_width, + scale_height); + } + case EventPreprocessorType::EVENT_CUBE: { + const timestamp accumulation_time = std::get(proc_params.at("delta_t")); + const float max_incr_per_pixel = std::get(proc_params.at("max_incr_per_pixel")); + if (max_incr_per_pixel <= 0.f) + throw std::runtime_error("max_incr_per_pixel must be strictly greater than 0"); + const float clip_value_after_normalization = std::get(proc_params.at("clip_value_after_normalization")); + if (clip_value_after_normalization < 0.f) + throw std::runtime_error("clip_value_after_normalization must be equal or greater than zero"); + const int num_utbins = std::get(proc_params.at("num_utbins")); + const bool split_polarity = std::get(proc_params.at("split_polarity")); + const float scale_width = + proc_params.count("scale_width") ? std::get(proc_params.at("scale_width")) : 1.f; + const float scale_height = + proc_params.count("scale_height") ? std::get(proc_params.at("scale_height")) : 1.f; + return std::make_unique>(accumulation_time, evt_width, evt_height, num_utbins, + split_polarity, max_incr_per_pixel, + clip_value_after_normalization, scale_width, scale_height); + } + case EventPreprocessorType::HARDWARE_DIFF: { + const int8_t min_val = std::get(proc_params.at("min_val")); + const int8_t max_val = std::get(proc_params.at("max_val")); + const bool allow_rollover = std::get(proc_params.at("allow_rollover")); + return std::make_unique>(evt_width, evt_height, min_val, max_val, + allow_rollover); + } + case EventPreprocessorType::HARDWARE_HISTO: { + const uint8_t neg_saturation = std::get(proc_params.at("neg_saturation")); + const uint8_t pos_saturation = std::get(proc_params.at("pos_saturation")); + return std::make_unique>(evt_width, evt_height, neg_saturation, pos_saturation); + } + case EventPreprocessorType::TIME_SURFACE: { + const uint8_t nb_channels = std::get(proc_params.at("nb_channels")); + if (nb_channels == 1) + return std::make_unique>(evt_width, evt_height); + else if (nb_channels == 2) + return std::make_unique>(evt_width, evt_height); + else + throw std::runtime_error("For TimeSurface preprocessing, number of channels should be 1 or 2."); + } + default: + throw std::runtime_error("Unknown EventPreprocessor type: " + + eventPreprocessorTypeToStringMap.at(processing_type)); + } +} + +} // namespace EventPreprocessorFactory + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_DETAIL_EVENT_PREPROCESSOR_FACTORY_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_preprocessor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_preprocessor_impl.h new file mode 100644 index 000000000..affb9122e --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/event_preprocessor_impl.h @@ -0,0 +1,87 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DETAIL_EVENT_PREPROCESSOR_IMPL_H +#define METAVISION_SDK_CORE_DETAIL_EVENT_PREPROCESSOR_IMPL_H + +#include "metavision/sdk/core/preprocessors/json_parser.h" + +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" + +namespace Metavision { + +template +EventPreprocessor::EventPreprocessor(const TensorShape &shape, const BaseType &type) : + output_tensor_shape_(shape), output_tensor_type_(type) { + const auto output_width = get_dim(shape, "W"); + const auto output_height = get_dim(shape, "H"); + if ((output_width < 1) || (output_height < 1)) { + std::ostringstream oss; + oss << "EventPreprocessor : invalid value for provided output frame shape (width and height must be >= 1): "; + oss << output_width << "x" << output_height << std::endl; + throw std::invalid_argument(oss.str()); + } +} + +template +const TensorShape &EventPreprocessor::get_output_shape() const { + return this->output_tensor_shape_; +} + +template +BaseType EventPreprocessor::get_output_type() const { + return this->output_tensor_type_; +} + +template +bool EventPreprocessor::has_expected_shape(const Tensor &t) const { + const auto &actual_dimensions = t.shape().dimensions; + const auto &expected_dimensions = this->output_tensor_shape_.dimensions; + const size_t n_actual = actual_dimensions.size(); + const size_t n_expected = expected_dimensions.size(); + unsigned int i = 0, j = 0; + while (i < n_actual) { + if (actual_dimensions[i].dim > 1) { + const auto &name = actual_dimensions[i].name; + while (j < n_expected && expected_dimensions[j].dim <= 1) + ++j; + if (j == n_expected || name != expected_dimensions[j].name || + actual_dimensions[i].dim != expected_dimensions[j].dim) + return false; + ++i; + ++j; + } else { + ++i; + } + } + return true; +} + +template +void EventPreprocessor::process_events(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, + Tensor &tensor) const { + if (begin == end) { + return; + } + + if (!has_expected_shape(tensor)) { + std::stringstream msg; + msg << "Incompatible tensor provided : expected shape " << this->output_tensor_shape_ << " but got shape " + << tensor.shape() << std::endl; + throw std::runtime_error(msg.str()); + } + + compute(cur_frame_start_ts, begin, end, tensor); +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_DETAIL_EVENT_PREPROCESSOR_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/hardware_diff_processor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/hardware_diff_processor_impl.h new file mode 100644 index 000000000..826290c9e --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/hardware_diff_processor_impl.h @@ -0,0 +1,54 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_HARDWARE_DIFF_PROCESSOR_IMPL_H +#define METAVISION_SDK_CORE_HARDWARE_DIFF_PROCESSOR_IMPL_H + +#include "metavision/sdk/core/preprocessors/hardware_diff_processor.h" + +namespace Metavision { + +template +HardwareDiffProcessor::HardwareDiffProcessor(int width, int height, int8_t min_val, int8_t max_val, + bool allow_rollover) : + EventPreprocessor(TensorShape({{"H", height}, {"W", width}, {"C", 1}}), BaseType::INT8), + allow_rollover_(allow_rollover), + min_val_(min_val), + max_val_(max_val), + width_(width) {} + +template +void HardwareDiffProcessor::process_events(InputIt begin, InputIt end, RawEventFrameDiff &diff) const { + Tensor wrapper(this->output_tensor_shape_, this->output_tensor_type_, + reinterpret_cast(diff.get_data().data()), false); + process_events(begin, end, wrapper); +} + +template +void HardwareDiffProcessor::compute(const timestamp, InputIt it_begin, InputIt it_end, Tensor &tensor) const { + auto diff = tensor.data(); + for (auto it = it_begin; it != it_end; ++it) { + const unsigned int idx = it->x + it->y * width_; + int8_t &sum_polarities = diff[idx]; + const bool should_rollover = + (sum_polarities == min_val_ && it->p == 0) || (sum_polarities == max_val_ && it->p == 1); + if (!should_rollover) { + sum_polarities += (it->p == 0 ? -1 : 1); + } else if (allow_rollover_) { + sum_polarities = (it->p == 0 ? max_val_ : min_val_); + } + // else sum_polarities is saturated + } +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_HARDWARE_DIFF_PROCESSOR_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/hardware_histo_processor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/hardware_histo_processor_impl.h new file mode 100644 index 000000000..cb6fa0b4d --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/hardware_histo_processor_impl.h @@ -0,0 +1,51 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_HARDWARE_HISTO_PROCESSOR_IMPL_H +#define METAVISION_SDK_CORE_HARDWARE_HISTO_PROCESSOR_IMPL_H + +#include + +#include "metavision/sdk/core/preprocessors/hardware_histo_processor.h" + +namespace Metavision { + +template +HardwareHistoProcessor::HardwareHistoProcessor(int width, int height, uint8_t neg_saturation, + uint8_t pos_saturation) : + EventPreprocessor(TensorShape({{"H", height}, {"W", width}, {"C", 2}}), BaseType::UINT8), + sum_max_neg_(neg_saturation), + sum_max_pos_(pos_saturation), + width_(width) {} + +template +void HardwareHistoProcessor::process_events(InputIt begin, InputIt end, RawEventFrameHisto &histo) const { + Tensor wrapper(this->output_tensor_shape_, this->output_tensor_type_, + reinterpret_cast(histo.get_data().data()), false); + process_events(0, begin, end, wrapper); +} + +template +void HardwareHistoProcessor::compute(const timestamp, InputIt it_begin, InputIt it_end, Tensor &tensor) const { + auto histo = tensor.data(); + for (auto it = it_begin; it != it_end; ++it) { + const unsigned int idx = it->p + (it->x + it->y * width_) * 2; + const uint8_t sum_max = (it->p == 0 ? sum_max_neg_ : sum_max_pos_); + uint8_t &sum_events = histo[idx]; + if (sum_events <= sum_max - 1) + ++sum_events; + // else sum_events is saturated + } +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_HARDWARE_HISTO_PROCESSOR_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/histo_processor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/histo_processor_impl.h new file mode 100644 index 000000000..1e3a92acd --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/histo_processor_impl.h @@ -0,0 +1,89 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DETAIL_HISTO_PROCESSOR_IMPL_H +#define METAVISION_SDK_CORE_DETAIL_HISTO_PROCESSOR_IMPL_H + +#include "metavision/sdk/core/preprocessors/histo_processor.h" + +namespace Metavision { + +template +HistoProcessor::HistoProcessor(int event_input_width, int event_input_height, float max_incr_per_pixel, + float clip_value_after_normalization, bool use_CHW, float width_scale, + float height_scale) : + EventPreprocessor((use_CHW) ? + TensorShape({{"C", 2}, {"H", event_input_height}, {"W", event_input_width}}) : + TensorShape({{"H", event_input_height}, {"W", event_input_width}, {"C", 2}}), + BaseType::FLOAT32), + clip_value_after_normalization_(clip_value_after_normalization), + width_(event_input_width), + height_(event_input_height), + channels_(2) { + if (max_incr_per_pixel == 0.f) + throw std::invalid_argument("max_incr_per_pixel can't be 0"); + if (clip_value_after_normalization <= 0.f) + throw std::invalid_argument("clip_value_after_normalization must be > 0"); + if (width_scale <= 0.f || height_scale <= 0.f) + throw std::runtime_error("Scaling factors for width and height should be > 0. Got " + + std::to_string(width_scale) + " and " + std::to_string(height_scale)); + + increment_ = 1.f / max_incr_per_pixel; + // Further normalize the increment_ to make up for adding more events per histogram cell (when there is a previous + // rescaling of events) + increment_ *= width_scale * height_scale; +} + +template +bool HistoProcessor::is_CHW(const Tensor &t) const { + const auto &dimensions = t.shape().dimensions; + return dimensions[0].name == "C" && dimensions[1].name == "H" && dimensions[2].name == "W"; +} + +template +void HistoProcessor::compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, + Tensor &tensor) const { + assert(tensor.type() == BaseType::FLOAT32); + auto buff = tensor.data(); + const auto buff_size = tensor.shape().get_nb_values(); + assert(buff_size == this->output_tensor_shape_.get_nb_values()); + if (is_CHW(tensor)) { + for (auto it = begin; it != end; ++it) { + const auto &ev = *it; + assert((ev.p == 0) || (ev.p == 1)); + assert(ev.t >= cur_frame_start_ts); + assert(ev.x >= 0); + assert(ev.x < width_); + assert(ev.y >= 0); + assert(ev.y < height_); + const int idx = width_ * (height_ * ev.p + ev.y) + ev.x; + assert(idx < static_cast(buff_size)); + buff[idx] = std::min(clip_value_after_normalization_, buff[idx] + increment_); + } + } else { + for (auto it = begin; it != end; ++it) { + const auto &ev = *it; + assert((ev.p == 0) || (ev.p == 1)); + assert(ev.t >= cur_frame_start_ts); + assert(ev.x >= 0); + assert(ev.x < width_); + assert(ev.y >= 0); + assert(ev.y < height_); + const int idx = channels_ * (width_ * ev.y + ev.x) + ev.p; + assert(idx < static_cast(buff_size)); + buff[idx] = std::min(clip_value_after_normalization_, buff[idx] + increment_); + } + } +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_DETAIL_HISTO_PROCESSOR_IMPL_H diff --git a/sdk/modules/driver/cpp/src/antiflicker_module.cpp b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/json_parser_impl.h similarity index 64% rename from sdk/modules/driver/cpp/src/antiflicker_module.cpp rename to sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/json_parser_impl.h index d56d4c3d1..3c378cd8e 100644 --- a/sdk/modules/driver/cpp/src/antiflicker_module.cpp +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/json_parser_impl.h @@ -9,32 +9,26 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/antiflicker_module.h" +#ifndef METAVISION_SDK_CORE_PREPROCESSORS_JSON_PARSER_IMPL_H +#define METAVISION_SDK_CORE_PREPROCESSORS_JSON_PARSER_IMPL_H -namespace Metavision { - -AntiFlickerModule::AntiFlickerModule(I_AntiFlickerModule *afk) : pimpl_(afk) {} - -AntiFlickerModule::~AntiFlickerModule() {} - -void AntiFlickerModule::enable(bool b) { - pimpl_->enable(b); -} - -bool AntiFlickerModule::is_enabled() { - return pimpl_->is_enabled(); -} - -void AntiFlickerModule::set_frequency_band(uint32_t min_freq, uint32_t max_freq) { - pimpl_->set_frequency_band(min_freq, max_freq); -} +#include "metavision/sdk/core/preprocessors/json_parser.h" -void AntiFlickerModule::set_filtering_mode(I_AntiFlickerModule::AntiFlickerMode mode) { - pimpl_->set_filtering_mode(mode); -} +namespace Metavision { -I_AntiFlickerModule *AntiFlickerModule::get_facility() const { - return pimpl_; +template +T get_element_from_ptree(const boost::property_tree::ptree &pt, const std::string &key) { + try { + T value = pt.get(key); + return value; + } catch (const boost::property_tree::ptree_error &e) { + std::ostringstream oss; + oss << "Error: could not find the key '" << key << "' in provided tree." << std::endl; + oss << e.what() << std::endl; + throw std::runtime_error(oss.str()); + } } } // namespace Metavision + +#endif // METAVISION_SDK_CORE_PREPROCESSORS_JSON_PARSER_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/tensor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/tensor_impl.h new file mode 100644 index 000000000..5afdfbf19 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/tensor_impl.h @@ -0,0 +1,83 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_PREPROCESSORS_TENSOR_IMPL_H +#define METAVISION_SDK_CORE_PREPROCESSORS_TENSOR_IMPL_H + +#include + +#include "metavision/sdk/core/preprocessors/tensor.h" + +namespace Metavision { + +template +const T *Tensor::data() const { + return reinterpret_cast(ptr_); +} + +template +T *Tensor::data() { + return reinterpret_cast(ptr_); +} + +template +void Tensor::set_to_impl(T typed_val, size_t n) { + auto ptr = reinterpret_cast(ptr_); + std::fill(ptr, ptr + n, typed_val); +} + +template +void Tensor::set_to(T val) { + const size_t n = shape_.get_nb_values(); + switch (type_) { + case BaseType::BOOL: + set_to_impl(static_cast(val), n); + break; + case BaseType::UINT8: + set_to_impl(static_cast(val), n); + break; + case BaseType::UINT16: + set_to_impl(static_cast(val), n); + break; + case BaseType::UINT32: + set_to_impl(static_cast(val), n); + break; + case BaseType::UINT64: + set_to_impl(static_cast(val), n); + break; + case BaseType::INT8: + set_to_impl(static_cast(val), n); + break; + case BaseType::INT16: + set_to_impl(static_cast(val), n); + break; + case BaseType::INT32: + set_to_impl(static_cast(val), n); + break; + case BaseType::INT64: + set_to_impl(static_cast(val), n); + break; + case BaseType::FLOAT32: + set_to_impl(static_cast(val), n); + break; + case BaseType::FLOAT64: + set_to_impl(static_cast(val), n); + break; + case BaseType::FLOAT16: + throw std::runtime_error("No implementation yet for 2-byte float"); + default: + throw std::runtime_error("Provided data type not managed."); + } +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_PREPROCESSORS_TENSOR_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/time_surface_processor_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/time_surface_processor_impl.h new file mode 100644 index 000000000..dfe4f79ec --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/detail/time_surface_processor_impl.h @@ -0,0 +1,46 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DETAIL_TIME_SURFACE_PROCESSOR_IMPL_H +#define METAVISION_SDK_CORE_DETAIL_TIME_SURFACE_PROCESSOR_IMPL_H + +#include "metavision/sdk/core/preprocessors/time_surface_processor.h" + +namespace Metavision { + +template +TimeSurfaceProcessor::TimeSurfaceProcessor(int width, int height) : + EventPreprocessor(TensorShape({{"H", height}, {"W", width}, {"C", CHANNELS}}), BaseType::INT64), + width_(width) {} + +template +void TimeSurfaceProcessor::process_events(InputIt begin, InputIt end, + MostRecentTimestampBuffer &time_surface) const { + Tensor wrapper(this->output_tensor_shape_, this->output_tensor_type_, + reinterpret_cast(time_surface.ptr()), false); + process_events(0, begin, end, wrapper); +} + +template +void TimeSurfaceProcessor::compute(const timestamp, InputIt it_begin, InputIt it_end, + Tensor &tensor) const { + auto buffer = tensor.data(); + for (auto it = it_begin; it != it_end; ++it) { + assert(it->p == 0 || it->p == 1); + const auto c = (CHANNELS == 1) ? 0 : it->p; + const int idx = CHANNELS * (width_ * it->y + it->x) + c; + buffer[idx] = it->t; + } +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_DETAIL_TIME_SURFACE_PROCESSOR_IMPL_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/diff_processor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/diff_processor.h new file mode 100644 index 000000000..97a119f93 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/diff_processor.h @@ -0,0 +1,49 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_DIFF_PROCESSOR_H +#define METAVISION_SDK_CORE_DIFF_PROCESSOR_H + +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" + +namespace Metavision { + +/// @brief Class used to compute the diff image from a stream of EventCD +/// @tparam InputIt The type of the input iterator for the range of events to process +template +class DiffProcessor : public EventPreprocessor { +public: + /// @brief Constructor + /// @param event_input_width Maximum width of input events + /// @param event_input_height Maximum height of input events + /// @param max_incr_per_pixel Maximum number of increments per pixel. This is used to normalize the contribution of + /// each event + /// @param clip_value_after_normalization Clipping value to apply after normalization (typically: 1.) + /// @param width_scale Scale on the width previously applied to input events. This factor is considered to modulate + /// the contribution of each event at its coordinates. + /// @param height_scale Scale on the height previously applied to input events. This factor is considered to + /// modulate the contribution of each event at its coordinates. + DiffProcessor(int event_input_width, int event_input_height, float max_incr_per_pixel, + float clip_value_after_normalization, float width_scale = 1.f, float height_scale = 1.f); + +private: + void compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, Tensor &tensor) const override; + + float increment_; + const float clip_value_after_normalization_; + const int width_; +}; + +} // namespace Metavision + +#include + +#endif // METAVISION_SDK_CORE_DIFF_PROCESSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_cube_processor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_cube_processor.h new file mode 100644 index 000000000..c45327fb3 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_cube_processor.h @@ -0,0 +1,64 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_EVENT_CUBE_PROCESSOR_H +#define METAVISION_SDK_CORE_EVENT_CUBE_PROCESSOR_H + +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" + +namespace Metavision { + +/// @brief Class used to compute an event cube from a stream of EventCD +/// @tparam InputIt The type of the input iterator for the range of events to process +template +class EventCubeProcessor : public EventPreprocessor { +public: + EventCubeProcessor() = default; + + /// @brief Constructor + /// @param delta_t Delta time used to accumulate events inside the frame + /// @param event_input_width Width of the event stream + /// @param event_input_height Height of the event stream + /// @param num_utbins Number of micro temporal bins + /// @param split_polarity Process positive and negative events into separate channels + /// @param max_incr_per_pixel Maximum number of increments per pixel. This is used to normalize the contribution of + /// each event + /// @param clip_value_after_normalization Clipping value to apply after normalization (typically: 1.) + /// @param width_scale Scale on the width previously applied to input events. This factor is considered to modulate + /// the contribution of each event at its coordinates. + /// @param height_scale Scale on the height previously applied to input events. This factor is considered to + /// modulate the contribution of each event at its coordinates. + EventCubeProcessor(timestamp delta_t, int event_input_width, int event_input_height, int num_utbins, + bool split_polarity, float max_incr_per_pixel, float clip_value_after_normalization = 0.f, + float width_scale = 1.f, float height_scale = 1.f); + +private: + inline void set_value(float *buff, const std::size_t buff_size, const int bin, const int p, const int x, + const int y, const float val) const; + + void compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, Tensor &tensor) const override; + + const float normalization_factor_; + const bool split_polarity_; + const int num_utbins_; + const float clip_value_after_normalization_; + const int num_polarities_; + const float num_utbins_over_delta_t_; + const int w_h_; // network_input_width * network_input_height + const int w_h_p_; // network_input_width * network_input_height * num_polarities + const int width_; +}; + +} // namespace Metavision + +#include + +#endif // METAVISION_SDK_CORE_EVENT_CUBE_PROCESSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor.h new file mode 100644 index 000000000..408be6877 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor.h @@ -0,0 +1,73 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_EVENT_PREPROCESSOR_H +#define METAVISION_SDK_CORE_EVENT_PREPROCESSOR_H + +#include + +#include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/core/preprocessors/tensor.h" + +namespace Metavision { + +/// @brief Processes events to update data from a tensor. +/// +/// This is the base class. It handles the rescaling of the events if necessary. +/// It also provides accessors to get the shape of the output tensor. +/// Derived class implement the computation. +/// Calling process_events() on this base class triggers the computation to update the provided tensor. +/// This tensor can typically be used as input of a neural network. +/// @tparam InputIt The type of the input iterator for the range of events to process +template +class EventPreprocessor { +public: + /// @brief Retrieves the shape of the processor's output tensor. + /// This shape can be used to initialize the output tensor provided to the @ref process_events method. + /// @returns The output tensor shape + const TensorShape &get_output_shape() const; + + /// @brief Retrieves the type of the processor's output tensor + /// This type can be used to initialize the output tensor provided to the @ref process_events method. + /// @returns The output tensor type + BaseType get_output_type() const; + + /// @brief Updates the output tensor depending on the input events + /// @param[in] cur_frame_start_ts starting timestamp of the current frame + /// @param[in] begin Begin iterator + /// @param[in] end End iterator + /// @param[out] tensor Updated output tensor + /// @warning The tensor needs to have its memory already allocated, which can be done thanks to the class @ref + /// get_output_shape and + /// @ref get_output_type methods and the Tensor method @ref Tensor::create. + void process_events(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, Tensor &tensor) const; + +protected: + /// @brief Constructor + /// @param shape Shape of the output tensor to update with events + /// @param type Type of the data contained in the output tensor to update + EventPreprocessor(const TensorShape &shape, const BaseType &type); + + TensorShape output_tensor_shape_; + const BaseType output_tensor_type_; + +private: + virtual void compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, Tensor &tensor) const = 0; + + /// @brief Returns true if the provided tensor has the expected shape + bool has_expected_shape(const Tensor &t) const; +}; + +} // namespace Metavision + +#include "metavision/sdk/core/preprocessors/detail/event_preprocessor_impl.h" + +#endif // METAVISION_SDK_CORE_EVENT_PREPROCESSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/time_surface_producer_algorithm_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor_factory.h similarity index 50% rename from sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/time_surface_producer_algorithm_impl.h rename to sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor_factory.h index 81f4c6a11..aeebbe97c 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/algorithms/detail/time_surface_producer_algorithm_impl.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor_factory.h @@ -9,40 +9,33 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_CORE_TIME_SURFACE_PRODUCER_ALGORITHM_IMPL_H -#define METAVISION_SDK_CORE_TIME_SURFACE_PRODUCER_ALGORITHM_IMPL_H +#ifndef METAVISION_SDK_CORE_EVENT_PREPROCESSOR_FACTORY_H +#define METAVISION_SDK_CORE_EVENT_PREPROCESSOR_FACTORY_H -namespace Metavision { +#include -template -TimeSurfaceProducerAlgorithm::TimeSurfaceProducerAlgorithm(int width, int height) : - time_surface_(height, width, CHANNELS) { - time_surface_.set_to(0); +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" - output_cb_ = [](timestamp, const MostRecentTimestampBuffer &) {}; -} +namespace Metavision { -template -void TimeSurfaceProducerAlgorithm::set_output_callback(const OutputCb &cb) { - output_cb_ = cb; -} +namespace EventPreprocessorFactory { -template +/// @brief Creates the event processor in adequation with the parameters map describing the event processing to apply +/// @details The map should contain a 'type' key, describing the type of preprocessor to create, as well as the +/// necessary parameters for the selected processor. +/// @tparam InputIt The type of the input iterator for the range of events to process +/// @param proc_params Parameters describing the processor to instantiate +/// @param tensor_shape Shape of the tensor to fill with preprocessed data (it must match the dimensions of the events +/// which will be passed to the processor). It is expected to provide at least "H" and "W" dimensions. template -inline void TimeSurfaceProducerAlgorithm::process_online(InputIt it_begin, InputIt it_end) { - for (auto it = it_begin; it != it_end; ++it) { - assert(it->p == 0 || it->p == 1); - const auto c = (CHANNELS == 1) ? 0 : it->p; - time_surface_.at(it->y, it->x, c) = it->t; - } -} - -template -void TimeSurfaceProducerAlgorithm::process_async(const timestamp processing_ts, - const size_t n_processed_events) { - output_cb_(processing_ts, time_surface_); -} +std::unique_ptr> + create(const std::unordered_map &proc_params, + const TensorShape &tensor_shape); + +} // namespace EventPreprocessorFactory } // namespace Metavision -#endif // METAVISION_SDK_CORE_TIME_SURFACE_PRODUCER_ALGORITHM_IMPL_H +#include "metavision/sdk/core/preprocessors/detail/event_preprocessor_factory_impl.h" + +#endif // METAVISION_SDK_CORE_EVENT_PREPROCESSOR_FACTORY_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor_type.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor_type.h new file mode 100644 index 000000000..1162e003a --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/event_preprocessor_type.h @@ -0,0 +1,47 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_EVENT_PREPROCESSOR_TYPE_H +#define METAVISION_SDK_CORE_EVENT_PREPROCESSOR_TYPE_H + +#include +#include + +namespace Metavision { + +enum class EventPreprocessorType : uint8_t { DIFF, HISTO, EVENT_CUBE, HARDWARE_HISTO, HARDWARE_DIFF, TIME_SURFACE }; + +static std::unordered_map const stringToEventPreprocessorTypeMap = { + {"diff", EventPreprocessorType::DIFF}, + {"diff3d", EventPreprocessorType::DIFF}, + {"histo", EventPreprocessorType::HISTO}, + {"histo3d", EventPreprocessorType::HISTO}, + {"event_cube", EventPreprocessorType::EVENT_CUBE}, + {"hardware_histo", EventPreprocessorType::HARDWARE_HISTO}, + {"hardware_diff", EventPreprocessorType::HARDWARE_DIFF}, + {"time_surface", EventPreprocessorType::TIME_SURFACE}}; + +static std::unordered_map const eventPreprocessorTypeToStringMap = { + {EventPreprocessorType::DIFF, "diff"}, + {EventPreprocessorType::HISTO, "histo"}, + {EventPreprocessorType::EVENT_CUBE, "event_cube"}, + {EventPreprocessorType::HARDWARE_HISTO, "hardware_histo"}, + {EventPreprocessorType::HARDWARE_DIFF, "hardware_diff"}, + {EventPreprocessorType::TIME_SURFACE, "time_surface"}}; + +} // namespace Metavision + +namespace std { +std::istream &operator>>(std::istream &in, Metavision::EventPreprocessorType &type); +std::ostream &operator<<(std::ostream &os, const Metavision::EventPreprocessorType &type); +} // namespace std + +#endif // METAVISION_SDK_CORE_EVENT_PREPROCESSOR_TYPE_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/hardware_diff_processor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/hardware_diff_processor.h new file mode 100644 index 000000000..7ff512d69 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/hardware_diff_processor.h @@ -0,0 +1,58 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_HARDWARE_DIFF_PROCESSOR_H +#define METAVISION_SDK_CORE_HARDWARE_DIFF_PROCESSOR_H + +#include "metavision/sdk/base/events/raw_event_frame_diff.h" +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" + +namespace Metavision { + +/// @brief Updates the data from a diff event frame in the form of a tensor with an input stream of events. +/// +/// This class implements the algorithm for producing diff event frames from a stream of events. This algorithm +/// computes, at each pixel, the sum of polarities of all processed events. +/// Generated event frames are stored using row-major convention. +/// @tparam InputIt The type of the input iterator for the range of events to process. +template +class HardwareDiffProcessor : public EventPreprocessor { +public: + using EventPreprocessor::process_events; + + /// @brief Constructor + /// @param width Width of the event stream + /// @param height Height of the event stream + /// @param min_val Lower representable value + /// @param max_val Higher representable value + /// @param allow_rollover If true, a roll-over will be realized when reaching minimal or maximal value. Else, + /// the pixel value will be saturated. + HardwareDiffProcessor(int width, int height, int8_t min_val, int8_t max_val, bool allow_rollover = true); + + /// @brief Updates the provided diff frame with the input events + /// @param[in] begin Iterator pointing to the beginning of the events buffer + /// @param[in] end Iterator pointing to the end of the events buffer + /// @param[out] diff Difference frame to update + void process_events(InputIt begin, InputIt end, RawEventFrameDiff &diff) const; + +private: + void compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, Tensor &tensor) const override; + + const bool allow_rollover_; + const int8_t min_val_, max_val_; + const int width_; +}; + +} // namespace Metavision + +#include "metavision/sdk/core/preprocessors/detail/hardware_diff_processor_impl.h" + +#endif // METAVISION_SDK_CORE_HARDWARE_DIFF_PROCESSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/hardware_histo_processor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/hardware_histo_processor.h new file mode 100644 index 000000000..29657155d --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/hardware_histo_processor.h @@ -0,0 +1,56 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_HARDWARE_HISTO_PROCESSOR_H +#define METAVISION_SDK_CORE_HARDWARE_HISTO_PROCESSOR_H + +#include "metavision/sdk/base/events/raw_event_frame_histo.h" +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" + +namespace Metavision { + +/// @brief Updates an input histogram with an input stream of events. +/// +/// This algorithm updates, separately at each pixel, the sum of positive and negative events from the event stream. +/// The histogram values will saturate if more events than the maximum representable integers are received +/// at a given pixel for a given polarity. This algorithm expects a pre-allocated tensor using row-major convention with +/// interleaved channels for each polarity. +/// @tparam InputIt The type of the input iterator for the range of events to process. +template +class HardwareHistoProcessor : public EventPreprocessor { +public: + using EventPreprocessor::process_events; + + /// @brief Constructor + /// @param width Width of the event stream + /// @param height Height of the event stream + /// @param neg_saturation Maximum value for the count of negative events in the histogram at each pixel + /// @param pos_saturation Maximum value for the count of positive events in the histogram at each pixel + HardwareHistoProcessor(int width, int height, uint8_t neg_saturation = 255, uint8_t pos_saturation = 255); + + /// @brief Updates the provided histogram with the input events + /// @param[in] begin Iterator pointing to the beginning of the events buffer + /// @param[in] end Iterator pointing to the end of the events buffer + /// @param[out] histo Histogram to update + void process_events(InputIt begin, InputIt end, RawEventFrameHisto &histo) const; + +private: + void compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, Tensor &tensor) const override; + + const uint8_t sum_max_neg_, sum_max_pos_; + const int width_; +}; + +} // namespace Metavision + +#include "metavision/sdk/core/preprocessors/detail/hardware_histo_processor_impl.h" + +#endif // METAVISION_SDK_CORE_HARDWARE_HISTO_PROCESSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/histo_processor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/histo_processor.h new file mode 100644 index 000000000..889919bb4 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/histo_processor.h @@ -0,0 +1,55 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_HISTO_PROCESSOR_H +#define METAVISION_SDK_CORE_HISTO_PROCESSOR_H + +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" + +namespace Metavision { + +/// @brief Class used to compute a histogram from a stream of EventCD +/// @tparam InputIt The type of the input iterator for the range of events to process +template +class HistoProcessor : public EventPreprocessor { +public: + HistoProcessor() = default; + + /// @brief Constructor + /// @param event_input_width Maximum width of input events + /// @param event_input_height Maximum height of input events + /// @param max_incr_per_pixel Maximum number of increments per pixel. This is used to normalize the contribution of + /// each event + /// @param clip_value_after_normalization Clipping value to apply after normalization (typically: 1.) + /// @param use_CHW Boolean to define frame dimension order, + /// True if the fields' frame order is (Channel, Height, Width) + /// @param width_scale Scale on the width previously applied to input events. This factor is considered to modulate + /// the contribution of each event at its coordinates. + /// @param height_scale Scale on the height previously applied to input events. This factor is considered to + /// modulate the contribution of each event at its coordinates. + HistoProcessor(int event_input_width, int event_input_height, float max_incr_per_pixel, + float clip_value_after_normalization, bool use_CHW = true, float width_scale = 1.f, + float height_scale = 1.f); + +private: + void compute(const timestamp cur_frame_start_ts, InputIt begin, InputIt end, Tensor &tensor) const override; + bool is_CHW(const Tensor &t) const; + + float increment_; + const float clip_value_after_normalization_; + const int width_, height_, channels_; +}; + +} // namespace Metavision + +#include + +#endif // METAVISION_SDK_CORE_HISTO_PROCESSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/json_parser.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/json_parser.h new file mode 100644 index 000000000..b38351bc6 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/json_parser.h @@ -0,0 +1,54 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_JSON_PARSER_H +#define METAVISION_SDK_CORE_JSON_PARSER_H + +#include +#include +#include +#include + +#include "metavision/sdk/base/utils/timestamp.h" +#include "metavision/sdk/core/preprocessors/event_preprocessor_type.h" + +namespace Metavision { + +/// @brief Opens a JSON file safely and provides a ptree to explore it +/// @param file_path JSON file to read +/// @return Tree describing the JSON structure +/// @throw runtime_error if the file does not exist or if the parsing is not successful +boost::property_tree::ptree get_tree_from_file(const std::filesystem::path &file_path); + +/// @brief Gets the value stored in a ptree referenced by its name +/// @tparam T Type of the data to retrieve +/// @param pt Root containing the information tree +/// @param key Name of the value to retrieve +/// @returns The value referenced by the input key +/// @throws std::runtime_error if the value was not found in the ptree +template +T get_element_from_ptree(const boost::property_tree::ptree &pt, const std::string &key); + +using PreprocessingParameters = std::variant, EventPreprocessorType>; + +/// @brief Reads the preprocessor parameters from the provided node +/// @param pt The node storing the different preprocessors configurations. It can either be a list or a single processor +/// parameters definition. +/// @param preprocess_maps List of the read preprocessor parameters +void parse_preprocessors_params(const boost::property_tree::ptree &pt, + std::vector> &preprocess_maps); + +} // namespace Metavision + +#include "metavision/sdk/core/preprocessors/detail/json_parser_impl.h" + +#endif // METAVISION_SDK_CORE_JSON_PARSER_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/tensor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/tensor.h new file mode 100644 index 000000000..8ff937a82 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/tensor.h @@ -0,0 +1,222 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_PREPROCESSORS_TENSOR_H +#define METAVISION_SDK_CORE_PREPROCESSORS_TENSOR_H + +#include +#include +#include +#include + +namespace Metavision { + +/// @brief Structure to store information on a tensor dimension +struct Dimension { + static constexpr int kDynamic = -1; + std::string name; + int dim; +}; + +/// @brief Structure to store information on a tensor dimensions +/// Dimension values should be >= 1 or equal to -1 to indicate a dynamic value +struct TensorShape { + /// @brief Default constructor + TensorShape(); + + /// @brief Constructor + /// @param dimensions Vector indicating the dimensions of the tensor + TensorShape(const std::vector &dimensions); + + /// @brief overrides "equal to" operator + bool operator==(const TensorShape &other) const; + + /// @brief overrides "not equal to" operator + bool operator!=(const TensorShape &other) const; + + /// @brief Provides the total number of values in the tensor + /// @returns The tensor size in terms of values + size_t get_nb_values() const; + + /// @brief Compares the dimensions and checks for mismatch. + /// It tests the equality of shape dimensions, except when one shape has a dynamic dimension. + /// In that case, the other can have any dimension. + /// @returns True if the two shape are equal, with dynamic dimensions allowed and considered as matching any + /// dimension + bool matches(const TensorShape &other) const; + + /// @brief Indicates whether the shape is composed of valid dimensions (strictly positive) + /// @returns False if any of the dimensions is <= 0, True otherwise + bool is_valid() const; + + std::vector dimensions; +}; + +/// @brief Retrieves the length of the required dimension in the provided shape +/// @param shape The tensor shape to look into +/// @param dim_name The name of the dimension to retrieve +/// @returns The value of the required dimension +/// @throws std::runtime_error if the requested dimension does not exist +int get_dim(const TensorShape &shape, const std::string &dim_name); + +/// @brief Sets the value of the required dimension in the provided shape +/// @param shape The tensor shape to update +/// @param dim_name The name of the dimension to update +/// @param value The new dimension value +/// @throws std::runtime_error if the requested dimension does not exist +void set_dim(TensorShape &shape, const std::string &dim_name, int value); + +/// @brief Sets all dynamic dimensions in the shape to 1 +/// @param shape The tensor shape to update +void set_dynamic_dimensions_to_one(TensorShape &shape); + +/// @brief Enumerate of the different base type that a tensor can contain +enum class BaseType : std::uint8_t { + BOOL, + UINT8, + UINT16, + UINT32, + UINT64, + INT8, + INT16, + INT32, + INT64, + FLOAT16, + FLOAT32, + FLOAT64 +}; + +/// @brief Provides a string representing the type +std::string to_string(const BaseType &type); + +/// @brief Retrieves the @ref Metavision::BaseType from a string +/// @details The string must have the same nomenclature as the BaseType name +BaseType from_string(const std::string name); + +/// @brief Provides the number of bytes on which data of this type is coded +/// @param type The type to give the byte size of +/// @returns The number of bytes coding a value of the input type +size_t byte_size(const BaseType &type); + +/// @brief Generic class to store information about an N-dimension tensor and its content +class Tensor { +public: + /// @brief Default constructor, no memory allocation + Tensor(); + + /// @brief Constructor with no input data + /// Memory is allocated with respect to provided shape ad data type. Tensor values are initialized to 0. + /// @param shape The shape of the tensor + /// @param type The type of data stored in the tensor + Tensor(const TensorShape &shape, const BaseType &type); + + /// @brief Main constructor for the tensor class + /// @param shape The shape of the tensor + /// @param type The type of data stored in the tensor + /// @param ptr Pointer to the tensor data (use reinterpret_cast if necessary). The ownership of the pointer is never + /// transferred. + /// @param copy Indicates whether or not to copy the tensor data. If false, the pointer will be used directly and + /// assumed to be valid. + Tensor(const TensorShape &shape, const BaseType &type, std::byte *ptr, bool copy = false); + + /// @brief Copy constructor + /// @param other Instance to copy from + Tensor(const Tensor &other); + + /// @brief Move constructor + /// @param other instance to move from + Tensor(Tensor &&other) noexcept; + + /// @brief Copy assignment operator + /// @param other Instance to copy from + Tensor &operator=(const Tensor &other); + + /// @brief Move assignment operator + /// @param other instance to move from + Tensor &operator=(Tensor &&other) noexcept; + + /// @brief Updates the tensor with new shape, type and data + /// @param shape New shape of the tensor + /// @param type New type of the tensor's data + /// @param ptr Pointer to the new tensor's data + /// @param copy If true, the data pointed by ptr will be copied internally. If the new required memory is + /// equal or lower than the previous one, no memory is reallocated. + void create(const TensorShape &shape, const BaseType &type, std::byte *ptr, bool copy = false); + + /// @brief Allocates memory to the tensor for a given shape and type of data + /// The tensor values are set to 0 and can be set later on thanks to the @ref Tensor::data() accessor. + /// @param shape New shape of the tensor + /// @param type New type of the tensor's data + void create(const TensorShape &shape, const BaseType &type); + + /// @brief Gets the shape of the tensor + /// @returns The tensor shape + TensorShape shape() const; + + /// @brief Gets the base type of the data stored in the tensor + /// @returns The base type of the tensor's data + BaseType type() const; + + /// @brief Returns the amount of bytes necessary to store the tensor data + /// @returns The tensor's data size in bytes + size_t byte_size() const; + + /// @brief Indicates whether the tensor contains any data + /// @returns True if the tensor is empty (contains 0 values) + bool empty(); + + /// @brief Gets the tensor data as const variable + /// @returns A const pointer to the tensor data + template + const T *data() const; + + /// @brief Gets the tensor data + /// @returns A pointer to the tensor data + template + T *data(); + + /// @brief Sets the tensors values to the provided one + /// @tparam Type of the input value + /// @param val The new value to set the tensor values to. + template + void set_to(T val); + + /// @brief Swaps the data between two Tensors + /// @param other The other tensor to swap data with + void swap(Tensor &other) { + std::swap(shape_, other.shape_); + std::swap(type_, other.type_); + std::swap(ptr_, other.ptr_); + std::swap(data_, other.data_); + } + +private: + template + void set_to_impl(T typed_val, size_t n); + + TensorShape shape_; // Shape of the tensor + BaseType type_; // Type of the base data stored in the tensor + std::byte *ptr_; // Pointer to the tensor data + std::vector data_; // Used to store the data when ownership is given in the constructor (copy = true) +}; + +} // namespace Metavision + +#include "metavision/sdk/core/preprocessors/detail/tensor_impl.h" + +namespace std { +std::istream &operator>>(std::istream &in, Metavision::TensorShape &tensor_shape); +std::istream &operator>>(std::istream &in, Metavision::BaseType &tensor_type); +std::ostream &operator<<(std::ostream &os, const Metavision::TensorShape &tensor_shape); +std::ostream &operator<<(std::ostream &os, const Metavision::BaseType &tensor_type); +} // namespace std + +#endif // METAVISION_SDK_CORE_PREPROCESSORS_TENSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/time_surface_processor.h b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/time_surface_processor.h new file mode 100644 index 000000000..ee4a2e75e --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/preprocessors/time_surface_processor.h @@ -0,0 +1,67 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_TIME_SURFACE_PROCESSOR_H +#define METAVISION_SDK_CORE_TIME_SURFACE_PROCESSOR_H + +#include +#include + +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" +#include "metavision/sdk/core/utils/mostrecent_timestamp_buffer.h" + +namespace Metavision { + +/// @brief Class that produces a @ref MostRecentTimestampBuffer (a.k.a. time surface) from events +/// @tparam InputIt The type of the input iterator for the range of events to process +/// @tparam CHANNELS Number of channels to use for producing the time surface. Only two values are possible for now: 1 +/// or 2. When a 1-channel time surface is used, events with different polarities are stored all together while they are +/// stored separately when using a 2-channels time surface. +template +class TimeSurfaceProcessor : public EventPreprocessor { +public: + static_assert(CHANNELS == 1 || CHANNELS == 2, "The timesurface producer is only compatible with 1 or 2 channels"); + + using EventPreprocessor::process_events; + + /// @brief Constructs a new time surface producer + /// @param width Sensor's width + /// @param height Sensor's height + TimeSurfaceProcessor(int width, int height); + + /// @brief Updates the provided time surface with the input events + /// @param[in] begin Iterator pointing to the beginning of the events buffer + /// @param[in] end Iterator pointing to the end of the events buffer + /// @param[out] time_surface Time surface to update + void process_events(InputIt begin, InputIt end, MostRecentTimestampBuffer &time_surface) const; + +private: + /// @brief Updates the input time surface with the provided events + /// @param ts starting timestamps of the current frame (not used) + /// @param it_begin Iterator pointing to the beginning of the events buffer + /// @param it_end Iterator pointing to the end of the events buffer + /// @param tensor The tensor to update with the provided events + void compute(const timestamp ts, InputIt it_begin, InputIt it_end, Tensor &tensor) const override; + + const int width_; +}; + +template +using TimeSurfaceProcessorMergePolarities = TimeSurfaceProcessor; + +template +using TimeSurfaceProcessorSplitPolarities = TimeSurfaceProcessor; + +} // namespace Metavision + +#include "metavision/sdk/core/preprocessors/detail/time_surface_processor_impl.h" + +#endif // METAVISION_SDK_CORE_TIME_SURFACE_PROCESSOR_H diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/utils/concurrent_queue.h b/sdk/modules/core/cpp/include/metavision/sdk/core/utils/concurrent_queue.h new file mode 100644 index 000000000..18fad2ef7 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/utils/concurrent_queue.h @@ -0,0 +1,101 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_CONCURRENT_QUEUE_H +#define METAVISION_SDK_CORE_CONCURRENT_QUEUE_H + +#include +#include +#include +#include + +namespace Metavision { + +/// @brief Class that implements a concurrent queue facility +/// +/// This class can be used to connect tasks together. For example, a task that produces some data will push it into the +/// queue while another one will pop the data from it to consume/process it. If the queue is empty, the consuming task, +/// when trying to pop data, will be blocked until new data is pushed in the queue by the producing task. +/// +/// In addition to that, this class maintains a state indicating whether the queue is opened or closed (i.e. enabled or +/// disabled). In the closed state, no data can be pushed (i.e. the call is ignored). This is useful to properly +/// handle the termination of tasks where some of them can be waiting for objects allocated from a memory pool to come +/// back before stopping. +/// +/// For example, let's imagine a task T1 that is allocating data from a pool and pushing it to a queue that another task +/// T2 is pulling. For the task T1 to terminate all the allocated data need to be back in the pool, otherwise the task +/// will wait and this can lead to deadlocks (e.g. if the task T2 is also waiting for new data to be produced). +/// A simple way to fix this problem is to: +/// - stop the task T2, +/// - clear and disable the queue (all the data will go back to the memory pool of the task T1) +/// - stop the task T1, if the task is executed in a separate thread then it may still try to push the data it has just +/// produced. In that case the call to push the data won't succeed because the queue would have been disabled before +/// and the data will directly go back to the memory pool. It will then be possible for the task T1 to terminate +/// properly without blocking. +/// @tparam T Type of the elements stored in the queue +template +class ConcurrentQueue { +public: + /// @brief Constructor + explicit ConcurrentQueue(size_t max_size = 0); + + /// @brief Destructor + ~ConcurrentQueue(); + + ConcurrentQueue(const ConcurrentQueue &) = delete; + ConcurrentQueue(ConcurrentQueue &&) = delete; + ConcurrentQueue &operator=(const ConcurrentQueue &) = delete; + ConcurrentQueue &operator=(ConcurrentQueue &&) = delete; + + /// @brief Retrieves the front element of the queue (i.e. the oldest one). + /// + /// If the queue is empty, this method waits until a new element is pushed to the queue, if the queue is closed in + /// the meantime, then this method returns false and the front element is not retrieved. + /// This method can be made non-blocking by setting the @p wait parameter to false. + /// @param wait If false, the method will return immediately if the queue is empty + /// @return The front element of the queue if this call succeeds + std::optional pop_front(bool wait = true); + + /// @brief Opens (i.e. enables) the queue. After the call it will be possible to push new elements + void open(); + + /// @brief Closes (i.e. disables) the queue. After the call it won't be possible to push new elements + void close(); + + /// @brief Pushes a new element to the queue. + /// + /// If the queue is full, this methods waits until a new element is popped out or until the queue is closed (in that + /// latter case the element is not pushed). + /// This method can be made non-blocking by setting the @p wait parameter to false. + /// @param[in] elt The new element to push + /// @param wait If false, the method will return immediately if the queue is full + /// @return True if the element was successfully added, false otherwise + bool emplace(T &&elt, bool wait = true); + + /// @brief Retrieves the size of the queue + /// @return The size of the queue + size_t size() const; + + /// @brief Clears the queue + void clear(); + +private: + const size_t max_size_; + std::queue q_; + mutable std::mutex mtx_; + std::condition_variable cond_; + bool enabled_{false}; +}; +} // namespace Metavision + +#include "metavision/sdk/core/utils/detail/concurrent_queue_impl.h" + +#endif // METAVISION_SDK_CORE_CONCURRENT_QUEUE_H \ No newline at end of file diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/utils/cv_video_recorder.h b/sdk/modules/core/cpp/include/metavision/sdk/core/utils/cv_video_recorder.h index c811f6e72..c99fc95ab 100644 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/utils/cv_video_recorder.h +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/utils/cv_video_recorder.h @@ -12,6 +12,7 @@ #ifndef METAVISION_SDK_CORE_CV_VIDEO_RECORDER_H #define METAVISION_SDK_CORE_CV_VIDEO_RECORDER_H +#include #include #include "metavision/sdk/core/utils/threaded_process.h" @@ -23,8 +24,8 @@ namespace Metavision { /// @brief A simple threaded video recorder using OpenCV routines class CvVideoRecorder { public: - CvVideoRecorder(const std::string &output_video_file, const int fourcc, const uint32_t fps, const cv::Size &size, - bool colored); + CvVideoRecorder(const std::filesystem::path &output_video_file, const int fourcc, const uint32_t fps, + const cv::Size &size, bool colored); /// @brief Records all remaining frames then destroys the object ~CvVideoRecorder(); diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/utils/detail/concurrent_queue_impl.h b/sdk/modules/core/cpp/include/metavision/sdk/core/utils/detail/concurrent_queue_impl.h new file mode 100644 index 000000000..4592b9a49 --- /dev/null +++ b/sdk/modules/core/cpp/include/metavision/sdk/core/utils/detail/concurrent_queue_impl.h @@ -0,0 +1,99 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. - All Rights Reserved * + * * + * Subject to Prophesee Metavision Licensing Terms and Conditions ("License T&C's"). * + * You may not use this file except in compliance with these License T&C's. * + * A copy of these License T&C's is located in the "licensing" folder accompanying this file. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_CORE_CONCURRENT_QUEUE_IMPL_H +#define METAVISION_SDK_CORE_CONCURRENT_QUEUE_IMPL_H + +#include "metavision/sdk/base/utils/log.h" + +namespace Metavision { + +template +ConcurrentQueue::ConcurrentQueue(size_t max_size) : max_size_(max_size) { + open(); +} + +template +ConcurrentQueue::~ConcurrentQueue() { + close(); +} + +template +std::optional ConcurrentQueue::pop_front(bool wait) { + std::unique_lock lock(mtx_); + if (q_.empty() && enabled_) { + if (!wait) { + return std::nullopt; + } + cond_.wait(lock, [&]() { return !q_.empty() || !enabled_; }); + } + + if (q_.empty() && !enabled_) { + return std::nullopt; + } + + auto front = std::move(q_.front()); + q_.pop(); + cond_.notify_one(); + + return std::move(front); +} + +template +void ConcurrentQueue::open() { + std::lock_guard lock(mtx_); + enabled_ = true; +} + +template +void ConcurrentQueue::close() { + std::lock_guard lock(mtx_); + + enabled_ = false; + + cond_.notify_all(); +} + +template +bool ConcurrentQueue::emplace(T &&elt, bool wait) { + std::unique_lock lock(mtx_); + + const bool queue_is_full = max_size_ != 0 && q_.size() == max_size_; + if (enabled_ && queue_is_full) { + if (!wait) { + return false; + } + cond_.wait(lock, [&]() { return q_.size() < max_size_ || !enabled_; }); + } + + if (!enabled_) { + return false; + } + + q_.emplace(std::forward(elt)); + cond_.notify_one(); + return true; +} + +template +size_t ConcurrentQueue::size() const { + std::lock_guard lock(mtx_); + return q_.size(); +} + +template +void ConcurrentQueue::clear() { + std::lock_guard lock(mtx_); + q_ = {}; + + cond_.notify_one(); +} + +} // namespace Metavision + +#endif // METAVISION_SDK_CORE_CONCURRENT_QUEUE_IMPL_H \ No newline at end of file diff --git a/sdk/modules/core/cpp/include/metavision/sdk/core/utils/simple_displayer.h b/sdk/modules/core/cpp/include/metavision/sdk/core/utils/simple_displayer.h deleted file mode 100644 index f8a5aeaec..000000000 --- a/sdk/modules/core/cpp/include/metavision/sdk/core/utils/simple_displayer.h +++ /dev/null @@ -1,77 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_SIMPLE_DISPLAYER_H -#define METAVISION_SDK_CORE_SIMPLE_DISPLAYER_H - -#include -#include -#include -#include -#include - -namespace Metavision { - -/// @brief Class representing a simple displayer -class [[deprecated("'SimpleDisplayer' class is deprecated since v4.1.0 and will be removed in future releases, " - "please use 'Window' or 'MTWindow' instead.")]] SimpleDisplayer { -public: - using OnKeyPressedCb = std::function; - - /// @brief Constructor - /// @param window_name Name of the window to display - /// @param fps Frames per second to display - SimpleDisplayer(const std::string window_name, int fps = 50); - - /// @brief Default destructor - ~SimpleDisplayer() = default; - - /// @brief Quits the display - void stop(); - - /// @brief Updates the current frame by swap - /// @param frame Frame to swap - void swap_frame(cv::Mat & frame); - - /// @brief Updates the current frame by copy - /// @param frame Frame to copy - void copy_frame(const cv::Mat &frame); - - /// @brief Sets the callback that is called when a key is pressed - /// @param on_key_pressed_cb Function to call - void set_on_key_pressed_cb(const OnKeyPressedCb &on_key_pressed_cb); - - /// @brief Runs the displayer. Should be called in the main thread - void run(); - -private: - // Start and stop mechanisms - volatile bool should_stop_ = false; ///< Bool to stop displayer generation from any thread - volatile bool started_ = false; ///< Bool to start the displayer - std::condition_variable started_cond_; ///< Conditional variable to notify starting - - // Images - cv::Mat front_img_; ///< Img to be displayed - cv::Mat middle_img_; ///< Intermediate buffer to avoid blocking the thread - std::mutex img_mutex_; ///< Mutex to swap the buffers - bool updated_ = false; ///< Check to update the front img - std::string window_name_; - - // Display - int wait_time_ms_; - - // Key pressed callback - OnKeyPressedCb on_key_pressed_cb_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_SIMPLE_DISPLAYER_H diff --git a/sdk/modules/core/cpp/lib/CMakeLists.txt b/sdk/modules/core/cpp/lib/CMakeLists.txt index af2aadcd4..c4fc94706 100644 --- a/sdk/modules/core/cpp/lib/CMakeLists.txt +++ b/sdk/modules/core/cpp/lib/CMakeLists.txt @@ -12,7 +12,7 @@ MetavisionSDK_add_module(core PUBLIC base EXTRA_REQUIRED_PACKAGE "OpenCV COMPONENTS core imgproc highgui videoio" - EXTRA_REQUIRED_PACKAGE "Boost COMPONENTS timer filesystem" + EXTRA_REQUIRED_PACKAGE "Boost COMPONENTS timer" EXTRA_REQUIRED_PACKAGE "Threads" ) @@ -29,7 +29,6 @@ target_link_libraries(metavision_sdk_core opencv_highgui opencv_videoio Boost::boost # Target for header-only dependencies - Boost::filesystem Boost::timer Threads::Threads ) \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/CMakeLists.txt b/sdk/modules/core/cpp/samples/CMakeLists.txt index 51bb5d824..daa9c151e 100644 --- a/sdk/modules/core/cpp/samples/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/CMakeLists.txt @@ -7,17 +7,13 @@ # 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. -option(COMPILE_PLAYER "Compile Metavision SDK player" ON) -if (COMPILE_PLAYER) - add_subdirectory(metavision_player) -endif () - if (NOT ANDROID) add_subdirectory(metavision_composed_viewer) add_subdirectory(metavision_csv_viewer) add_subdirectory(metavision_dummy_radar) add_subdirectory(metavision_event_frame_generation) add_subdirectory(metavision_event_frame_gpu_loading) + add_subdirectory(metavision_events_integration) add_subdirectory(metavision_file_to_video) add_subdirectory(metavision_filtering) add_subdirectory(metavision_sdk_get_started) diff --git a/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt index 10c256684..681d07f39 100644 --- a/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_composed_viewer) -set (common_libraries MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui Boost::program_options) +set (common_libraries MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) diff --git a/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt.install index f42c51480..74dd5efaf 100644 --- a/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_composed_viewer/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver ui REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream ui REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) set (sample metavision_composed_viewer) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui Boost::program_options) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) diff --git a/sdk/modules/core/cpp/samples/metavision_composed_viewer/metavision_composed_viewer.cpp b/sdk/modules/core/cpp/samples/metavision_composed_viewer/metavision_composed_viewer.cpp index 983cdde1f..22076348c 100644 --- a/sdk/modules/core/cpp/samples/metavision_composed_viewer/metavision_composed_viewer.cpp +++ b/sdk/modules/core/cpp/samples/metavision_composed_viewer/metavision_composed_viewer.cpp @@ -9,23 +9,22 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// This code sample demonstrates how to use Metavision Core SDK pipeline utility to filter events and show a frame -// combining unfiltered and filtered events. It also shows how to set a custom consuming callback on a -// @ref FrameCompositionStage instance, so that it can consume data from multiple stages. +// This code sample demonstrates how to use Metavision Core SDK to filter events and show a frame +// combining unfiltered and filtered events. +#include +#include #include #include #include -#include -#include -#include -#include +#include +#include +#include #include -#include +#include namespace po = boost::program_options; -/// [PIPELINE_COMPOSED_BEGIN] int main(int argc, char *argv[]) { std::string event_file_path; @@ -57,24 +56,21 @@ int main(int argc, char *argv[]) { return 0; } - // A pipeline for which all added stages will automatically be run in their own processing threads (if applicable) - Metavision::Pipeline p(true); - // Construct a camera from a file or a live stream Metavision::Camera cam; + std::atomic should_stop = false; if (!event_file_path.empty()) { cam = Metavision::Camera::from_file(event_file_path); } else { cam = Metavision::Camera::from_first_available(); } - const unsigned short width = cam.geometry().width(); - const unsigned short height = cam.geometry().height(); + const unsigned short width = cam.geometry().get_width(); + const unsigned short height = cam.geometry().get_height(); const Metavision::timestamp event_buffer_duration_ms = 2; const uint32_t accumulation_time_ms = 10; const int display_fps = 100; - /// Pipeline // // 0 (Camera) ---------------->---------------- 1 (Polarity Filter) // | | @@ -90,33 +86,63 @@ int main(int argc, char *argv[]) { // 5 (Display) // - // 0) Stage producing events from a camera - auto &cam_stage = p.add_stage(std::make_unique(std::move(cam), event_buffer_duration_ms)); - - // 1) Stage wrapping a polarity filter algorithm to keep positive events - auto &pol_filter_stage = p.add_algorithm_stage(std::make_unique(1), cam_stage); - - // 2,3) Stages generating frames from the previous stages - auto &left_frame_stage = - p.add_stage(std::make_unique(width, height, accumulation_time_ms), cam_stage); - auto &right_frame_stage = p.add_stage( - std::make_unique(width, height, accumulation_time_ms), pol_filter_stage); - - // 4) Stage generating a combined frame - auto &full_frame_stage = p.add_stage(std::make_unique(display_fps)); - full_frame_stage.add_previous_frame_stage(left_frame_stage, 0, 0, width, height); - full_frame_stage.add_previous_frame_stage(right_frame_stage, width + 10, 0, width, height); - - // 5) Stage displaying the combined frame - const auto full_width = full_frame_stage.frame_composer().get_total_width(); - const auto full_height = full_frame_stage.frame_composer().get_total_height(); - auto &disp_stage = p.add_stage( - std::make_unique("CD & noise filtered CD events", full_width, full_height), - full_frame_stage); - - // Run the pipeline and wait for its completion - p.run(); + Metavision::FrameComposer frame_composer; + + // Left frame, plain output from the sensor + const auto left_image_ref = frame_composer.add_new_subimage_parameters(0, 0, {width, height}, Metavision::FrameComposer::GrayToColorOptions()); + Metavision::PeriodicFrameGenerationAlgorithm left_frame_generator(width, height, accumulation_time_ms * 1000); + cam.cd().add_callback([&left_frame_generator](const Metavision::EventCD *begin, const Metavision::EventCD *end) { + left_frame_generator.process_events(begin, end); + }); + left_frame_generator.set_output_callback( + [&left_image_ref, &frame_composer](Metavision::timestamp t, cv::Mat &frame_data) { + if (!frame_data.empty()) { + frame_composer.update_subimage(left_image_ref, frame_data); + } + }); + + // Right frame, output only positive events + const auto right_image_ref = frame_composer.add_new_subimage_parameters(width + 10, 0, {width, height}, Metavision::FrameComposer::GrayToColorOptions()); + Metavision::PeriodicFrameGenerationAlgorithm right_frame_generator(width, height, accumulation_time_ms * 1000); + Metavision::PolarityFilterAlgorithm pol_filter(1); + cam.cd().add_callback([&pol_filter, &right_frame_generator](const Metavision::EventCD *begin, const Metavision::EventCD *end) { + std::vector pol_filter_out; + pol_filter.process_events(begin, end, std::back_inserter(pol_filter_out)); + right_frame_generator.process_events(pol_filter_out.begin(), pol_filter_out.end()); + }); + right_frame_generator.set_output_callback( + [&right_image_ref, &frame_composer](Metavision::timestamp t, cv::Mat &frame_data) { + if (!frame_data.empty()) { + frame_composer.update_subimage(right_image_ref, frame_data); + } + }); + + + Metavision::Window window("CD & noise filtered CD events", frame_composer.get_total_width(), frame_composer.get_total_height(), + Metavision::Window::RenderMode::BGR); + window.set_keyboard_callback([&should_stop](Metavision::UIKeyEvent key, int scancode, Metavision::UIAction action, int mods) { + if (action == Metavision::UIAction::RELEASE) { + switch (key) { + case Metavision::UIKeyEvent::KEY_ESCAPE: + case Metavision::UIKeyEvent::KEY_Q: + should_stop = true; + break; + } + } + }); + + const auto period_us = std::chrono::microseconds(1000000 / display_fps); + auto last_frame_update = std::chrono::high_resolution_clock::now() - period_us; + cam.start(); + while (!should_stop && cam.is_running()) { + if (std::chrono::high_resolution_clock::now() - last_frame_update >= period_us + && !frame_composer.get_full_image().empty()) { + window.show(frame_composer.get_full_image()); + last_frame_update = std::chrono::high_resolution_clock::now(); + } + Metavision::EventLoop::poll_and_dispatch(); + } + cam.stop(); return 0; } -/// [PIPELINE_COMPOSED_END] diff --git a/sdk/modules/core/cpp/samples/metavision_csv_viewer/metavision_csv_viewer.cpp b/sdk/modules/core/cpp/samples/metavision_csv_viewer/metavision_csv_viewer.cpp index 058e651ac..5c38c6cd8 100644 --- a/sdk/modules/core/cpp/samples/metavision_csv_viewer/metavision_csv_viewer.cpp +++ b/sdk/modules/core/cpp/samples/metavision_csv_viewer/metavision_csv_viewer.cpp @@ -9,21 +9,22 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// This code sample demonstrates how to use Metavision Core SDK pipeline utility to display events read from a CSV -// formatted event-based file, such as one produced by the sample metavision_file_to_csv. It also shows how to create a -// class deriving from BaseStage that produces data but consumes nothing. +// This code sample demonstrates how to use Metavision Core SDK to display events read from a CSV +// formatted event-based file, such as one produced by the sample metavision_file_to_csv. +#include #include #include #include #include +#include #include +#include "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/base/utils/object_pool.h" #include -#include -#include -#include +#include +#include #include -#include // A stage producing events from a CSV file with events written in the following format: // x1,y1,t1,p1 @@ -31,10 +32,14 @@ // ... // xn,yn,tn,pn -/// [PIPELINE_USAGE_DEFINE_STAGE_BEGIN] -class CSVReadingStage : public Metavision::BaseStage { +class CSVReader { public: - CSVReadingStage(const std::string &filename) : ifs_(filename) { + using EventBuffer = std::vector; + using EventBufferPool = Metavision::SharedObjectPool; + using EventBufferPtr = EventBufferPool::ptr_type; + using OutputCallback = std::function; + + CSVReader(const std::string &filename) : ifs_(filename) { if (!ifs_.is_open()) { MV_LOG_ERROR() << "Unable to open " << filename; throw std::runtime_error("Unable to open " + filename); @@ -46,28 +51,11 @@ class CSVReadingStage : public Metavision::BaseStage { cur_cd_buffer_ = cd_buffer_pool_.acquire(); cur_cd_buffer_->clear(); - - // this callback is called once the pipeline is started, so the stage knows it can start producing - set_starting_callback([this]() { - done_ = false; - reading_thread_ = std::thread([this] { read(); }); - }); - - // this callback is called once the pipeline is stopped : it can be initiated by a call - // to @ref Pipeline::cancel() and/or after all stages are done and all task queues have been cleared - set_stopping_callback([this]() { - done_ = true; - if (reading_thread_.joinable()) - reading_thread_.join(); - }); } - /// [PIPELINE_USAGE_READ_BEGIN] void read() { std::string line; while (!done_ && std::getline(ifs_, line)) { - // once here, we know that the stage has not been stopped yet, - // so we read a line and may produce a buffer std::istringstream iss(line); std::vector tokens; std::string token; @@ -78,8 +66,7 @@ class CSVReadingStage : public Metavision::BaseStage { MV_LOG_ERROR() << "Invalid line : <" << line << "> ignored"; } else { if (cur_cd_buffer_->size() > 5000) { - // this is how a stage produces data to be consumed by the next stages - produce(cur_cd_buffer_); + output_cb_(cur_cd_buffer_->data(), cur_cd_buffer_->data() + cur_cd_buffer_->size()); cur_cd_buffer_ = cd_buffer_pool_.acquire(); cur_cd_buffer_->clear(); } @@ -88,10 +75,15 @@ class CSVReadingStage : public Metavision::BaseStage { static_cast(std::stoi(tokens[2])), std::stoll(tokens[3])); } } - // notifies to the pipeline that this producer has no more data to produce - complete(); } - /// [PIPELINE_USAGE_READ_END] + + void stop() { + done_ = true; + } + + void set_output_callback(const OutputCallback &out_cb) { + output_cb_ = out_cb; + } std::optional get_width() const { return width_; @@ -136,17 +128,16 @@ class CSVReadingStage : public Metavision::BaseStage { } std::optional width_, height_; - std::atomic done_; + std::atomic done_ = false; std::thread reading_thread_; std::ifstream ifs_; EventBufferPool cd_buffer_pool_; EventBufferPtr cur_cd_buffer_; + OutputCallback output_cb_; }; -/// [PIPELINE_USAGE_DEFINE_STAGE_END] namespace po = boost::program_options; -/// [PIPELINE_USAGE_MAIN_BEGIN] int main(int argc, char *argv[]) { std::string in_csv_file_path; int width, height; @@ -186,29 +177,48 @@ int main(int argc, char *argv[]) { // 0 (Csv Reading) -->-- 1 (Frame Generation) -->-- 2 (Display) // - // A pipeline for which all added stages will automatically be run in their own processing threads (if applicable) - Metavision::Pipeline p(true); - - // 0) Stage producing events from a CSV file - auto csv_reader = std::make_unique(in_csv_file_path); - if (auto width_opt = csv_reader->get_width()) { + std::atomic should_stop = false; + CSVReader csv_reader(in_csv_file_path); + if (auto width_opt = csv_reader.get_width()) { width = *width_opt; } - if (auto height_opt = csv_reader->get_height()) { + if (auto height_opt = csv_reader.get_height()) { height = *height_opt; } - auto &csv_stage = p.add_stage(std::move(csv_reader)); - // 1) Stage generating a frame with events previously produced using accumulation time of 10ms - auto &frame_stage = p.add_stage(std::make_unique(width, height, 10), csv_stage); + Metavision::PeriodicFrameGenerationAlgorithm frame_generator(width, height, 10000); + csv_reader.set_output_callback([&frame_generator](const Metavision::EventCD *begin, const Metavision::EventCD *end) { + frame_generator.process_events(begin, end); + }); + + Metavision::Window window("CD events", width, height, Metavision::Window::RenderMode::BGR); + window.set_keyboard_callback([&should_stop, &csv_reader](Metavision::UIKeyEvent key, int scancode, Metavision::UIAction action, int mods) { + if (action == Metavision::UIAction::RELEASE) { + switch (key) { + case Metavision::UIKeyEvent::KEY_ESCAPE: + case Metavision::UIKeyEvent::KEY_Q: + should_stop = true; + csv_reader.stop(); + break; + } + } + }); + + frame_generator.set_output_callback( + [&window](Metavision::timestamp t, cv::Mat &frame_data) { + if (!frame_data.empty()) + window.show(frame_data); + }); - // 2) Stage displaying the generated frame - auto &disp_stage = - p.add_stage(std::make_unique("CD events", width, height), frame_stage); + auto t = std::thread([&csv_reader]() { csv_reader.read(); }); + while (!t.joinable()) { + } + + while (!should_stop) { + Metavision::EventLoop::poll_and_dispatch(); + } - // Run the pipeline and wait for its completion - p.run(); + t.join(); return 0; } -/// [PIPELINE_USAGE_MAIN_END] diff --git a/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt index ad7ed6a30..5fff99448 100644 --- a/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt @@ -10,7 +10,7 @@ set (sample metavision_dummy_radar) set (common_libraries MetavisionSDK::core - MetavisionSDK::driver + MetavisionSDK::stream MetavisionSDK::ui Boost::program_options opencv_core diff --git a/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt.install index cb7af9c78..9d832a939 100644 --- a/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_dummy_radar/CMakeLists.txt.install @@ -13,7 +13,7 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver ui REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream ui REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) find_package(OpenCV COMPONENTS core highgui imgproc REQUIRED) @@ -22,7 +22,7 @@ add_executable(${sample} ${sample}.cpp activity_monitoring.cpp radar_viewer.cpp) target_link_libraries(${sample} MetavisionSDK::base MetavisionSDK::core - MetavisionSDK::driver + MetavisionSDK::stream MetavisionSDK::ui Boost::program_options opencv_core diff --git a/sdk/modules/core/cpp/samples/metavision_dummy_radar/metavision_dummy_radar.cpp b/sdk/modules/core/cpp/samples/metavision_dummy_radar/metavision_dummy_radar.cpp index f3141d266..73aa5981b 100644 --- a/sdk/modules/core/cpp/samples/metavision_dummy_radar/metavision_dummy_radar.cpp +++ b/sdk/modules/core/cpp/samples/metavision_dummy_radar/metavision_dummy_radar.cpp @@ -26,7 +26,7 @@ // Basic utils for camera streaming #include -#include +#include #include #include @@ -110,8 +110,8 @@ int main(int argc, char *argv[]) { /// [ALGO INITIALIZATION] // Get camera resolution - const int camera_width = camera.geometry().width(); - const int camera_height = camera.geometry().height(); + const int camera_width = camera.geometry().get_width(); + const int camera_height = camera.geometry().get_height(); ActivityMonitor::Config config; config.n_bins = parameters.nbins; diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt index 5492a958c..669843887 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_event_frame_generation) -set (common_libraries MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui Boost::program_options) +set (common_libraries MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt.install index a258cf4d6..cd98fd399 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver ui REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream ui REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) set (sample metavision_event_frame_generation) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui Boost::program_options) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/metavision_event_frame_generation.cpp b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/metavision_event_frame_generation.cpp index b1c436c07..a3c59d7ca 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_generation/metavision_event_frame_generation.cpp +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_generation/metavision_event_frame_generation.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -121,13 +121,13 @@ int main(int argc, char *argv[]) { return 2; } - const int camera_width = camera.geometry().width(); - const int camera_height = camera.geometry().height(); + const int camera_width = camera.geometry().get_width(); + const int camera_height = camera.geometry().get_height(); const int npixels = camera_width * camera_height; // Instantiate generator for event frame diff and visualization functor - Metavision::EventFrameDiffGenerationAlgorithm diff_generator(camera_width, camera_height, diff_bit_size, - diff_allow_rollover, min_generation_period_us); + Metavision::EventFrameDiffGenerationAlgorithm diff_generator( + camera_width, camera_height, diff_bit_size, diff_allow_rollover, min_generation_period_us); Metavision::RawEventFrameDiff evframe_diff; const double diff_rescaler = 128. / (1 << (diff_bit_size - 1)); auto diff_to_viz_fct = [&](int8_t diff_val) { @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) { }; // Instantiate generator for event frame histo and visualization functor - Metavision::EventFrameHistoGenerationAlgorithm histo_generator( + Metavision::EventFrameHistoGenerationAlgorithm histo_generator( camera_width, camera_height, histo_bit_size_neg, histo_bit_size_pos, histo_packed, min_generation_period_us); Metavision::RawEventFrameHisto evframe_histo; const uint8_t histo_packed_neg_mask = (1 << histo_bit_size_neg) - 1; diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt index e702ec3c2..5e3fe61c9 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt @@ -22,12 +22,11 @@ if (CMAKE_CUDA_COMPILER) target_include_directories(${sample} PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) target_link_libraries(${sample} PRIVATE - Boost::filesystem Boost::program_options "${OpenCV_LIBS}" MetavisionSDK::base MetavisionSDK::core - MetavisionSDK::driver + MetavisionSDK::stream cuda_event_frame_convert ) endif(CMAKE_CUDA_COMPILER) diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt.install index 5fa923c86..734562c50 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/CMakeLists.txt.install @@ -13,8 +13,8 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS base core driver REQUIRED) -find_package(Boost COMPONENTS program_options filesystem REQUIRED) +find_package(MetavisionSDK COMPONENTS base core stream REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED) find_package(OpenCV COMPONENTS core imgproc imgcodecs REQUIRED) enable_language(CUDA) @@ -35,11 +35,10 @@ set_property(TARGET ${sample} PROPERTY CUDA_RESOLVE_DEVICE_SYMBOLS ON) target_include_directories(${sample} PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) target_link_libraries(${sample} - Boost::filesystem Boost::program_options "${OpenCV_LIBS}" MetavisionSDK::base MetavisionSDK::core - MetavisionSDK::driver + MetavisionSDK::stream cuda_event_frame_convert ) diff --git a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp index 501aefd36..2fa47b9d8 100644 --- a/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp +++ b/sdk/modules/core/cpp/samples/metavision_event_frame_gpu_loading/metavision_event_frame_gpu_loading.cpp @@ -12,18 +12,18 @@ // This code sample demonstrates how to preprocess raw event frame on a GPU using CUDA. #include +#include #include #include #include #include -#include #include #include #include #include -#include +#include #include #include "convert_event_frame.h" @@ -103,13 +103,13 @@ int main(int argc, char *argv[]) { return 1; } - if (!boost::filesystem::exists(output_dir)) { - if (!boost::filesystem::create_directories(output_dir)) { + if (!std::filesystem::exists(output_dir)) { + if (!std::filesystem::create_directories(output_dir)) { MV_LOG_ERROR() << "Failed to create output directory " << output_dir; return 1; } } - if (!boost::filesystem::is_directory(output_dir)) { + if (!std::filesystem::is_directory(output_dir)) { MV_LOG_ERROR() << "Output path '" << output_dir << "' is not a directory"; return 1; } @@ -133,7 +133,7 @@ int main(int argc, char *argv[]) { cv::Mat frame; frame = cv::Mat(cfg.height, cfg.width, CV_32FC3, res); cv::imwrite( - (boost::filesystem::path(output_dir) / ("histo_frame" + std::to_string(frame_idx) + ".jpg")).string(), + (std::filesystem::path(output_dir) / ("histo_frame" + std::to_string(frame_idx) + ".jpg")).string(), frame); cudaFree(res); @@ -153,7 +153,7 @@ int main(int argc, char *argv[]) { frame = cv::Mat(cfg.height, cfg.width, CV_32FC3, res); cv::imwrite( - (boost::filesystem::path(output_dir) / ("diff_frame" + std::to_string(frame_idx) + ".jpg")).string(), + (std::filesystem::path(output_dir) / ("diff_frame" + std::to_string(frame_idx) + ".jpg")).string(), frame); ++frame_idx; }); diff --git a/sdk/modules/core/cpp/samples/metavision_events_integration/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_events_integration/CMakeLists.txt new file mode 100644 index 000000000..2103e09ea --- /dev/null +++ b/sdk/modules/core/cpp/samples/metavision_events_integration/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) Prophesee S.A. +# +# 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 (sample metavision_events_integration) +set (common_libraries MetavisionSDK::stream MetavisionSDK::core MetavisionSDK::ui Boost::program_options) + +add_executable(${sample} ${sample}.cpp) +target_link_libraries(${sample} PRIVATE ${common_libraries}) + +install(FILES ${sample}.cpp + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} + COMPONENT metavision-sdk-core-samples +) + +install(FILES CMakeLists.txt.install + RENAME CMakeLists.txt + DESTINATION share/metavision/sdk/core/cpp_samples/${sample} + COMPONENT metavision-sdk-core-samples +) diff --git a/sdk/modules/core/cpp/samples/metavision_events_integration/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_events_integration/CMakeLists.txt.install new file mode 100644 index 000000000..e60aaf7f5 --- /dev/null +++ b/sdk/modules/core/cpp/samples/metavision_events_integration/CMakeLists.txt.install @@ -0,0 +1,21 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +project(metavision_events_integration) + +cmake_minimum_required(VERSION 3.5) + +set(CMAKE_CXX_STANDARD 17) + +find_package(MetavisionSDK COMPONENTS core stream ui REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED) + +set (sample metavision_events_integration) +add_executable(${sample} ${sample}.cpp) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) diff --git a/sdk/modules/core/cpp/samples/metavision_events_integration/metavision_events_integration.cpp b/sdk/modules/core/cpp/samples/metavision_events_integration/metavision_events_integration.cpp new file mode 100644 index 000000000..e8b7fc31f --- /dev/null +++ b/sdk/modules/core/cpp/samples/metavision_events_integration/metavision_events_integration.cpp @@ -0,0 +1,193 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +// Example of using Metavision SDK Core API for integrating events into a grayscale-like image + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace po = boost::program_options; + +int main(int argc, char *argv[]) { + std::string serial; + std::string cam_config_path; + std::string in_file_path; + Metavision::timestamp period_us; + uint32_t decay_time; + float contrast_on, contrast_off, diffusion_weight; + int integration_blur_radius, tonemapping_max_ev_count; + std::string output_video_path; + + const std::string short_program_desc( + "Example of using Metavision SDK Core API for integrating events into a grayscale-like image.\n"); + po::options_description options_desc("Options"); + + // clang-format off + options_desc.add_options() + ("help,h", "Produce help message.") + ("serial,s", po::value(&serial)->default_value(""),"Serial ID of the camera. If empty, will open the first camera found. This flag is incompatible with flag '--input-file'.") + ("input-file,i", po::value(&in_file_path)->default_value(""), "Path to input file. If not specified, the camera live stream is used.") + ("input-camera-config,j", po::value(&cam_config_path)->default_value(""), "Path to a JSON file containing camera config settings to restore a camera state. Only works for live cameras.") + ("period,p", po::value(&period_us)->default_value(30'000), "Period for the generation of the integrated event frames, in us.") + ("decay-time,d", po::value(&decay_time)->default_value(100'000), "Decay time after which integrated frame tends back to neutral gray. This needs to be adapted to the scene dynamics.") + ("blur-radius,r", po::value(&diffusion_weight)->default_value(0), "Weight used to diffuse neighboring intensities into each other to slowly smooth the image. Disabled if zero, cannot exceed 0.25f.") + ("diffusion-weight,w", po::value(&integration_blur_radius)->default_value(1), "Gaussian blur radius to be used to smooth integrated intensities.") + ("contrast-on,c", po::value(&contrast_on)->default_value(1.2f), "Contrast associated to ON events.") + ("contrast-off", po::value(&contrast_off)->default_value(-1), "Contrast associated to OFF events. If negative, the inverse of contrast-on is used.") + ("tonemapping-count", po::value(&tonemapping_max_ev_count)->default_value(5), "Maximum event count to tonemap in 8-bit grayscale frame. This needs to be adapted to the scene dynamic range & sensor sensitivity.") + ("output-video,o", po::value(&output_video_path)->default_value(""), "Save display window in a .avi format") + ; + // clang-format on + + po::variables_map vm; + try { + po::store(po::command_line_parser(argc, argv).options(options_desc).run(), vm); + po::notify(vm); + } catch (po::error &e) { + MV_LOG_ERROR() << short_program_desc; + MV_LOG_ERROR() << options_desc; + MV_LOG_ERROR() << "Parsing error:" << e.what(); + return 1; + } + + if (vm.count("help")) { + MV_LOG_INFO() << short_program_desc; + MV_LOG_INFO() << options_desc; + return 0; + } + + if (contrast_off <= 0) { + contrast_off = 1 / contrast_on; + } + + // Open the input event stream + Metavision::Camera camera; + if (!in_file_path.empty()) { + if (!serial.empty()) { + MV_LOG_ERROR() << "Options --serial and --input-file are not compatible."; + return 1; + } + + try { + camera = + Metavision::Camera::from_file(in_file_path, Metavision::FileConfigHints().real_time_playback(true)); + } catch (Metavision::CameraException &e) { + MV_LOG_ERROR() << e.what(); + return 2; + } + } else { // otherwise, set the input source to a camera + try { + if (!serial.empty()) { + camera = Metavision::Camera::from_serial(serial); + } else { + camera = Metavision::Camera::from_first_available(); + } + if (!cam_config_path.empty()) { + camera.load(cam_config_path); + } + } catch (Metavision::CameraException &e) { + MV_LOG_ERROR() << e.what(); + return 3; + } + } + + const int camera_width = camera.geometry().get_width(); + const int camera_height = camera.geometry().get_height(); + + // Instantiate event integration algorithm + bool show_cmap = false; + Metavision::EventsIntegrationAlgorithm ev_integrator(camera_width, camera_height, decay_time, contrast_on, + contrast_off, tonemapping_max_ev_count, + integration_blur_radius, diffusion_weight); + Metavision::ContrastMapGenerationAlgorithm cmap_generator(camera_width, camera_height, contrast_on, contrast_off); + const float tonemapping_factor = 1 / static_cast(std::pow(contrast_on, tonemapping_max_ev_count - 1) - 1); + Metavision::OnDemandFrameGenerationAlgorithm frame_generator(camera_width, camera_height, decay_time / 3, + Metavision::ColorPalette::Gray); + + // Instantiate window to render generated frames + Metavision::Window window("Metavision Event Integration", camera_width, 2 * camera_height, + Metavision::BaseWindow::RenderMode::GRAY); + window.set_keyboard_callback( + [&window, &show_cmap](Metavision::UIKeyEvent key, int, Metavision::UIAction action, int) { + if (action == Metavision::UIAction::RELEASE && + (key == Metavision::UIKeyEvent::KEY_ESCAPE || key == Metavision::UIKeyEvent::KEY_Q)) { + window.set_close_flag(); + } else if (action == Metavision::UIAction::RELEASE && key == Metavision::UIKeyEvent::KEY_T) { + show_cmap = !show_cmap; + } + }); + // Instantiate video writer + std::unique_ptr video_writer; + if (!output_video_path.empty()) { + const int fourcc = cv::VideoWriter::fourcc('M', 'J', 'P', 'G'); + video_writer = std::make_unique(output_video_path, fourcc, 1e6 / period_us, + cv::Size(camera_width, 2 * camera_height), true); + if (!video_writer->isOpened()) { + MV_LOG_ERROR() << "Failed to open video writer!"; + return 1; + } + } + + // Instantiate event reslicer and define its slicing & event callbacks + Metavision::EventBufferReslicerAlgorithm reslicer( + nullptr, Metavision::EventBufferReslicerAlgorithm::Condition::make_n_us(period_us)); + + cv::Mat_ contrast_map; + cv::Mat visu_frame(2 * camera_height, camera_width, CV_8U), visu_frame_color; + cv::Mat visu_events = visu_frame(cv::Rect(0, 0, camera_width, camera_height)); + cv::Mat visu_integrated = visu_frame(cv::Rect(0, camera_height, camera_width, camera_height)); + reslicer.set_on_new_slice_callback([&](Metavision::EventBufferReslicerAlgorithm::ConditionStatus, + Metavision::timestamp ts, std::size_t) { + frame_generator.generate(ts, visu_events); + if (show_cmap) { + cmap_generator.generate(contrast_map); + contrast_map.convertTo(visu_integrated, CV_8U, 128 * tonemapping_factor, 128 * (1 - tonemapping_factor)); + } else { + ev_integrator.generate(visu_integrated); + } + + window.show(visu_frame); + if (video_writer) { + cv::putText(visu_events, "CD Events", cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), 4); + cv::putText(visu_integrated, "Integrated", cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255), + 4); + cv::cvtColor(visu_frame, visu_frame_color, cv::COLOR_GRAY2BGR); + video_writer->write(visu_frame_color); + } + }); + + auto reslicer_ev_callback = [&](const Metavision::EventCD *ev_begin, const Metavision::EventCD *ev_end) { + frame_generator.process_events(ev_begin, ev_end); + ev_integrator.process_events(ev_begin, ev_end); + cmap_generator.process_events(ev_begin, ev_end); + }; + + // Register the processing callback when receiving new events + camera.cd().add_callback([&](const Metavision::EventCD *ev_begin, const Metavision::EventCD *ev_end) { + reslicer.process_events(ev_begin, ev_end, reslicer_ev_callback); + }); + + // Start the event stream + camera.start(); + while (camera.is_running() && !window.should_close()) { + static constexpr std::int64_t kSleepPeriodMs = 20; + Metavision::EventLoop::poll_and_dispatch(kSleepPeriodMs); + } + camera.stop(); +} diff --git a/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt index f807c34b2..bc7faa3c7 100644 --- a/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt @@ -10,9 +10,9 @@ add_executable(metavision_file_to_video metavision_file_to_video.cpp) target_link_libraries(metavision_file_to_video PRIVATE - MetavisionSDK::driver + MetavisionSDK::stream MetavisionSDK::core - Boost::program_options Boost::filesystem Threads::Threads + Boost::program_options Threads::Threads opencv_core opencv_highgui opencv_videoio ) diff --git a/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt.install index 58870fe3d..b5b061619 100644 --- a/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_file_to_video/CMakeLists.txt.install @@ -13,16 +13,16 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS driver core REQUIRED) -find_package(Boost COMPONENTS program_options filesystem REQUIRED) +find_package(MetavisionSDK COMPONENTS stream core REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED) find_package(OpenCV COMPONENTS core highgui videoio REQUIRED) find_package(Threads REQUIRED) add_executable(metavision_file_to_video metavision_file_to_video.cpp) target_link_libraries(metavision_file_to_video PRIVATE - MetavisionSDK::driver + MetavisionSDK::stream MetavisionSDK::core - Boost::program_options Boost::filesystem Threads::Threads + Boost::program_options Threads::Threads opencv_core opencv_highgui opencv_videoio ) \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/metavision_file_to_video/metavision_file_to_video.cpp b/sdk/modules/core/cpp/samples/metavision_file_to_video/metavision_file_to_video.cpp index 556a3b87c..f324782ad 100644 --- a/sdk/modules/core/cpp/samples/metavision_file_to_video/metavision_file_to_video.cpp +++ b/sdk/modules/core/cpp/samples/metavision_file_to_video/metavision_file_to_video.cpp @@ -9,17 +9,16 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// Example of using Metavision SDK Driver and Core API for generating a video from a RAW or HDF5 file. +// Example of using Metavision SDK Stream and Core API for generating a video from a RAW or HDF5 file. #include #include #include -#include #include #include #include #include -#include +#include #include #include #include @@ -28,10 +27,6 @@ namespace po = boost::program_options; -void remove_file(const std::string &filepath) { - boost::filesystem::remove(boost::filesystem::path(filepath)); -} - int main(int argc, char *argv[]) { std::string in_event_file_path; std::string out_video_file_path; @@ -109,12 +104,12 @@ int main(int argc, char *argv[]) { Metavision::CvVideoRecorder recorder( out_video_file_path, enable_image_sequence ? 0 : cv::VideoWriter::fourcc(fourcc[0], fourcc[1], fourcc[2], fourcc[3]), - enable_image_sequence ? 0 : fps, cv::Size(geometry.width(), geometry.height()), true); + enable_image_sequence ? 0 : fps, cv::Size(geometry.get_width(), geometry.get_height()), true); recorder.start(); // Set up frame generator for CD events - Metavision::PeriodicFrameGenerationAlgorithm frame_generation(geometry.width(), geometry.height()); + Metavision::PeriodicFrameGenerationAlgorithm frame_generation(geometry.get_width(), geometry.get_height()); bool has_cd = false; try { auto &cd = camera.cd(); @@ -134,7 +129,7 @@ int main(int argc, char *argv[]) { // Set up frame converter for Histo3D frames try { auto &histo_module = camera.frame_histo(); - Metavision::RawEventFrameConverter frame_converter(geometry.height(), geometry.width(), 2); + Metavision::RawEventFrameConverter frame_converter(geometry.get_height(), geometry.get_width(), 2); histo_module.add_callback([&recorder, frame_converter](const Metavision::RawEventFrameHisto &histo) { auto histo_cfg = histo.get_config(); auto converted_histo = frame_converter.convert(histo); @@ -156,7 +151,7 @@ int main(int argc, char *argv[]) { // Set up frame converter for Diff3D frames try { auto &diff_module = camera.frame_diff(); - Metavision::RawEventFrameConverter frame_converter(geometry.height(), geometry.width(), 1); + Metavision::RawEventFrameConverter frame_converter(geometry.get_height(), geometry.get_width(), 1); diff_module.add_callback([&recorder, frame_converter](const Metavision::RawEventFrameDiff &diff) { auto diff_cfg = diff.get_config(); auto converted_diff = frame_converter.convert(diff); diff --git a/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt index e2644c58f..cd32546a2 100644 --- a/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_filtering) -set (common_libraries MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui Boost::program_options) +set (common_libraries MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) diff --git a/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt.install index 5c605f4d3..c6d2b3ab0 100644 --- a/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_filtering/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver ui REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream ui REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) set (sample metavision_filtering) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui Boost::program_options) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) diff --git a/sdk/modules/core/cpp/samples/metavision_filtering/metavision_filtering.cpp b/sdk/modules/core/cpp/samples/metavision_filtering/metavision_filtering.cpp index 35ea60f27..0611b1427 100644 --- a/sdk/modules/core/cpp/samples/metavision_filtering/metavision_filtering.cpp +++ b/sdk/modules/core/cpp/samples/metavision_filtering/metavision_filtering.cpp @@ -9,28 +9,29 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// This code sample demonstrates how to use Metavision Core SDK pipeline utility to display and filter events. -// It shows how to capture the keys pressed in a display window so as to modify the behavior of the stages while the -// pipeline is running. +// This code sample demonstrates how to use Metavision Core SDK utility to display and filter events. +// It shows how to capture the keys pressed in a display window so as to modify the behavior of the filters while the +// camera is running. +#include #include +#include #include -#include -#include +#include #include #include -#include -#include -#include +#include +#include +#include "metavision/sdk/ui/utils/event_loop.h" +#include "metavision/sdk/ui/utils/window.h" namespace po = boost::program_options; -/// [PIPELINE_FILTERING_BEGIN] int main(int argc, char *argv[]) { std::string event_file_path; - const std::string short_program_desc("Code sample showing how the pipeline utility can be used to " - "create a simple application to filter and display events.\n"); + const std::string short_program_desc("Code sample showing how to create a simple application to filter" + " and display events.\n"); const std::string long_program_desc(short_program_desc + "Available keyboard options:\n" " - r - toggle the ROI filter algorithm\n" @@ -66,69 +67,95 @@ int main(int argc, char *argv[]) { MV_LOG_INFO() << long_program_desc; - // A pipeline for which all added stages will automatically be run in their own processing threads (if applicable) - Metavision::Pipeline p(true); - // Construct a camera from a recording or a live stream Metavision::Camera cam; + std::atomic should_stop = false; if (!event_file_path.empty()) { cam = Metavision::Camera::from_file(event_file_path); } else { cam = Metavision::Camera::from_first_available(); } - const unsigned short width = cam.geometry().width(); - const unsigned short height = cam.geometry().height(); - - /// Pipeline - // - // 0 (Camera) -->-- 1 (ROI) -->-- 2 (Polarity) -->-- 3 (Frame Generation) -->-- 4 (Display) - // + const unsigned short width = cam.geometry().get_width(); + const unsigned short height = cam.geometry().get_height(); - // 0) Stage producing events from a camera - auto &cam_stage = p.add_stage(std::make_unique(std::move(cam))); + Metavision::RoiFilterAlgorithm roi_filter(150, 150, width - 150, height - 150, false); + std::atomic roi_filter_enabled = false; + Metavision::PolarityFilterAlgorithm pol_filter(0); + std::atomic pol_filter_enabled = false; - // 1) Stage wrapping an ROI filter algorithm - auto &roi_stage = p.add_algorithm_stage( - std::make_unique(150, 150, width - 150, height - 150, false), cam_stage, false); + // Generating a frame from filtered events using accumulation time of 30ms + Metavision::PeriodicFrameGenerationAlgorithm frame_generator(width, height, 30000); - // 2) Stage wrapping a polarity filter algorithm - auto &pol_stage = p.add_algorithm_stage(std::make_unique(0), roi_stage, false); - - // 3) Stage generating a frame from filtered events using accumulation time of 30ms - auto &frame_stage = p.add_stage(std::make_unique(width, height, 30), pol_stage); + try { + cam.cd().add_callback( + [&roi_filter_enabled, &roi_filter, + &pol_filter_enabled, &pol_filter, + &frame_generator](const Metavision::EventCD *begin, const Metavision::EventCD *end) { + std::vector roi_filter_out; + if (roi_filter_enabled) { + roi_filter.process_events(begin, end, std::back_inserter(roi_filter_out)); + begin = roi_filter_out.data(); + end = begin + roi_filter_out.size(); + } + + std::vector pol_filter_out; + if (pol_filter_enabled) { + pol_filter.process_events(begin, end, std::back_inserter(pol_filter_out)); + begin = pol_filter_out.data(); + end = begin + pol_filter_out.size(); + } + + frame_generator.process_events(begin, end); + }); + } catch (const Metavision::CameraException &e) { + MV_LOG_ERROR() << "Unexpected error: " << e.what(); + } - // 4) Stage displaying the frame - auto &disp_stage = - p.add_stage(std::make_unique("CD events", width, height), frame_stage); + Metavision::Window window("CD events", width, height, Metavision::Window::RenderMode::BGR); - disp_stage.set_key_callback([&](Metavision::UIKeyEvent key, int scancode, Metavision::UIAction action, int mods) { + window.set_keyboard_callback( + [&roi_filter_enabled, &pol_filter_enabled, &pol_filter, &cam, &should_stop](Metavision::UIKeyEvent key, + int scancode, + Metavision::UIAction action, int mods) { if (action == Metavision::UIAction::RELEASE) { switch (key) { case Metavision::UIKeyEvent::KEY_A: // show all events - pol_stage.set_enabled(false); + pol_filter_enabled = false; break; case Metavision::UIKeyEvent::KEY_N: // show only negative events - pol_stage.set_enabled(true); - pol_stage.algo().set_polarity(0); + pol_filter_enabled = true; + pol_filter.set_polarity(0); break; case Metavision::UIKeyEvent::KEY_P: // show only positive events - pol_stage.set_enabled(true); - pol_stage.algo().set_polarity(1); + pol_filter_enabled = true; + pol_filter.set_polarity(1); break; case Metavision::UIKeyEvent::KEY_R: // toggle ROI filter - roi_stage.set_enabled(!roi_stage.is_enabled()); + roi_filter_enabled = !roi_filter_enabled; + break; + case Metavision::UIKeyEvent::KEY_ESCAPE: + case Metavision::UIKeyEvent::KEY_Q: + should_stop = true; break; } } }); - // Run the pipeline - p.run(); + frame_generator.set_output_callback( + [&window](Metavision::timestamp t, cv::Mat &frame_data) { + if (!frame_data.empty()) + window.show(frame_data); + }); + + cam.start(); + while (!should_stop && cam.is_running()) { + Metavision::EventLoop::poll_and_dispatch(); + } + cam.stop(); return 0; } -/// [PIPELINE_FILTERING_END] diff --git a/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt deleted file mode 100644 index e0d6b0df4..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) Prophesee S.A. -# -# 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. - -add_executable(metavision_player - src/main.cpp - src/viewer.cpp - src/view.cpp - src/analysis_view.cpp - src/camera_view.cpp -) -target_link_libraries(metavision_player - PRIVATE - Boost::filesystem - Boost::program_options - ${OpenCV_LIBS} - MetavisionSDK::core - MetavisionSDK::driver -) -target_include_directories(metavision_player PRIVATE inc) - -install( - TARGETS metavision_player - RUNTIME DESTINATION bin - COMPONENT metavision-sdk-core-bin -) - -# Install source code -install(FILES CMakeLists.txt.install - RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/core/cpp_samples/metavision_player - COMPONENT metavision-sdk-core-samples -) -install(DIRECTORY inc src - DESTINATION share/metavision/sdk/core/cpp_samples/metavision_player - COMPONENT metavision-sdk-core-samples -) - -if (BUILD_TESTING) - add_subdirectory(test) -endif () \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt.install deleted file mode 100644 index ab46cc737..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/CMakeLists.txt.install +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (c) Prophesee S.A. -# -# 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. - -project(metavision_player) - -cmake_minimum_required(VERSION 3.5) - -set(CMAKE_CXX_STANDARD 17) - -find_package(MetavisionSDK COMPONENTS driver core REQUIRED) -find_package(Boost COMPONENTS program_options filesystem REQUIRED) -find_package(OpenCV COMPONENTS core highgui imgproc imgcodecs REQUIRED) - -add_executable(metavision_player - src/main.cpp - src/viewer.cpp - src/view.cpp - src/analysis_view.cpp - src/camera_view.cpp -) -target_link_libraries(metavision_player - PRIVATE - Boost::filesystem - Boost::program_options - ${OpenCV_LIBS} - MetavisionSDK::core - MetavisionSDK::driver -) -target_include_directories(metavision_player PRIVATE inc) - diff --git a/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_utils.h b/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_utils.h deleted file mode 100644 index aaaabf1c3..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_utils.h +++ /dev/null @@ -1,120 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_PLAYER_ANALYSIS_UTILS_H -#define METAVISION_PLAYER_ANALYSIS_UTILS_H - -#include - -#include "utils.h" -#include "analysis_view.h" - -inline Metavision::timestamp compute_sequence_start_time(Metavision::timestamp first_time_us, - Metavision::timestamp last_time_us, int frame_period_us, - int sequence_start_ratio) { - const Metavision::timestamp min_start_time_us = first_time_us + frame_period_us; - Metavision::timestamp max_start_time_us = min_start_time_us; - while (max_start_time_us <= last_time_us) { - max_start_time_us += frame_period_us; - } - const Metavision::timestamp start_time_us = static_cast( - sequence_start_ratio * (max_start_time_us - min_start_time_us) / 100. + min_start_time_us + 0.5); - return clip(start_time_us, min_start_time_us, max_start_time_us); -} - -inline Metavision::timestamp compute_sequence_duration(Metavision::timestamp first_time_us, - Metavision::timestamp last_time_us, int frame_period_us, - int sequence_start_ratio, int sequence_duration_ratio) { - const Metavision::timestamp start_time_us = - compute_sequence_start_time(first_time_us, last_time_us, frame_period_us, sequence_start_ratio); - Metavision::timestamp time_us = start_time_us + frame_period_us; - Metavision::timestamp max_duration_us = frame_period_us; - while (time_us <= last_time_us) { - time_us += frame_period_us; - max_duration_us += frame_period_us; - } - const Metavision::timestamp min_duration_us = frame_period_us; - Metavision::timestamp duration_us = static_cast( - sequence_duration_ratio * (max_duration_us - min_duration_us) / 100. + 0.5 + min_duration_us); - duration_us = - static_cast((duration_us + frame_period_us - 1.0) / frame_period_us) * frame_period_us; - return clip(duration_us, min_duration_us, max_duration_us); -} - -inline int compute_current_time(Metavision::timestamp sequence_start_time_us, int frame_id, int frame_period_us) { - return sequence_start_time_us + frame_id * frame_period_us; -} - -struct AnalysisData { - int fps, min_fps, max_fps; - int min_sequence_start_ratio, max_sequence_start_ratio; - int min_sequence_duration_ratio, max_sequence_duration_ratio; - int accumulation_ratio, min_accumulation_ratio, max_accumulation_ratio; - int frame_id, min_frame_id, max_frame_id; -}; - -inline AnalysisData compute_analysis_data(Metavision::timestamp first_time_us, Metavision::timestamp last_time_us, - int fps, int accumulation_ratio, int sequence_start_ratio, - int sequence_duration_ratio, int current_time_us) { - AnalysisData data; - - int frame_period_us = compute_frame_period(fps); - const Metavision::timestamp sequence_start_time_us = - compute_sequence_start_time(first_time_us, last_time_us, frame_period_us, sequence_start_ratio); - const Metavision::timestamp sequence_duration_us = compute_sequence_duration( - first_time_us, last_time_us, frame_period_us, sequence_start_ratio, sequence_duration_ratio); - const Metavision::timestamp accumulation_time_us = compute_accumulation_time(accumulation_ratio, frame_period_us); - - // Update fps given start time - const Metavision::timestamp min_frame_period_us = 1; - const Metavision::timestamp max_frame_period_us = last_time_us - first_time_us; - const int min_fps = - clip(static_cast(1.e6 / max_frame_period_us + 0.5), AnalysisView::MinFps(), AnalysisView::MaxFps()); - const int max_fps = - clip(static_cast(1.e6 / min_frame_period_us + 0.5), AnalysisView::MinFps(), AnalysisView::MaxFps()); - - data.fps = clip(fps, min_fps, max_fps); - data.max_fps = max_fps; - data.min_fps = min_fps; - frame_period_us = compute_frame_period(data.fps); - - // Update start ratio - data.max_sequence_start_ratio = 100; - data.min_sequence_start_ratio = 0; - - // Update duration ratio - data.max_sequence_duration_ratio = 100; - data.min_sequence_duration_ratio = 1; - - // Update accumulation ratio given start time and frame period : we cannot accumulate more than - // sequence_start_time_us in any case - const int max_accumulation_ratio = clip(static_cast(sequence_start_time_us * 100. / frame_period_us + 0.5), - AnalysisView::MinAccumulationRatio(), AnalysisView::MaxAccumulationRatio()); - data.accumulation_ratio = clip(accumulation_ratio, AnalysisView::MinAccumulationRatio(), max_accumulation_ratio); - data.max_accumulation_ratio = max_accumulation_ratio; - data.min_accumulation_ratio = AnalysisView::MinAccumulationRatio(); - - // Update frame id given start time and frame duration - const Metavision::timestamp sequence_end_time_us = sequence_start_time_us + sequence_duration_us; - Metavision::timestamp time_us = sequence_start_time_us; - Metavision::timestamp max_frame_id = 0; - while (time_us + frame_period_us < sequence_end_time_us) { - time_us += frame_period_us; - ++max_frame_id; - } - data.max_frame_id = max_frame_id; - data.min_frame_id = 0; - data.frame_id = (current_time_us - sequence_start_time_us + frame_period_us - 1) / frame_period_us; - - return data; -} - -#endif // METAVISION_PLAYER_ANALYSIS_UTILS_H diff --git a/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_view.h b/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_view.h deleted file mode 100644 index 2efa6d5b3..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/inc/analysis_view.h +++ /dev/null @@ -1,100 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_PLAYER_ANALYSIS_VIEW_H -#define METAVISION_PLAYER_ANALYSIS_VIEW_H - -#include -#include -#include -#include -#include - -#include "viewer.h" -#include "view.h" -#include "params.h" - -class AnalysisView : public View { -public: - AnalysisView(Metavision::Camera &camera, Viewer::EventBuffer &event_buffer, const Parameters ¶meters, - const std::string &window_name = std::string()); - AnalysisView(const View &view); - - virtual void setAccumulationRatio(int accumulation_ratio) override; - virtual int accumulationRatio() const override; - - virtual void setFps(int fps) override; - virtual int fps() const override; - - virtual void setCurrentTimeUs(Metavision::timestamp time) override; - virtual Metavision::timestamp currentTimeUs() const override; - - static constexpr int MinFps() { - return 1; - }; - - static constexpr int MaxFps() { - return 2000; - } - - static constexpr int DefaultFps() { - return 25; - } - - static constexpr int MinAccumulationRatio() { - return 25; - } - - static constexpr int MaxAccumulationRatio() { - return 400; - } - - static constexpr int DefaultAccumulationRatio() { - return 100; - } - -protected: - virtual void setup() override; - virtual void update(cv::Mat &frame, int key_pressed) override; - virtual std::vector getHelpMessages() const override; - -private: - void setMinFps(int min_fps); - void setMaxFps(int max_fps); - - void setMinAccumulationRatio(int min_accumulation_ratio); - void setMaxAccumulationRatio(int max_accumulation_ratio); - - int sequenceStartTimeUs() const; - int sequenceStartRatio() const; - void setSequenceStartRatio(int sequence_start_ratio); - void setMinSequenceStartRatio(int min_sequence_start_time_ratio); - void setMaxSequenceStartRatio(int max_sequence_start_time_ratio); - - int sequenceDurationUs() const; - int sequenceDurationRatio() const; - void setSequenceDurationRatio(int sequence_duration_ratio); - void setMinSequenceDurationRatio(int min_sequence_duration_ratio); - void setMaxSequenceDurationRatio(int max_sequence_duration_ratio); - - int frameId() const; - void setFrameId(int frame_id); - void setMinFrameId(int min_frame_id); - void setMaxFrameId(int max_frame_id); - - void exportVideo(); - - Metavision::timestamp first_time_us_, last_time_us_; - bool setup_ = false; - cv::Mat frame_, tmp_frame_; -}; - -#endif // METAVISION_PLAYER_ANALYSIS_VIEW_H diff --git a/sdk/modules/core/cpp/samples/metavision_player/inc/camera_view.h b/sdk/modules/core/cpp/samples/metavision_player/inc/camera_view.h deleted file mode 100644 index c8ca2c5b3..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/inc/camera_view.h +++ /dev/null @@ -1,76 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_PLAYER_CAMERA_VIEW_H -#define METAVISION_PLAYER_CAMERA_VIEW_H - -#include -#include -#include -#include -#include -#include - -#include "view.h" -#include "params.h" - -class CameraView : public View { -public: - struct RoiControl { - static constexpr int MIN_ROI_SIZE = 5; - - RoiControl(Metavision::Camera &c) : camera(c) {} - - enum State { - NONE, - INIT, - CREATED, - REMOVE, - }; - - Metavision::Camera &camera; - int x, x_end, y, y_end; - State state{NONE}; - }; - - CameraView(Metavision::Camera &camera, Viewer::EventBuffer &event_buffer, const Parameters ¶meters, bool live, - const std::string &window_name = std::string()); - CameraView(bool live, const View &view); - ~CameraView(); - - virtual void setAccumulationRatio(int accumulation_ratio) override; - virtual int accumulationRatio() const override; - - virtual void setFps(int fps) override; - virtual int fps() const override; - - virtual void setCurrentTimeUs(Metavision::timestamp time) override; - virtual Metavision::timestamp currentTimeUs() const override; - - bool is_ready() const; - -protected: - virtual void setup() override; - virtual void update(cv::Mat &frame, int key_pressed) override; - virtual std::vector getHelpMessages() const override; - -private: - bool live_ = false; - bool recording_ = false; - bool ready_ = false; - std::string raw_filename_; - RoiControl roi_control_; - Metavision::timestamp time_us_ = 0; - int accumulation_ratio_ = 100; - int fps_ = 25; -}; - -#endif // METAVISION_PLAYER_CAMERA_VIEW_H diff --git a/sdk/modules/core/cpp/samples/metavision_player/inc/utils.h b/sdk/modules/core/cpp/samples/metavision_player/inc/utils.h deleted file mode 100644 index e843b913f..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/inc/utils.h +++ /dev/null @@ -1,124 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_PLAYER_UTILS_H -#define METAVISION_PLAYER_UTILS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -template -T clip(const T &val, const T &minVal, const T &maxVal) { - return std::min(std::max(val, minVal), maxVal); -} - -inline void addTrackBar(const std::string &label, const std::string &window, int minValue, int maxValue, - void (*cb)(int, void *) = nullptr, void *data = nullptr) { - cv::createTrackbar(label, window, nullptr, maxValue, cb, data); - cv::setTrackbarMax(label, window, maxValue); - cv::setTrackbarMin(label, window, minValue); - cv::setTrackbarPos(label, window, minValue); -} - -inline void addText(cv::Mat &frame, const std::string &text, const cv::Point &pos, const cv::Scalar &color) { - cv::putText(frame, text, pos, cv::FONT_HERSHEY_PLAIN, 1, color, 1, cv::LINE_AA); -} - -inline cv::Vec3b getCVColor(const Metavision::ColorPalette &palette, const Metavision::ColorType &type) { - const Metavision::RGBColor c = Metavision::get_color(palette, type); - return cv::Vec3b(c.b * 255 + 0.5, c.g * 255 + 0.5, c.r * 255 + 0.5); -} - -inline cv::Size getCameraSize(const Metavision::Camera &camera) { - return cv::Size(camera.geometry().width(), camera.geometry().height()); -} - -template -std::pair getSlice(It begin, It end, Metavision::timestamp t_begin, Metavision::timestamp t_end) { - // - // Look for the first element whose timestamp is > t_begin. - auto slice_begin = std::lower_bound(begin, end, t_begin, [](auto evt, auto ts) { return evt.t <= ts; }); - - // Look for the first element whose timestamp is >= t_end. - // Note that we begin at *slice_begin*, this makes that for an inverted range, the output is empty, as intended. - auto slice_end = std::upper_bound(slice_begin, end, t_end, [](auto ts, auto evt) { return evt.t > ts; }); - - return std::pair(slice_begin, slice_end); -} - -template -inline size_t makeSliceImage(cv::Mat &frame_bgr, InputIt begin, InputIt end, Metavision::timestamp current_ts_us, - Metavision::timestamp accumulation_time_us, Metavision::timestamp frame_duration_us, - int display_fps, const Metavision::ColorPalette &palette) { - auto slice_it = getSlice(begin, end, current_ts_us - accumulation_time_us, current_ts_us); - - const cv::Vec3b bg_color = getCVColor(palette, Metavision::ColorType::Background); - const cv::Vec3b pos_color = getCVColor(palette, Metavision::ColorType::Positive); - const cv::Vec3b neg_color = getCVColor(palette, Metavision::ColorType::Negative); - frame_bgr.setTo(bg_color); - - for (auto ev = slice_it.first; ev != slice_it.second; ++ev) { - if (ev->p == 1) { - frame_bgr.at(ev->y, ev->x) = pos_color; - } else if (ev->p == 0) { - frame_bgr.at(ev->y, ev->x) = neg_color; - } - } - - return std::distance(slice_it.first, slice_it.second); -} - -inline std::string timeInSeconds(Metavision::timestamp t) { - std::ostringstream oss; - oss << std::setprecision(3) << std::fixed << (t / 1.e6) << "s"; - return oss.str(); -} - -inline std::string makeSliceImageOverlayText(size_t num_events, Metavision::timestamp current_ts_us, - Metavision::timestamp accumulation_time_us, - Metavision::timestamp frame_duration_us, int display_fps) { - std::string msg = "Time : " + timeInSeconds(current_ts_us); - msg += " Rate : " + std::to_string(num_events * 1'000 / accumulation_time_us) + "kev/s"; - msg += " Acc. : " + std::to_string(accumulation_time_us) + "us"; - - const float fps = (1e6 / frame_duration_us); - const float speed_factor = display_fps / fps; - std::stringstream ss; - ss << " FPS : " << std::fixed << std::setprecision(1) << fps << " (" << std::setprecision(6) << std::defaultfloat - << speed_factor << "X)"; - msg += ss.str(); - return msg; -} - -inline std::string makeRawFilename(const std::string &basename) { - char buf[1024]; - std::time_t t = std::time(nullptr); - std::strftime(buf, 1024, "%Y-%m-%d_%H-%M-%S", std::localtime(&t)); - std::string filename(basename + "_" + buf + ".raw"); - return filename; -} - -inline int compute_frame_period(int fps) { - return static_cast(1.e6 / fps + 0.5); -} - -inline int compute_accumulation_time(int accumulation_ratio, int frame_period_us) { - return static_cast(accumulation_ratio * frame_period_us / 100. + 0.5); -} - -#endif // METAVISION_PLAYER_UTILS_H diff --git a/sdk/modules/core/cpp/samples/metavision_player/inc/view.h b/sdk/modules/core/cpp/samples/metavision_player/inc/view.h deleted file mode 100644 index a202042e9..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/inc/view.h +++ /dev/null @@ -1,88 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_PLAYER_VIEW_H -#define METAVISION_PLAYER_VIEW_H - -#include -#include -#include -#include -#include -#include - -#include "viewer.h" -#include "params.h" - -class View { -public: - static constexpr int TRACKBAR_HEIGHT = 60; - - View(Metavision::Camera &camera, Viewer::EventBuffer &event_buffer, const Parameters ¶meters, - const cv::Size &ui_size, const std::string &window_name); - View(const cv::Size &ui_size, const View &view); - - virtual ~View(); - - const std::string &windowName() const; - - void toggleHelpVisibility(); - bool helpVisible() const; - - void cycleColorPalette(); - Metavision::ColorPalette colorPalette() const; - - void setStatusMessage(const std::string &msg, int delay_msecs = 5'000); - - const Metavision::Camera &camera() const; - Metavision::Camera &camera(); - - const Viewer::EventBuffer &eventBuffer() const; - - const Parameters ¶meters() const; - - virtual void setAccumulationRatio(int accumulation_ratio) = 0; - virtual int accumulationRatio() const = 0; - int accumulationTimeUs() const; - - virtual void setFps(int fps) = 0; - virtual int fps() const = 0; - int framePeriodUs() const; - - virtual void setCurrentTimeUs(Metavision::timestamp time) = 0; - virtual Metavision::timestamp currentTimeUs() const = 0; - - int update(); - -protected: - virtual void setup() = 0; - virtual void update(cv::Mat &frame, int key_pressed) = 0; - virtual std::vector getHelpMessages() const = 0; - -private: - void showHelp(cv::Mat &frame); - void addTextBox(const std::string &text, const cv::Scalar &color, const cv::Rect &rect, const cv::Point &pos); - - Metavision::Camera &camera_; - Viewer::EventBuffer &event_buffer_; - Parameters parameters_; - std::string window_name_; - cv::Size window_size_; - cv::Mat frame_; - bool setup_; - bool show_help_; - Metavision::ColorPalette palette_; - std::string status_msg_; - std::chrono::high_resolution_clock::time_point status_msg_time_; - int status_msg_delay_ms_; -}; - -#endif // METAVISION_PLAYER_VIEW_H diff --git a/sdk/modules/core/cpp/samples/metavision_player/inc/viewer.h b/sdk/modules/core/cpp/samples/metavision_player/inc/viewer.h deleted file mode 100644 index 2f683060f..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/inc/viewer.h +++ /dev/null @@ -1,56 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_PLAYER_VIEWER_H -#define METAVISION_PLAYER_VIEWER_H - -#include -#include -#include -#include -#include -#include - -#include "params.h" - -class View; - -class Viewer { -public: - using EventBuffer = boost::circular_buffer; - static constexpr int FRAME_RATE = 25; - - Viewer(const Parameters ¶ms); - ~Viewer(); - - void start(); - bool update(); - void stop(); - - bool is_running(); - -private: - void setup_camera(); - - std::unique_ptr> prod_; - Parameters parameters_; - bool paused_; - Metavision::Camera camera_; - Metavision::timestamp ts_; - std::vector input_evt_buffer_; - EventBuffer event_buffer_; - cv::Size sensor_size_; - cv::Mat frame_; - std::unique_ptr view_; - int cd_events_cb_id_; -}; - -#endif // METAVISION_PLAYER_VIEWER_H diff --git a/sdk/modules/core/cpp/samples/metavision_player/src/analysis_view.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/analysis_view.cpp deleted file mode 100644 index d65484e6f..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/src/analysis_view.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "utils.h" -#include "analysis_view.h" -#include "analysis_utils.h" - -namespace { -const std::string FpsLabel("Fps"); -const std::string AccumulationRatioLabel("Acc (%)"); -const std::string SequenceStartRatioLabel("Start (%)"); -const std::string SequenceDurationRatioLabel("Length (%)"); -const std::string FrameIdLabel("Frame #"); -const size_t NumTrackBars = 5; -} // namespace - -AnalysisView::AnalysisView(Metavision::Camera &camera, Viewer::EventBuffer &event_buffer, const Parameters ¶meters, - const std::string &window_name) : - View(camera, event_buffer, parameters, cv::Size(0, NumTrackBars * TRACKBAR_HEIGHT), window_name), - first_time_us_(event_buffer.front().t), - last_time_us_(event_buffer.back().t) {} - -AnalysisView::AnalysisView(const View &view) : - View(cv::Size(0, NumTrackBars * TRACKBAR_HEIGHT), view), - first_time_us_(eventBuffer().front().t), - last_time_us_(eventBuffer().back().t) {} - -void AnalysisView::setup() { - setup_ = true; - const auto &window_name = windowName(); - addTrackBar(FpsLabel, window_name, MinFps(), MaxFps()); - setFps(DefaultFps()); - addTrackBar(AccumulationRatioLabel, window_name, MinAccumulationRatio(), MaxAccumulationRatio()); - setAccumulationRatio(DefaultAccumulationRatio()); - addTrackBar(SequenceStartRatioLabel, window_name, 0, 100); - setSequenceStartRatio(10); - addTrackBar(SequenceDurationRatioLabel, window_name, 1, 100); - setSequenceDurationRatio(100); - const int frame_period_us = framePeriodUs(); - int time_us = first_time_us_ + frame_period_us; - int frame_id = 0; - while (time_us + frame_period_us < last_time_us_) { - time_us += frame_period_us; - ++frame_id; - } - addTrackBar(FrameIdLabel, window_name, 0, frame_id); - setFrameId(frame_id); -} - -int AnalysisView::fps() const { - return (setup_ ? cv::getTrackbarPos(FpsLabel, windowName()) : DefaultFps()); -} - -void AnalysisView::setFps(int fps) { - cv::setTrackbarPos(FpsLabel, windowName(), fps); -} - -void AnalysisView::setMinFps(int min_fps) { - cv::setTrackbarMin(FpsLabel, windowName(), min_fps); -} - -void AnalysisView::setMaxFps(int max_fps) { - cv::setTrackbarMax(FpsLabel, windowName(), max_fps); -} - -int AnalysisView::accumulationRatio() const { - return (setup_ ? cv::getTrackbarPos(AccumulationRatioLabel, windowName()) : DefaultAccumulationRatio()); -} - -void AnalysisView::setAccumulationRatio(int accumulation_ratio) { - cv::setTrackbarPos(AccumulationRatioLabel, windowName(), accumulation_ratio); -} - -void AnalysisView::setMinAccumulationRatio(int min_accumulation_ratio) { - cv::setTrackbarMin(AccumulationRatioLabel, windowName(), min_accumulation_ratio); -} - -void AnalysisView::setMaxAccumulationRatio(int max_accumulation_ratio) { - cv::setTrackbarMax(AccumulationRatioLabel, windowName(), max_accumulation_ratio); -} - -int AnalysisView::sequenceStartTimeUs() const { - return compute_sequence_start_time(first_time_us_, last_time_us_, framePeriodUs(), sequenceStartRatio()); -} - -int AnalysisView::sequenceStartRatio() const { - return (setup_ ? cv::getTrackbarPos(SequenceStartRatioLabel, windowName()) : 0); -} - -void AnalysisView::setSequenceStartRatio(int sequence_start_ratio) { - cv::setTrackbarPos(SequenceStartRatioLabel, windowName(), sequence_start_ratio); -} - -void AnalysisView::setMinSequenceStartRatio(int min_sequence_start_ratio) { - cv::setTrackbarMin(SequenceStartRatioLabel, windowName(), min_sequence_start_ratio); -} - -void AnalysisView::setMaxSequenceStartRatio(int max_sequence_start_ratio) { - cv::setTrackbarMax(SequenceStartRatioLabel, windowName(), max_sequence_start_ratio); -} - -int AnalysisView::sequenceDurationUs() const { - return compute_sequence_duration(first_time_us_, last_time_us_, framePeriodUs(), sequenceStartRatio(), - sequenceDurationRatio()); -} - -int AnalysisView::sequenceDurationRatio() const { - return (setup_ ? cv::getTrackbarPos(SequenceDurationRatioLabel, windowName()) : 100); -} - -void AnalysisView::setSequenceDurationRatio(int sequence_duration_us) { - cv::setTrackbarPos(SequenceDurationRatioLabel, windowName(), sequence_duration_us); -} - -void AnalysisView::setMinSequenceDurationRatio(int min_sequence_duration_us) { - cv::setTrackbarMin(SequenceDurationRatioLabel, windowName(), min_sequence_duration_us); -} - -void AnalysisView::setMaxSequenceDurationRatio(int max_sequence_duration_us) { - cv::setTrackbarMax(SequenceDurationRatioLabel, windowName(), max_sequence_duration_us); -} - -int AnalysisView::frameId() const { - return (setup_ ? cv::getTrackbarPos(FrameIdLabel, windowName()) : 0); -} - -void AnalysisView::setFrameId(int frame_id) { - if (setup_) { - cv::setTrackbarPos(FrameIdLabel, windowName(), frame_id); - } -} - -void AnalysisView::setMinFrameId(int min_frame_id) { - cv::setTrackbarMin(FrameIdLabel, windowName(), min_frame_id); -} - -void AnalysisView::setMaxFrameId(int max_frame_id) { - cv::setTrackbarMax(FrameIdLabel, windowName(), max_frame_id); -} - -Metavision::timestamp AnalysisView::currentTimeUs() const { - return compute_current_time(sequenceStartTimeUs(), frameId(), framePeriodUs()); -} - -void AnalysisView::setCurrentTimeUs(Metavision::timestamp) {} - -std::vector AnalysisView::getHelpMessages() const { - // clang-format off - std::vector msgs = { - "Keyboard/mouse actions:", - " \"h\" show/hide the help menu", - " \"c\" cycle color theme", - " \"a\" toggle analysis mode", - " \"s\" save a snapshot image of current frame", - " \"v\" save a video of current buffer", - }; - msgs.push_back(" \"q\" or ESC exit the application"); - // clang-format on - return msgs; -} - -void AnalysisView::exportVideo() { - const auto &event_buffer = eventBuffer(); - const auto &palette = colorPalette(); - const auto ¶ms = parameters(); - if (event_buffer.empty()) { - return; - } - - auto log = MV_LOG_INFO() << Metavision::Log::no_endline << Metavision::Log::no_space << "Exporting to " - << params.out_avi_file << "@" << params.out_avi_fps << " fps."; - - auto begin = event_buffer.begin(), end = event_buffer.end(); - const int sequence_start_time_us = sequenceStartTimeUs(); - const int sequence_end_time_us = sequence_start_time_us + sequenceDurationUs(); - const int frame_period_us = framePeriodUs(); - const int accumulation_time_us = accumulationTimeUs(); - const auto &sensor_size = getCameraSize(camera()); - cv::Mat frame(sensor_size, CV_8UC3); - cv::VideoWriter video_writer(params.out_avi_file, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), params.out_avi_fps, - sensor_size); - int n_frames = 0; - for (Metavision::timestamp ts_us = sequence_start_time_us; ts_us <= sequence_end_time_us; - ts_us += frame_period_us, ++n_frames) {} - - auto last = std::chrono::time_point::max(); - int frame_id = 0; - for (Metavision::timestamp ts_us = sequence_start_time_us; ts_us <= sequence_end_time_us; - ts_us += frame_period_us, ++frame_id) { - auto now = std::chrono::high_resolution_clock::now(); - long delay = std::chrono::duration_cast(now - last).count(); - if (frame_id == 0 || delay > 500) { - log << "."; - tmp_frame_ = frame_.clone(); - - std::ostringstream oss; - const auto &color = getCVColor(palette, Metavision::ColorType::Auxiliary); - cv::Rect rect(0, frame_.rows - 20, frame_.cols, 20); - cv::Mat box = tmp_frame_(rect); - box -= cv::Scalar::all(255 * 0.8); - oss << "Exporting frame " << frame_id << " of " << n_frames << ", please wait."; - addText(box, oss.str(), cv::Point(5, 14), color); - imshow(windowName(), tmp_frame_); - cv::waitKey(1); - last = now; - } - makeSliceImage(frame, begin, end, ts_us, accumulation_time_us, frame_period_us, params.out_avi_fps, palette); - video_writer.write(frame); - } - log << std::endl; - MV_LOG_INFO() << "Done writing video, wrote" << n_frames << "frames"; -} - -void AnalysisView::update(cv::Mat &frame, int key_pressed) { - const auto &event_buffer = eventBuffer(); - const auto ¶ms = parameters(); - const auto &palette = colorPalette(); - - switch (key_pressed) { - case 's': { - cv::imwrite(params.out_png_file, frame); - setStatusMessage("Saved frame at " + params.out_png_file); - MV_LOG_INFO() << "Saved frame at" << params.out_png_file; - break; - } - case 'v': - frame_ = frame; - exportVideo(); - setStatusMessage("Saved video at " + params.out_avi_file); - MV_LOG_INFO() << "Saved video at" << params.out_avi_file; - break; - } - - const auto &window_name = windowName(); - AnalysisData data = compute_analysis_data(first_time_us_, last_time_us_, fps(), accumulationRatio(), - sequenceStartRatio(), sequenceDurationRatio(), currentTimeUs()); - - // Update fps - setMaxFps(data.max_fps); - setMinFps(data.min_fps); - setFps(data.fps); - - // Update start ratio - setMaxSequenceStartRatio(data.max_sequence_start_ratio); - setMinSequenceStartRatio(data.min_sequence_start_ratio); - - // Update duration ratio - setMaxSequenceDurationRatio(data.max_sequence_duration_ratio); - setMinSequenceDurationRatio(data.min_sequence_duration_ratio); - - // Update accumulation ratio - setMaxAccumulationRatio(data.max_accumulation_ratio); - setMinAccumulationRatio(data.min_accumulation_ratio); - setAccumulationRatio(data.accumulation_ratio); - - // Update frame id - setMaxFrameId(data.max_frame_id); - setMinFrameId(data.min_frame_id); - setFrameId(data.frame_id); -} diff --git a/sdk/modules/core/cpp/samples/metavision_player/src/camera_view.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/camera_view.cpp deleted file mode 100644 index 893a7d357..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/src/camera_view.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "utils.h" -#include "camera_view.h" - -namespace { -const std::string DiffOnLabel("diff_on"); -const std::string DiffOffLabel("diff_off"); -const std::string HpfLabel("hpf"); -const std::string FoLabel("fo"); -const std::string PrLabel("pr"); -const std::string RefrLabel("refr"); - -std::unordered_map biasLabelToName{ - {DiffOnLabel, "bias_diff_on"}, {DiffOffLabel, "bias_diff_off"}, {HpfLabel, "bias_hpf"}, {FoLabel, "bias_fo"}, - {PrLabel, "bias_pr"}, {RefrLabel, "bias_refr"}}; - -const size_t NumTrackBars = biasLabelToName.size(); - -std::unordered_map orig_biases; -std::unordered_map current_biases; - -int current_roi_x, current_roi_x_end, current_roi_y, current_roi_y_end; -CameraView::RoiControl::State current_roi_state = CameraView::RoiControl::State::NONE; - -void diff_off_trackbar_handler(int v, void *ptr) { - auto *view = reinterpret_cast(ptr); - if (view->is_ready()) { - view->camera().biases().get_facility()->set(biasLabelToName[DiffOffLabel], v); - } -} - -void diff_on_trackbar_handler(int v, void *ptr) { - auto *view = reinterpret_cast(ptr); - if (view->is_ready()) { - view->camera().biases().get_facility()->set(biasLabelToName[DiffOnLabel], v); - } -} - -void hpf_trackbar_handler(int v, void *ptr) { - auto *view = reinterpret_cast(ptr); - if (view->is_ready()) { - view->camera().biases().get_facility()->set(biasLabelToName[HpfLabel], v); - } -} - -void fo_trackbar_handler(int v, void *ptr) { - auto *view = reinterpret_cast(ptr); - if (view->is_ready()) { - view->camera().biases().get_facility()->set(biasLabelToName[FoLabel], v); - } -} - -void pr_trackbar_handler(int v, void *ptr) { - auto *view = reinterpret_cast(ptr); - if (view->is_ready()) { - view->camera().biases().get_facility()->set(biasLabelToName[PrLabel], v); - } -} - -void refr_trackbar_handler(int v, void *ptr) { - auto *view = reinterpret_cast(ptr); - if (view->is_ready()) { - view->camera().biases().get_facility()->set(biasLabelToName[RefrLabel], v); - } -} - -void mouse_handler(int event, int x, int y, int, void *ptr) { - CameraView::RoiControl *roi_control = static_cast(ptr); - - if (event == cv::EVENT_LBUTTONDOWN) { - if (roi_control->state != CameraView::RoiControl::INIT) { - roi_control->state = CameraView::RoiControl::INIT; - roi_control->x = x; - roi_control->y = y; - roi_control->x_end = x; - roi_control->y_end = y; - } - } else if (event == cv::EVENT_MOUSEMOVE && roi_control->state == CameraView::RoiControl::INIT) { - roi_control->x_end = x; - roi_control->y_end = y; - } else if (event == cv::EVENT_LBUTTONUP && roi_control->state == CameraView::RoiControl::INIT) { - roi_control->state = CameraView::RoiControl::CREATED; - roi_control->x_end = x; - roi_control->y_end = y; - } else if (event == cv::EVENT_RBUTTONDOWN) { - roi_control->state = CameraView::RoiControl::REMOVE; - } -} - -} // namespace - -CameraView::CameraView(Metavision::Camera &cam, Viewer::EventBuffer &event_buffer, const Parameters ¶meters, - bool live, const std::string &window_name) : - View(cam, event_buffer, parameters, - cv::Size(0, live && parameters.show_biases ? NumTrackBars * TRACKBAR_HEIGHT : 0), window_name), - live_(live), - roi_control_(cam) {} - -CameraView::CameraView(bool live, const View &view) : - View(cv::Size(0, live && view.parameters().show_biases ? NumTrackBars * TRACKBAR_HEIGHT : 0), view), - live_(live), - roi_control_(camera()) {} - -CameraView::~CameraView() { - if (recording_) { - camera().stop_recording(); - MV_LOG_INFO() << "Saved RAW file at" << raw_filename_; - } - - if (live_) { - // Update values of current biases - auto &cam = camera(); - const auto ¶ms = parameters(); - if (params.show_biases) { - try { - auto *bias = cam.biases().get_facility(); - for (auto p : biasLabelToName) { - current_biases[p.first] = bias->get(p.second); - } - } catch (...) {} - } - } -} - -void CameraView::setup() { - if (live_) { - const auto &window_name = windowName(); - cv::setMouseCallback(window_name, mouse_handler, &roi_control_); - - const auto ¶ms = parameters(); - if (params.show_biases) { - auto &cam = camera(); - try { - const auto &gen = cam.generation(); - auto *bias = cam.biases().get_facility(); - - addTrackBar(DiffOffLabel, window_name, 0, 1, diff_off_trackbar_handler, this); - addTrackBar(DiffOnLabel, window_name, 0, 1, diff_on_trackbar_handler, this); - addTrackBar(HpfLabel, window_name, 0, 1, hpf_trackbar_handler, this); - addTrackBar(FoLabel, window_name, 0, 1, fo_trackbar_handler, this); - if (!(gen.version_major() == 4 && gen.version_minor() == 1)) { - addTrackBar(PrLabel, window_name, 0, 1, pr_trackbar_handler, this); - } - addTrackBar(RefrLabel, window_name, 0, 1, refr_trackbar_handler, this); - - if (gen.version_major() == 4) { - if (gen.version_minor() == 0) { - biasLabelToName[FoLabel] = "bias_fo_n"; - } else { - biasLabelToName.erase(PrLabel); - } - } - - if (current_biases.size() == 0) { - // In this case it's the first time this view has been build : - // we take the original biases - for (auto p : biasLabelToName) { - orig_biases[p.first] = bias->get(p.second); - current_biases[p.first] = orig_biases[p.first]; - } - } else { - // In this case we set the biases to their last value - for (auto p : biasLabelToName) { - bias->set(p.second, current_biases[p.first]); - } - } - - int bias_diff = bias->get("bias_diff"); - if (gen.version_major() == 3 && gen.version_minor() == 0) { - cv::setTrackbarMax(DiffOffLabel, window_name, bias_diff - 1); - cv::setTrackbarMin(DiffOffLabel, window_name, 0); - cv::setTrackbarMax(DiffOnLabel, window_name, 1800); - cv::setTrackbarMin(DiffOnLabel, window_name, bias_diff + 1); - cv::setTrackbarMax(HpfLabel, window_name, 1800); - cv::setTrackbarMin(HpfLabel, window_name, 0); - cv::setTrackbarMax(FoLabel, window_name, 1800); - cv::setTrackbarMin(FoLabel, window_name, 1650); - cv::setTrackbarMax(PrLabel, window_name, 1800); - cv::setTrackbarMin(PrLabel, window_name, 1200); - cv::setTrackbarMax(RefrLabel, window_name, 1800); - cv::setTrackbarMin(RefrLabel, window_name, 1300); - } else if (gen.version_major() == 3 && gen.version_minor() == 1) { - cv::setTrackbarMax(DiffOffLabel, window_name, bias_diff - 1); - cv::setTrackbarMin(DiffOffLabel, window_name, 0); - cv::setTrackbarMax(DiffOnLabel, window_name, 1800); - cv::setTrackbarMin(DiffOnLabel, window_name, bias_diff + 1); - cv::setTrackbarMax(HpfLabel, window_name, 1800); - cv::setTrackbarMin(HpfLabel, window_name, 0); - cv::setTrackbarMax(FoLabel, window_name, 1800); - cv::setTrackbarMin(FoLabel, window_name, 0); - cv::setTrackbarMax(PrLabel, window_name, 1800); - cv::setTrackbarMin(PrLabel, window_name, 0); - cv::setTrackbarMax(RefrLabel, window_name, 1800); - cv::setTrackbarMin(RefrLabel, window_name, 0); - } else if (gen.version_major() == 4) { - cv::setTrackbarMax(DiffOffLabel, window_name, bias_diff - 1); - cv::setTrackbarMin(DiffOffLabel, window_name, 0); - cv::setTrackbarMax(DiffOnLabel, window_name, 255); - cv::setTrackbarMin(DiffOnLabel, window_name, bias_diff + 1); - cv::setTrackbarMax(HpfLabel, window_name, 255); - cv::setTrackbarMin(HpfLabel, window_name, 0); - cv::setTrackbarMax(FoLabel, window_name, 255); - cv::setTrackbarMin(FoLabel, window_name, 0); - if (gen.version_minor() != 1) { - cv::setTrackbarMax(PrLabel, window_name, 255); - cv::setTrackbarMin(PrLabel, window_name, 0); - } - cv::setTrackbarMax(RefrLabel, window_name, 255); - cv::setTrackbarMin(RefrLabel, window_name, 0); - } else { - MV_LOG_ERROR() << "Unknown camera generation"; - return; - } - for (auto p : biasLabelToName) { - cv::setTrackbarPos(p.first, window_name, current_biases[p.first]); - } - } catch (...) {} - } - - // Update Roi if necessary : - if (current_roi_state == RoiControl::CREATED) { - roi_control_.state = current_roi_state; - roi_control_.x = current_roi_x; - roi_control_.x_end = current_roi_x_end; - roi_control_.y = current_roi_y; - roi_control_.y_end = current_roi_y_end; - } - ready_ = true; - } -} - -std::vector CameraView::getHelpMessages() const { - // clang-format off - std::vector msgs = { - "Keyboard/mouse actions:", - " \"h\" show/hide the help menu", - " \"c\" cycle color theme", - " \"a\" toggle analysis mode", - }; - // clang-format on - const auto ¶ms = parameters(); - if (params.show_biases) { - msgs.push_back(" \"b\" save current biases in a bias file"); - if (!params.in_bias_file.empty()) - msgs.push_back(" \"r\" reset biases to values loaded from bias file"); - else - msgs.push_back(" \"r\" reset biases to default values"); - } - msgs.push_back(" SPACE start/stop recording RAW file"); - msgs.push_back(" \"q\" or ESC exit the application"); - if (live_) { - msgs.push_back(" Click and drag to create ROI"); - msgs.push_back(" Right-click to cancel ROI"); - } - return msgs; -} - -int CameraView::accumulationRatio() const { - return accumulation_ratio_; -} - -void CameraView::setAccumulationRatio(int accumulation_ratio) { - accumulation_ratio_ = accumulation_ratio; -} - -int CameraView::fps() const { - return fps_; -} - -void CameraView::setFps(int fps) { - fps_ = fps; -} - -void CameraView::setCurrentTimeUs(Metavision::timestamp time_us) { - time_us_ = time_us; -} - -Metavision::timestamp CameraView::currentTimeUs() const { - return time_us_; -} - -bool CameraView::is_ready() const { - return ready_; -} - -void CameraView::update(cv::Mat &frame, int key_pressed) { - const auto &window_name = windowName(); - auto &cam = camera(); - const auto ¶ms = parameters(); - - switch (key_pressed) { - case 'r': { - if (params.show_biases) { - try { - for (auto p : biasLabelToName) { - cam.biases().get_facility()->set(p.second, orig_biases[p.first]); - current_biases[p.first] = orig_biases[p.first]; - cv::setTrackbarPos(p.first, window_name, orig_biases[p.first]); - } - if (!params.in_bias_file.empty()) { - setStatusMessage("Reset biases to values loaded from bias file"); - MV_LOG_INFO() << "Reset biases to values loaded from bias file"; - } else { - setStatusMessage("Reset biases to default values"); - MV_LOG_INFO() << "Reset biases to default values"; - } - } catch (...) {} - } - break; - } - case 'b': { - if (params.show_biases) { - try { - cam.biases().save_to_file(params.out_bias_file); - setStatusMessage("Saved bias file at " + params.out_bias_file); - MV_LOG_INFO() << "Saved bias file at" << params.out_bias_file; - } catch (...) {} - } - break; - } - case ' ': { - recording_ = !recording_; - if (recording_) { - raw_filename_ = makeRawFilename(params.out_raw_basename); - cam.start_recording(raw_filename_); - setStatusMessage("Saving RAW file at " + raw_filename_); - MV_LOG_INFO() << "Saving RAW file at" << raw_filename_; - } else { - cam.stop_recording(); - setStatusMessage("Saved RAW file at " + raw_filename_); - MV_LOG_INFO() << "Saved RAW file at" << raw_filename_; - } - break; - } - } - - const auto &palette = colorPalette(); - switch (roi_control_.state) { - case RoiControl::NONE: - break; - case RoiControl::REMOVE: - roi_control_.state = RoiControl::NONE; - roi_control_.camera.roi().unset(); - current_roi_state = RoiControl::NONE; - break; - case RoiControl::INIT: { - int x = cv::max(0, cv::min(roi_control_.x, roi_control_.x_end)); - int y = cv::max(0, cv::min(roi_control_.y, roi_control_.y_end)); - int x_end = cv::min(roi_control_.camera.geometry().width(), cv::max(roi_control_.x, roi_control_.x_end)); - int y_end = cv::min(roi_control_.camera.geometry().height(), cv::max(roi_control_.y, roi_control_.y_end)); - - cv::Rect rect(x, y, x_end - x, y_end - y); - const cv::Scalar c = getCVColor(palette, Metavision::ColorType::Auxiliary); - cv::rectangle(frame, rect, c); - break; - } - case RoiControl::CREATED: { - int x = cv::max(0, cv::min(roi_control_.x, roi_control_.x_end)); - int y = cv::max(0, cv::min(roi_control_.y, roi_control_.y_end)); - int x_end = cv::min(roi_control_.camera.geometry().width(), cv::max(roi_control_.x, roi_control_.x_end)); - int y_end = cv::min(roi_control_.camera.geometry().height(), cv::max(roi_control_.y, roi_control_.y_end)); - - Metavision::Roi::Window rect_roi; - rect_roi.x = x; - rect_roi.y = y; - rect_roi.width = x_end - x; - rect_roi.height = y_end - y; - if (rect_roi.width >= RoiControl::MIN_ROI_SIZE && rect_roi.height >= RoiControl::MIN_ROI_SIZE) { - roi_control_.camera.roi().set(rect_roi); - } - - // Update value of current roi: - current_roi_state = RoiControl::CREATED; - current_roi_x = roi_control_.x; - current_roi_x_end = roi_control_.x_end; - current_roi_y = roi_control_.y; - current_roi_y_end = roi_control_.y_end; - - roi_control_.state = RoiControl::NONE; - break; - } - } -} diff --git a/sdk/modules/core/cpp/samples/metavision_player/src/main.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/main.cpp deleted file mode 100644 index 2df869eaf..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/src/main.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifdef _WIN32 -#include -#include -#endif -#include -#include -#include -#include -#include -#include - -#include "params.h" -#include "viewer.h" -#include "utils.h" - -namespace po = boost::program_options; - -// Parse command line input and return parameters for the application. -// Returns true if the application is supposed to continue running, false otherwise. -bool parse_command_line(int argc, const char *argv[], Parameters &app_params) { - const std::string program_desc("Metavision Player allows to stream/records events and analyse event-based data.\n"); - - boost::filesystem::path docs_path; -#ifdef _WIN32 - - PWSTR ppszPath; // variable to receive the path memory block pointer. - HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath); - std::wstring myPath; - if (SUCCEEDED(hr)) { - myPath = ppszPath; // make a local copy of the path - } - CoTaskMemFree(ppszPath); // free up the path memory block - docs_path = boost::filesystem::path(myPath); - -#else - char *home_path_ptr = getenv("HOME"); - if (home_path_ptr) { - std::string home_path(home_path_ptr); - docs_path = boost::filesystem::path(home_path) / "Documents"; - } -#endif - - if (docs_path.empty()) { - MV_LOG_ERROR() << "Could not determine default Documents directory "; - return false; - } - - docs_path /= "Prophesee"; - if (!boost::filesystem::exists(docs_path) && !boost::filesystem::create_directories(docs_path)) { - MV_LOG_ERROR() << "Could not create directory " << docs_path.string(); - return false; - } - - po::options_description options_desc("Options"); - // clang-format off - options_desc.add_options() - ("help,h", "Produce help message.") - ("biases,b", po::value(&app_params.in_bias_file), "Path to a bias file. If not specified, default biases will be used.") - ("show-biases", po::bool_switch(&app_params.show_biases)->default_value(false), "Show sliders to change biases dynamically.") - ("buffer-capacity,k", po::value(&app_params.buffer_size_mev)->default_value(100), "Max number of events to be stored in the buffer, in millions of events.") - ("output-bias-file", po::value(&app_params.out_bias_file)->default_value((docs_path / "out.bias").string()), "Path to the output bias file for exporting, only available if --show-biases is used.") - ("output-png-file,p", po::value(&app_params.out_png_file)->default_value((docs_path / "frame.png").string()), "Path to the output PNG file for exporting.") - ("output-avi-file,v", po::value(&app_params.out_avi_file)->default_value((docs_path / "video.avi").string()), "Path to the output AVI file for exporting.") - ("output-avi-framerate,f", po::value(&app_params.out_avi_fps)->default_value(25), "Frame rate of the output AVI file.") - ("output-raw-basename,o", po::value(&app_params.out_raw_basename)->default_value((docs_path / "out").string()), - "Path and base name of the output RAW file for exporting. Each file will have the name /_.raw, where represents the day and time the file was recorded.") - ("input-event-file,i", po::value(&app_params.event_file_path), "Path to input event file (RAW or HDF5). If not specified, the camera live stream is used.") - ; - // clang-format on - - po::variables_map vm; - try { - po::store(po::command_line_parser(argc, argv).options(options_desc).run(), vm); - po::notify(vm); - } catch (po::error &e) { - MV_LOG_ERROR() << program_desc; - MV_LOG_ERROR() << options_desc; - MV_LOG_ERROR() << "Parsing error:" << e.what(); - return false; - } - - if (vm.count("help")) { - MV_LOG_INFO() << program_desc; - MV_LOG_INFO() << options_desc; - return false; - } - - // Check extension of provided output files - if (boost::filesystem::extension(app_params.out_bias_file) != ".bias") { - MV_LOG_ERROR() << "Wrong extension for provided output bias file: supported extension is '.bias'"; - return false; - } - if (boost::filesystem::extension(app_params.out_png_file) != ".png") { - MV_LOG_ERROR() << "Wrong extension for provided output PNG file: supported extension is '.png'"; - return false; - } - if (boost::filesystem::extension(app_params.out_avi_file) != ".avi") { - MV_LOG_ERROR() << "Wrong extension for provided output AVI file: supported extension is '.avi'"; - return false; - } - return true; -} - -namespace { -std::atomic signal_caught{false}; - -void sig_handler(int s) { - MV_LOG_TRACE() << "Interrupt signal received." << std::endl; - signal_caught = true; -} -} // anonymous namespace - -int main(int argc, const char *argv[]) { - signal(SIGINT, sig_handler); - - // Parse command line. - Parameters params; - if (!parse_command_line(argc, argv, params)) { - return 1; - } - - Viewer viewer(params); - try { - viewer.start(); - } catch (Metavision::CameraException &e) { - MV_LOG_ERROR() << e.what(); - return 1; - } - - bool ret = true; - while (!signal_caught && ret) { - ret = viewer.update(); - } - - viewer.stop(); - - return signal_caught; -} diff --git a/sdk/modules/core/cpp/samples/metavision_player/src/view.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/view.cpp deleted file mode 100644 index c50b39d31..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/src/view.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "utils.h" -#include "view.h" - -View::View(Metavision::Camera &camera, Viewer::EventBuffer &event_buffer, const Parameters ¶meters, - const cv::Size &ui_size, const std::string &window_name) : - camera_(camera), - event_buffer_(event_buffer), - parameters_(parameters), - window_name_((window_name.empty() ? "Metavision Player" : window_name)), - window_size_(getCameraSize(camera) + ui_size), - frame_(getCameraSize(camera), CV_8UC3), - setup_(false), - show_help_(false), - palette_(Metavision::ColorPalette::Light) {} - -View::View(const cv::Size &ui_size, const View &view) : - camera_(view.camera_), - event_buffer_(view.event_buffer_), - parameters_(view.parameters_), - window_name_(view.window_name_), - window_size_(getCameraSize(view.camera_) + ui_size), - frame_(view.frame_.clone()), - setup_(false), - show_help_(view.show_help_), - palette_(view.palette_) {} - -View::~View() { - if (setup_) { - cv::destroyWindow(window_name_); - } -} - -const std::string &View::windowName() const { - return window_name_; -} - -bool View::helpVisible() const { - return show_help_; -} - -void View::toggleHelpVisibility() { - show_help_ = !show_help_; -} - -void View::showHelp(cv::Mat &frame) { - const auto &palette = colorPalette(); - const cv::Scalar aux_color = getCVColor(palette, Metavision::ColorType::Auxiliary); - frame -= cv::Scalar::all(255 * 0.8); - - std::vector msgs = getHelpMessages(); - const int LetterWidth = 8, LineHeight = 20; - cv::Size size; - for (auto &msg : msgs) { - if (msg.size() * LetterWidth > static_cast(size.width)) - size.width = msg.size() * LetterWidth; - size.height += LineHeight; - } - - int y_offset = 0; - for (auto &msg : msgs) { - addText(frame, msg, cv::Point((frame.cols - size.width) / 2, (frame.rows - size.height) / 2 + y_offset), - aux_color); - y_offset += LineHeight; - } -} - -void View::addTextBox(const std::string &text, const cv::Scalar &color, const cv::Rect &rect, const cv::Point &pos) { - cv::Mat box = frame_(rect); - box -= cv::Scalar::all(255 * 0.8); - addText(box, text, pos, color); -} - -int View::update() { - if (!setup_) { - setup_ = true; - cv::namedWindow(window_name_, cv::WINDOW_NORMAL); - cv::imshow(window_name_, frame_); - cv::resizeWindow(window_name_, window_size_.width, window_size_.height); - setup(); - cv::waitKey(1); - } - - int key_pressed = cv::waitKey(1); - switch (key_pressed) { - case 'h': - toggleHelpVisibility(); - break; - case 'c': - cycleColorPalette(); - break; - default: - break; - } - - // Draw image and compute statistic message - auto &buffer = eventBuffer(); - Metavision::timestamp ts = currentTimeUs(); - size_t num_events = makeSliceImage(frame_, buffer.begin(), buffer.end(), ts, accumulationTimeUs(), framePeriodUs(), - Viewer::FRAME_RATE, colorPalette()); - - update(frame_, key_pressed); - if (helpVisible()) { - showHelp(frame_); - } else { - const auto &msg = - makeSliceImageOverlayText(num_events, ts, accumulationTimeUs(), framePeriodUs(), Viewer::FRAME_RATE); - addTextBox(msg, cv::Scalar::all(255), cv::Rect(0, 0, frame_.cols, 20), cv::Point(5, 14)); - } - if (!status_msg_.empty()) { - const auto &palette = colorPalette(); - auto now = std::chrono::high_resolution_clock::now(); - long delay = std::chrono::duration_cast(now - status_msg_time_).count(); - if (delay < status_msg_delay_ms_) { - addTextBox(status_msg_, getCVColor(palette, Metavision::ColorType::Auxiliary), - cv::Rect(0, frame_.rows - 20, frame_.cols, 20), cv::Point(5, 14)); - } else { - status_msg_ = std::string(); - } - } - cv::imshow(window_name_, frame_); - - return key_pressed; -} - -void View::cycleColorPalette() { - palette_ = static_cast((static_cast(palette_) + 1) % 3); -} - -Metavision::ColorPalette View::colorPalette() const { - return palette_; -} - -void View::setStatusMessage(const std::string &msg, int delay_msecs) { - status_msg_ = msg; - status_msg_time_ = std::chrono::high_resolution_clock::now(); - status_msg_delay_ms_ = delay_msecs; -} - -Metavision::Camera &View::camera() { - return camera_; -} - -const Metavision::Camera &View::camera() const { - return camera_; -} - -const Viewer::EventBuffer &View::eventBuffer() const { - return event_buffer_; -} - -const Parameters &View::parameters() const { - return parameters_; -} - -int View::accumulationTimeUs() const { - return compute_accumulation_time(accumulationRatio(), framePeriodUs()); -} - -int View::framePeriodUs() const { - return compute_frame_period(fps()); -} diff --git a/sdk/modules/core/cpp/samples/metavision_player/src/viewer.cpp b/sdk/modules/core/cpp/samples/metavision_player/src/viewer.cpp deleted file mode 100644 index fea30a8fe..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/src/viewer.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "utils.h" -#include "viewer.h" -#include "view.h" -#include "camera_view.h" -#include "analysis_view.h" - -Viewer::Viewer(const Parameters ¶meters) : - parameters_(parameters), - event_buffer_(parameters.buffer_size_mev * 1e6), - paused_(false), - ts_(0), - cd_events_cb_id_(-1) {} - -Viewer::~Viewer() { - stop(); -} - -void Viewer::setup_camera() { - // Release camera. - camera_ = Metavision::Camera(); - - // Live camera. - if (parameters_.event_file_path.empty()) { - camera_ = Metavision::Camera::from_first_available(); - - // Set biases if file specified. - if (!parameters_.in_bias_file.empty()) { - camera_.biases().set_from_file(parameters_.in_bias_file); - } - } - // RAW file. - else { - camera_ = Metavision::Camera::from_file(parameters_.event_file_path); - } - - // Get sensor size - auto &geometry = camera_.geometry(); - sensor_size_.width = geometry.width(); - sensor_size_.height = geometry.height(); - - // Add runtime error callback. - camera_.add_runtime_error_callback([](const Metavision::CameraException &e) { - MV_LOG_ERROR() << e.what(); - throw; - }); - - // Add CD callback - prod_.reset(new Metavision::GenericProducerAlgorithm(40'000)); - cd_events_cb_id_ = - camera_.cd().add_callback([this](const Metavision::Event2d *ev_begin, const Metavision::Event2d *ev_end) { - prod_->register_new_event_buffer(ev_begin, ev_end); - }); -} - -bool Viewer::is_running() { - return paused_ || camera_.is_running(); -} - -void Viewer::start() { - setup_camera(); - camera_.start(); - - bool live = parameters_.event_file_path.empty(); - view_.reset(new CameraView(camera_, event_buffer_, parameters_, live)); -} - -bool Viewer::update() { - if (parameters_.event_file_path.empty() && parameters_.show_biases) { - // Handle specific case of trying to set biases when using an IMX636 or a GenX320 camera - if ((camera_.generation().version_major() == 4 && camera_.generation().version_minor() == 2) || - (camera_.generation().version_major() == 320 && camera_.generation().version_minor() == 0)) { - MV_LOG_ERROR() << "Metavision Player can not be used to set biases for this camera. Please use " - "Metavision Studio instead."; - return false; - } - } - - if (!paused_) { - input_evt_buffer_.clear(); - ts_ += view_->framePeriodUs(); - view_->setCurrentTimeUs(ts_); - prod_->process_events(ts_, std::back_inserter(input_evt_buffer_)); - - // Insert data into the buffer. - event_buffer_.insert(event_buffer_.end(), input_evt_buffer_.cbegin(), input_evt_buffer_.cend()); - } - - int key_pressed = view_->update(); - if (key_pressed == 27 || key_pressed == 'q') { - // Quit - return false; - } else if (key_pressed == 'a') { - // Enter/exit pause mode. - paused_ = !paused_; - if (paused_) { - if (event_buffer_.back().t - event_buffer_.front().t < 5'000) { - // Ignore the key until we have enough events in the buffer ... - paused_ = false; - } else { - // When pausing, stop the camera - camera_.stop(); - view_.reset(new AnalysisView(*view_)); - } - } else { - bool live = parameters_.event_file_path.empty(); - if (live) { - // When using a live camera, recreate it from scratch at start - // and reset the timestamp - setup_camera(); - ts_ = 0; - } - - // When restarting after pause, start the camera and clear the buffer - camera_.start(); - event_buffer_.clear(); - view_.reset(new CameraView(live, *view_)); - } - } - return true; -} - -void Viewer::stop() { - // unregister callbacks to make sure they are not called anymore - if (cd_events_cb_id_ >= 0) { - camera_.cd().remove_callback(cd_events_cb_id_); - cd_events_cb_id_ = -1; - } - if (camera_.is_running()) { - MV_LOG_TRACE() << "Closing camera." << std::endl; - camera_.stop(); - } - prod_->set_source_as_done(); -} diff --git a/sdk/modules/core/cpp/samples/metavision_player/test/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_player/test/CMakeLists.txt deleted file mode 100644 index 706bb38b1..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/test/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) Prophesee S.A. -# -# 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. - -add_executable(gtest_metavision_sdk_core_player player_gtest.cpp) -target_include_directories(gtest_metavision_sdk_core_player - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/../inc -) -target_link_libraries(gtest_metavision_sdk_core_player - PRIVATE - MetavisionSDK::core - MetavisionSDK::driver - MetavisionUtils::gtest -) - -register_gtest(TEST sdk-core-player-unit-tests TARGET gtest_metavision_sdk_core_player) diff --git a/sdk/modules/core/cpp/samples/metavision_player/test/player_gtest.cpp b/sdk/modules/core/cpp/samples/metavision_player/test/player_gtest.cpp deleted file mode 100644 index 4ebe184ca..000000000 --- a/sdk/modules/core/cpp/samples/metavision_player/test/player_gtest.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "analysis_utils.h" - -TEST(PlayerTest, frame_period) { - EXPECT_EQ(1'000'000, compute_frame_period(1)); - EXPECT_EQ(40'000, compute_frame_period(25)); - EXPECT_EQ(10'000, compute_frame_period(100)); - EXPECT_EQ(500, compute_frame_period(2000)); -} - -TEST(PlayerTest, accumulation_time) { - EXPECT_EQ(250'000, compute_accumulation_time(25, 1'000'000)); - EXPECT_EQ(4'000'000, compute_accumulation_time(400, 1'000'000)); - EXPECT_EQ(40'000, compute_accumulation_time(100, 40'000)); - EXPECT_EQ(10'000, compute_accumulation_time(25, 40'000)); - EXPECT_EQ(160'000, compute_accumulation_time(400, 40'000)); -} - -TEST(PlayerTest, sequence_start_time) { - EXPECT_EQ(Metavision::timestamp(10), compute_sequence_start_time(0, 7, 10, 0)); - EXPECT_EQ(Metavision::timestamp(10), compute_sequence_start_time(0, 7, 10, 50)); - EXPECT_EQ(Metavision::timestamp(10), compute_sequence_start_time(0, 7, 10, 100)); - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_start_time(0, 100, 100, 0)); - EXPECT_EQ(Metavision::timestamp(200), compute_sequence_start_time(0, 100, 100, 100)); - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_start_time(0, 1000, 100, 0)); - EXPECT_EQ(Metavision::timestamp(1100), compute_sequence_start_time(0, 1000, 100, 100)); - EXPECT_EQ(Metavision::timestamp(39), compute_sequence_start_time(29, 93, 10, 0)); - EXPECT_EQ(Metavision::timestamp(99), compute_sequence_start_time(29, 93, 10, 100)); -} - -TEST(PlayerTest, sequence_duration) { - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_duration(0, 100, 100, 0, 1)); - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_duration(0, 100, 100, 100, 1)); - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_duration(0, 100, 100, 0, 100)); - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_duration(0, 100, 100, 100, 100)); - EXPECT_EQ(Metavision::timestamp(200), compute_sequence_duration(0, 1000, 100, 0, 1)); - EXPECT_EQ(Metavision::timestamp(200), compute_sequence_duration(0, 1000, 100, 0, 2)); - EXPECT_EQ(Metavision::timestamp(600), compute_sequence_duration(0, 1000, 100, 0, 50)); - EXPECT_EQ(Metavision::timestamp(1000), compute_sequence_duration(0, 1000, 100, 0, 100)); - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_duration(0, 1000, 100, 100, 1)); - EXPECT_EQ(Metavision::timestamp(100), compute_sequence_duration(0, 1000, 100, 100, 100)); - EXPECT_EQ(Metavision::timestamp(60), compute_sequence_duration(29, 93, 10, 0, 100)); - EXPECT_EQ(Metavision::timestamp(10), compute_sequence_duration(29, 93, 10, 100, 100)); - EXPECT_EQ(Metavision::timestamp(200), compute_sequence_duration(0, 10000, 100, 0, 1)); - EXPECT_EQ(Metavision::timestamp(300), compute_sequence_duration(0, 10000, 100, 0, 2)); - EXPECT_EQ(Metavision::timestamp(400), compute_sequence_duration(0, 10000, 100, 0, 3)); - EXPECT_EQ(Metavision::timestamp(10000), compute_sequence_duration(0, 10000, 100, 0, 100)); -} - -TEST(PlayerTest, current_time) { - EXPECT_EQ(Metavision::timestamp(1000), compute_current_time(1000, 0, 100)); - EXPECT_EQ(Metavision::timestamp(1100), compute_current_time(1000, 1, 100)); - EXPECT_EQ(Metavision::timestamp(3700), compute_current_time(1000, 27, 100)); -} - -TEST(PlayerTest, analysis_data_fps_not_changed) { - // Given a fps of 25 (frame period of 40ms), a first time of 0ms and a last time of 1s - // When the analysis data is updated - // Then the fps should not be changed (as a frame period of 40ms still makes sense) - AnalysisData data = compute_analysis_data(0, 1'000'000, 25, 100, 0, 100, 0); - EXPECT_EQ(25, data.fps); - EXPECT_EQ(1, data.min_fps); - EXPECT_EQ(2'000, data.max_fps); -} - -TEST(PlayerTest, analysis_data_fps_min_changed) { - // Given a fps of 25 (frame period of 40ms), a first time of 0ms and a last time of 10ms - // When the analysis data is updated - // Then the fps should be changed (as a frame period of 40ms is now too big, and 10ms is the max = 100 FPS) - AnalysisData data = compute_analysis_data(0, 10'000, 25, 100, 0, 100, 0); - EXPECT_EQ(100, data.fps); - EXPECT_EQ(100, data.min_fps); - EXPECT_EQ(2'000, data.max_fps); -} - -TEST(PlayerTest, analysis_data_fps_max_changed) { - // Given a fps of 5'000 - // When the analysis data is updated - // Then the fps should be changed (as the max is 2'000) - AnalysisData data = compute_analysis_data(0, 1'000'000, 5'000, 100, 0, 100, 0); - EXPECT_EQ(2'000, data.fps); - EXPECT_EQ(1, data.min_fps); - EXPECT_EQ(2'000, data.max_fps); -} - -TEST(PlayerTest, analysis_data_accum_not_changed) { - // Given an accumulation ratio of 100, a frame period of 10ms and a starting time of 500ms - // When the analysis data is updated - // Then the accumulation ratio should not be changed (as an accumulation of 10ms still makes sense) - AnalysisData data = compute_analysis_data(0, 1'000'000, 100, 100, 50, 100, 0); - EXPECT_EQ(100, data.accumulation_ratio); - EXPECT_EQ(25, data.min_accumulation_ratio); - EXPECT_EQ(400, data.max_accumulation_ratio); -} - -TEST(PlayerTest, analysis_data_accum_changed) { - // Given an accumulation ratio of 200, a frame period of 10ms and a starting time of 10ms - // When the analysis data is updated - // Then the accumulation ratio should be changed (as an accumulation of 20ms is now too big, and 10ms is now the - // max) - AnalysisData data = compute_analysis_data(0, 1'000'000, 100, 200, 0, 100, 0); - EXPECT_EQ(100, data.accumulation_ratio); - EXPECT_EQ(25, data.min_accumulation_ratio); - EXPECT_EQ(100, data.max_accumulation_ratio); -} - -TEST(PlayerTest, analysis_data_sequence_start) { - AnalysisData data = compute_analysis_data(0, 1'000'000, 25, 100, 0, 100, 0); - EXPECT_EQ(0, data.min_sequence_start_ratio); - EXPECT_EQ(100, data.max_sequence_start_ratio); -} - -TEST(PlayerTest, analysis_data_sequence_duration) { - AnalysisData data = compute_analysis_data(0, 1'000'000, 25, 100, 0, 100, 0); - EXPECT_EQ(1, data.min_sequence_duration_ratio); - EXPECT_EQ(100, data.max_sequence_duration_ratio); -} - -TEST(PlayerTest, analysis_data_frame_id_not_changed) { - // Given coherent data - // When the analysis data is updated - // Then the frame id should not be changed - AnalysisData data = compute_analysis_data(0, 1'000'000, 25, 100, 0, 100, 360'000); - EXPECT_EQ(8, data.frame_id); -} - -TEST(PlayerTest, analysis_data_frame_id_changed) { - // Given incoherent data - // When the analysis data is updated - // Then the frame id should change to represent the same current time - Metavision::timestamp first_time_us = 0, last_time_us = 1'000'000; - AnalysisData data; - int fps, frame_period_us; - - fps = 25 * 2; - data = compute_analysis_data(0, 1'000'000, fps, 100, 0, 100, 360'000); - EXPECT_EQ(8 * 2 + 1, data.frame_id); - frame_period_us = compute_frame_period(fps); - EXPECT_EQ(360'000, - compute_current_time(compute_sequence_start_time(first_time_us, last_time_us, frame_period_us, 0), - data.frame_id, frame_period_us)); - - fps = 25 * 4; - data = compute_analysis_data(0, 1'000'000, fps, 100, 0, 100, 360'000); - EXPECT_EQ(8 * 4 + 3, data.frame_id); - frame_period_us = compute_frame_period(fps); - EXPECT_EQ(360'000, - compute_current_time(compute_sequence_start_time(first_time_us, last_time_us, frame_period_us, 0), - data.frame_id, frame_period_us)); - - fps = 25 * 8; - data = compute_analysis_data(0, 1'000'000, fps, 100, 0, 100, 360'000); - EXPECT_EQ(8 * 8 + 7, data.frame_id); - frame_period_us = compute_frame_period(fps); - EXPECT_EQ(360'000, - compute_current_time(compute_sequence_start_time(first_time_us, last_time_us, frame_period_us, 0), - data.frame_id, frame_period_us)); -} \ No newline at end of file diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt index 5fcc1a2c9..31143b904 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_sdk_get_started) -set (common_libraries MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui) +set (common_libraries MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui) add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt.install index 0a2ef6758..a4be3dbb2 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/CMakeLists.txt.install @@ -13,8 +13,8 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver ui REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream ui REQUIRED) set (sample metavision_sdk_get_started) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui) diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started.cpp b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started.cpp index 68079c119..cbed88a96 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started.cpp +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started.cpp @@ -12,7 +12,7 @@ // This code sample demonstrate how to use the Metavision C++ SDK. The goal of this sample is to create a simple event // counter and displayer by introducing some basic concepts of the Metavision SDK. -#include +#include #include #include #include @@ -76,8 +76,8 @@ int main(int argc, char *argv[]) { // to visualize the events, we will need to build frames and render them. // building frame will be done with a frame generator that will accumulate the events over time. // we need to provide it the camera resolution that we can retrieve from the camera instance - int camera_width = cam.geometry().width(); - int camera_height = cam.geometry().height(); + int camera_width = cam.geometry().get_width(); + int camera_height = cam.geometry().get_height(); // we also need to choose an accumulation time and a frame rate (here of 20ms and 50 fps) const std::uint32_t acc = 20000; diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v1.cpp b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v1.cpp index 3f4137feb..bfd9aa9ca 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v1.cpp +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v1.cpp @@ -14,7 +14,7 @@ // NOTE: this file is just here to ease the integration with the docs. The main sample is metavision_sdk_get_started.cpp // NOTE: if you modify this file, please check that the docs references are correct (line numbers) -#include +#include // main loop int main(int argc, char *argv[]) { diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v2.cpp b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v2.cpp index 6338a97af..14a637690 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v2.cpp +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v2.cpp @@ -14,7 +14,7 @@ // NOTE: this file is just here to ease the integration with the docs. The main sample is metavision_sdk_get_started.cpp // NOTE: if you modify this file, please check that the docs references are correct (line numbers) -#include +#include #include // this function will be associated to the camera callback diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v3.cpp b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v3.cpp index 58757b275..950e9719e 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v3.cpp +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v3.cpp @@ -14,7 +14,7 @@ // NOTE: this file is just here to ease the integration with the docs. The main sample is metavision_sdk_get_started.cpp // NOTE: if you modify this file, please check that the docs references are correct (line numbers) -#include +#include #include // this class will be used to analyze the events diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v4.cpp b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v4.cpp index 016f27d8f..0db5cd331 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v4.cpp +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v4.cpp @@ -12,7 +12,7 @@ // This code sample demonstrate how to use the Metavision C++ SDK. The goal of this sample is to create a simple event // counter and displayer by introducing some basic concepts of the Metavision SDK. -#include +#include #include #include #include diff --git a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v5.cpp b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v5.cpp index ebf5f074b..d44e6ec82 100644 --- a/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v5.cpp +++ b/sdk/modules/core/cpp/samples/metavision_sdk_get_started/metavision_sdk_get_started_v5.cpp @@ -12,7 +12,7 @@ // This code sample demonstrate how to use the Metavision C++ SDK. The goal of this sample is to create a simple event // counter and displayer by introducing some basic concepts of the Metavision SDK. -#include +#include #include #include #include diff --git a/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt b/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt index e29a22514..57113afde 100644 --- a/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt +++ b/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_time_surface) -set (common_libraries MetavisionSDK::driver MetavisionSDK::core MetavisionSDK::ui Boost::program_options) +set (common_libraries MetavisionSDK::stream MetavisionSDK::core MetavisionSDK::ui Boost::program_options) add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) diff --git a/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt.install b/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt.install index 8e1e155f9..12a356694 100644 --- a/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt.install +++ b/sdk/modules/core/cpp/samples/metavision_time_surface/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver ui REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream ui REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) set (sample metavision_time_surface) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver MetavisionSDK::ui Boost::program_options) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream MetavisionSDK::ui Boost::program_options) diff --git a/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp b/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp index a9155b61e..992c1e7eb 100644 --- a/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp +++ b/sdk/modules/core/cpp/samples/metavision_time_surface/metavision_time_surface.cpp @@ -15,7 +15,7 @@ // Basic utils for camera streaming #include -#include +#include #include #include @@ -77,8 +77,8 @@ int main(int argc, char *argv[]) { } // Get camera resolution - const int camera_width = camera.geometry().width(); - const int camera_height = camera.geometry().height(); + const int camera_width = camera.geometry().get_width(); + const int camera_height = camera.geometry().get_height(); // To render the frames, we create a window using the Window class of the UI // module diff --git a/sdk/modules/core/cpp/src/CMakeLists.txt b/sdk/modules/core/cpp/src/CMakeLists.txt index 6b7b511d0..52de013fa 100644 --- a/sdk/modules/core/cpp/src/CMakeLists.txt +++ b/sdk/modules/core/cpp/src/CMakeLists.txt @@ -8,22 +8,26 @@ # See the License for the specific language governing permissions and limitations under the License. target_sources(metavision_sdk_core PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/adaptive_rate_events_splitter_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/base_frame_generation_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/cd_frame_generator.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/cv_video_recorder.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/data_synchronizer_from_triggers.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/event_buffer_reslicer_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/event_frame_diff_generation_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/event_frame_histo_generation_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/fast_math_functions.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/misc.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/on_demand_frame_generation_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/periodic_frame_generation_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/rate_estimator.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/raw_event_frame_converter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/simple_displayer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/threaded_process.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/time_decay_frame_generation_algorithm.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/video_writer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/adaptive_rate_events_splitter_algorithm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/base_frame_generation_algorithm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/contrast_map_generation_algorithm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/event_buffer_reslicer_algorithm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/events_integration_algorithm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/on_demand_frame_generation_algorithm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/periodic_frame_generation_algorithm.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/algorithms/time_decay_frame_generation_algorithm.cpp + + ${CMAKE_CURRENT_SOURCE_DIR}/preprocessors/json_parser.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/preprocessors/event_preprocessor_type.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/preprocessors/tensor.cpp + + ${CMAKE_CURRENT_SOURCE_DIR}/utils/cd_frame_generator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/cv_video_recorder.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/data_synchronizer_from_triggers.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/fast_math_functions.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/misc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/rate_estimator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/raw_event_frame_converter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/threaded_process.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/utils/video_writer.cpp ) diff --git a/sdk/modules/core/cpp/src/adaptive_rate_events_splitter_algorithm.cpp b/sdk/modules/core/cpp/src/algorithms/adaptive_rate_events_splitter_algorithm.cpp similarity index 100% rename from sdk/modules/core/cpp/src/adaptive_rate_events_splitter_algorithm.cpp rename to sdk/modules/core/cpp/src/algorithms/adaptive_rate_events_splitter_algorithm.cpp diff --git a/sdk/modules/core/cpp/src/base_frame_generation_algorithm.cpp b/sdk/modules/core/cpp/src/algorithms/base_frame_generation_algorithm.cpp similarity index 100% rename from sdk/modules/core/cpp/src/base_frame_generation_algorithm.cpp rename to sdk/modules/core/cpp/src/algorithms/base_frame_generation_algorithm.cpp diff --git a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/detail/error_category_impl.h b/sdk/modules/core/cpp/src/algorithms/contrast_map_generation_algorithm.cpp similarity index 51% rename from sdk/modules/base/cpp/include/metavision/sdk/base/utils/detail/error_category_impl.h rename to sdk/modules/core/cpp/src/algorithms/contrast_map_generation_algorithm.cpp index 6956bd04b..81b50af86 100644 --- a/sdk/modules/base/cpp/include/metavision/sdk/base/utils/detail/error_category_impl.h +++ b/sdk/modules/core/cpp/src/algorithms/contrast_map_generation_algorithm.cpp @@ -9,31 +9,37 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_BASE_DETAIL_ERROR_CATEGORY_IMPL_H -#define METAVISION_SDK_BASE_DETAIL_ERROR_CATEGORY_IMPL_H - #include +#include "metavision/sdk/core/algorithms/contrast_map_generation_algorithm.h" + namespace Metavision { -inline ErrorCategory::ErrorCategory(int error_code, const std::string &name, const std::string &message) : name_(name) { - error_message_ = "\n------------------------------------------------\n" + name + "\n\n"; - std::ostringstream error_as_hex; - error_as_hex << std::hex << error_code; - error_message_ += "Error " + error_as_hex.str() + ": " + message; - error_message_ += "\n------------------------------------------------\n"; +ContrastMapGenerationAlgorithm::ContrastMapGenerationAlgorithm(unsigned int width, unsigned int height, + float contrast_on, float contrast_off) : + width_(width), + height_(height), + contrasts_{(contrast_off <= 0 ? (1 / contrast_on) : contrast_off), contrast_on}, + states_(cv::Mat_::ones(height, width)) {} + +void ContrastMapGenerationAlgorithm::generate(cv::Mat_ &contrast_map) { + std::swap(states_, contrast_map); + states_.create(height_, width_); + states_.setTo(1.f); } -inline ErrorCategory::~ErrorCategory() {} - -inline const char *ErrorCategory::name() const noexcept { - return name_.c_str(); +void ContrastMapGenerationAlgorithm::generate(cv::Mat_ &contrast_map_tonnemapped, float tonemapping_factor, + float tonemapping_bias) { + states_.convertTo(contrast_map_tonnemapped, CV_8U, tonemapping_factor, tonemapping_bias); + states_.setTo(1.f); } -inline std::string ErrorCategory::message([[maybe_unused]] int ev) const { - return error_message_; +void ContrastMapGenerationAlgorithm::reset() { + states_.setTo(1.f); } -} // namespace Metavision +void ContrastMapGenerationAlgorithm::process_event(const EventCD &e) { + states_.at(e.y, e.x) *= contrasts_[e.p]; +} -#endif // METAVISION_SDK_BASE_DETAIL_ERROR_CATEGORY_IMPL_H +} // namespace Metavision \ No newline at end of file diff --git a/sdk/modules/core/cpp/src/event_buffer_reslicer_algorithm.cpp b/sdk/modules/core/cpp/src/algorithms/event_buffer_reslicer_algorithm.cpp similarity index 100% rename from sdk/modules/core/cpp/src/event_buffer_reslicer_algorithm.cpp rename to sdk/modules/core/cpp/src/algorithms/event_buffer_reslicer_algorithm.cpp diff --git a/sdk/modules/core/cpp/src/algorithms/events_integration_algorithm.cpp b/sdk/modules/core/cpp/src/algorithms/events_integration_algorithm.cpp new file mode 100644 index 000000000..b5ee6b68f --- /dev/null +++ b/sdk/modules/core/cpp/src/algorithms/events_integration_algorithm.cpp @@ -0,0 +1,89 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/core/algorithms/events_integration_algorithm.h" +#include "metavision/sdk/core/utils/fast_math_functions.h" + +namespace Metavision { + +EventsIntegrationAlgorithm::EventsIntegrationAlgorithm(unsigned int width, unsigned int height, timestamp decay_time, + float contrast_on, float contrast_off, + int tonemapping_max_ev_count, int gaussian_blur_kernel_radius, + float diffusion_weight) : + width_(width), + height_(height), + gaussian_blur_kernel_radius_(gaussian_blur_kernel_radius), + diffusion_weight_(std::min(0.25f, std::max(0.f, diffusion_weight))), + decay_time_(decay_time), + log_contrast_{std::log(contrast_off <= 0 ? 1 / contrast_on : contrast_off), std::log(contrast_on)}, + tonemapping_factor_(std::exp(-tonemapping_max_ev_count * std::log(contrast_on))), + exp_decay_lut_{Math::init_exp_decay_lut(128)}, + states_(width * height) {} + +void EventsIntegrationAlgorithm::generate(cv::Mat &grayscale_frame) { + grayscale_frame.create(height_, width_, CV_8UC1); + uchar *pframe = grayscale_frame.ptr(); + auto *pstates = states_.data(); + for (unsigned int y = 0; y < height_; ++y) { + for (unsigned int x = 0; x < width_; ++x, ++pframe, ++pstates) { + const float decay_factor = + Math::fast_exp_decay(exp_decay_lut_, (last_t_ - pstates->last_t) / static_cast(decay_time_)); + pstates->last_t = last_t_; + pstates->logI = pstates->logI * decay_factor; + *pframe = cv::saturate_cast(255 * tonemapping_factor_ * std::exp(pstates->logI)); + } + } + if (diffusion_weight_ > 0) { + diffuse_intensities(); + } else if (gaussian_blur_kernel_radius_ > 0) { + cv::GaussianBlur(grayscale_frame, grayscale_frame, + cv::Size(2 * gaussian_blur_kernel_radius_ + 1, 2 * gaussian_blur_kernel_radius_ + 1), 0); + } +} + +void EventsIntegrationAlgorithm::reset() { + PxState s_reset{}; + std::fill(states_.begin(), states_.end(), s_reset); +} + +void EventsIntegrationAlgorithm::integrate_event(const EventCD &e) { + if (e.x >= width_ || e.y >= height_) { // e.x<0 || e.y<0 cannot happen since they are unsigned + return; + } + auto &s = states_[e.y * width_ + e.x]; + const float decay_factor = Math::fast_exp_decay(exp_decay_lut_, (e.t - s.last_t) / static_cast(decay_time_)); + s.logI = s.logI * decay_factor + log_contrast_[e.p]; + s.last_t = e.t; +} + +void EventsIntegrationAlgorithm::diffuse_intensities() { + const float stable_weight = std::max(0.f, 1.f - 4 * diffusion_weight_); + const float diffusion_weight = std::min(0.25f, diffusion_weight_); + const int stride = static_cast(width_); + auto pstates = states_.data(); + for (unsigned int y = 0; y < height_; ++y) { + for (unsigned int x = 0; x < width_; ++x, ++pstates) { + if (x == 0 || x == width_ - 1 || y == 0 || y == height_ - 1) { + continue; + } + float sum_logI = stable_weight * pstates->logI; + sum_logI += diffusion_weight * pstates[-1].logI; + sum_logI += diffusion_weight * pstates[1].logI; + sum_logI += diffusion_weight * pstates[-stride].logI; + sum_logI += diffusion_weight * pstates[stride].logI; + pstates->logI = sum_logI; + } + } +} + +} // namespace Metavision \ No newline at end of file diff --git a/sdk/modules/core/cpp/src/on_demand_frame_generation_algorithm.cpp b/sdk/modules/core/cpp/src/algorithms/on_demand_frame_generation_algorithm.cpp similarity index 100% rename from sdk/modules/core/cpp/src/on_demand_frame_generation_algorithm.cpp rename to sdk/modules/core/cpp/src/algorithms/on_demand_frame_generation_algorithm.cpp diff --git a/sdk/modules/core/cpp/src/periodic_frame_generation_algorithm.cpp b/sdk/modules/core/cpp/src/algorithms/periodic_frame_generation_algorithm.cpp similarity index 100% rename from sdk/modules/core/cpp/src/periodic_frame_generation_algorithm.cpp rename to sdk/modules/core/cpp/src/algorithms/periodic_frame_generation_algorithm.cpp diff --git a/sdk/modules/core/cpp/src/time_decay_frame_generation_algorithm.cpp b/sdk/modules/core/cpp/src/algorithms/time_decay_frame_generation_algorithm.cpp similarity index 100% rename from sdk/modules/core/cpp/src/time_decay_frame_generation_algorithm.cpp rename to sdk/modules/core/cpp/src/algorithms/time_decay_frame_generation_algorithm.cpp diff --git a/sdk/modules/core/cpp/src/event_frame_diff_generation_algorithm.cpp b/sdk/modules/core/cpp/src/event_frame_diff_generation_algorithm.cpp deleted file mode 100644 index 6c6fb4052..000000000 --- a/sdk/modules/core/cpp/src/event_frame_diff_generation_algorithm.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/core/algorithms/event_frame_diff_generation_algorithm.h" - -namespace Metavision { - -EventFrameDiffGenerationAlgorithm::EventFrameDiffGenerationAlgorithm(unsigned int width, unsigned int height, - unsigned int bit_size, bool allow_rollover, - timestamp min_generation_period_us) : - allow_rollover_(allow_rollover), - min_val_(-(1 << (bit_size - 1))), - max_val_((1 << (bit_size - 1)) - 1), - min_generation_period_us_(min_generation_period_us), - frame_(height, width, bit_size) {} - -void EventFrameDiffGenerationAlgorithm::generate(RawEventFrameDiff &frame) { - const auto &cfg = frame_.get_config(); - frame.reset(cfg.height, cfg.width, cfg.bit_size); // Prepare next accumulating frame - frame.swap(frame_); // Swap internal event frame with provided one -} - -bool EventFrameDiffGenerationAlgorithm::generate(timestamp ts_event_frame, RawEventFrameDiff &event_frame) { - if (is_ts_prev_set_ && ts_event_frame - ts_prev_ < min_generation_period_us_) - return false; - is_ts_prev_set_ = true; - ts_prev_ = ts_event_frame; - generate(event_frame); - return true; -} - -void EventFrameDiffGenerationAlgorithm::reset() { - frame_.reset(); - is_ts_prev_set_ = false; -} - -} // namespace Metavision diff --git a/sdk/modules/core/cpp/src/event_frame_histo_generation_algorithm.cpp b/sdk/modules/core/cpp/src/event_frame_histo_generation_algorithm.cpp deleted file mode 100644 index aadfdf076..000000000 --- a/sdk/modules/core/cpp/src/event_frame_histo_generation_algorithm.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/core/algorithms/event_frame_histo_generation_algorithm.h" - -namespace Metavision { - -EventFrameHistoGenerationAlgorithm::EventFrameHistoGenerationAlgorithm(unsigned width, unsigned height, - unsigned channel_bit_neg, - unsigned channel_bit_pos, bool packed, - timestamp min_generation_period_us) : - sum_max_neg_((1 << channel_bit_neg) - 1), - sum_max_pos_((1 << channel_bit_pos) - 1), - cfg_({width, height, {channel_bit_neg, channel_bit_pos}, packed}), - min_generation_period_us_(min_generation_period_us), - frame_unpacked_(height, width, channel_bit_neg, channel_bit_pos, false) {} - -void EventFrameHistoGenerationAlgorithm::generate(RawEventFrameHisto &frame) { - if (cfg_.packed) { - frame.reset(cfg_.height, cfg_.width, cfg_.channel_bit_size[0], cfg_.channel_bit_size[1], - cfg_.packed); // Prepare target frame - auto &histo_out = frame.get_data(); - auto &histo_unpacked = frame_unpacked_.get_data(); - for (unsigned int npixels = cfg_.width * cfg_.height, idx_px = 0; idx_px < npixels; ++idx_px) { - const uint8_t bitval_neg = histo_unpacked[2 * idx_px]; - const uint8_t bitval_pos = histo_unpacked[2 * idx_px + 1]; - histo_out[idx_px] = (bitval_pos << cfg_.channel_bit_size[0]) | (bitval_neg); - } - frame_unpacked_.reset(); // Prepare next accumulating frame - } else { - frame.reset(cfg_.height, cfg_.width, cfg_.channel_bit_size[0], cfg_.channel_bit_size[1], - cfg_.packed); // Prepare next accumulating frame - frame.swap(frame_unpacked_); // Swap internal event frame with provided one - } -} - -bool EventFrameHistoGenerationAlgorithm::generate(timestamp ts_event_frame, RawEventFrameHisto &event_frame) { - if (is_ts_prev_set_ && ts_event_frame - ts_prev_ < min_generation_period_us_) - return false; - is_ts_prev_set_ = true; - ts_prev_ = ts_event_frame; - generate(event_frame); - return true; -} - -void EventFrameHistoGenerationAlgorithm::reset() { - frame_unpacked_.reset(); - is_ts_prev_set_ = false; -} - -} // namespace Metavision diff --git a/sdk/modules/core/cpp/src/preprocessors/event_preprocessor_type.cpp b/sdk/modules/core/cpp/src/preprocessors/event_preprocessor_type.cpp new file mode 100644 index 000000000..12be72fe9 --- /dev/null +++ b/sdk/modules/core/cpp/src/preprocessors/event_preprocessor_type.cpp @@ -0,0 +1,34 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/base/utils/sdk_log.h" +#include "metavision/sdk/core/preprocessors/event_preprocessor_type.h" + +namespace std { + +std::istream &operator>>(std::istream &in, Metavision::EventPreprocessorType &type) { + std::string type_str; + in >> type_str; + + if (Metavision::stringToEventPreprocessorTypeMap.count(type_str) > 0) + type = Metavision::stringToEventPreprocessorTypeMap.at(type_str); + else + throw std::runtime_error(type_str + " is not a compatible event preprocessor type"); + + return in; +} + +std::ostream &operator<<(std::ostream &os, const Metavision::EventPreprocessorType &type) { + os << Metavision::eventPreprocessorTypeToStringMap.at(type); + return os; +} + +} // namespace std diff --git a/sdk/modules/core/cpp/src/preprocessors/json_parser.cpp b/sdk/modules/core/cpp/src/preprocessors/json_parser.cpp new file mode 100644 index 000000000..22539374c --- /dev/null +++ b/sdk/modules/core/cpp/src/preprocessors/json_parser.cpp @@ -0,0 +1,145 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/core/preprocessors/json_parser.h" +#include "metavision/sdk/core/preprocessors/event_preprocessor_type.h" + +namespace Metavision { + +namespace detail { + +void read_diff(const boost::property_tree::ptree &node, + std::unordered_map ¶ms_map) { + params_map["max_incr_per_pixel"] = get_element_from_ptree(node, "max_incr_per_pixel"); + params_map["clip_value_after_normalization"] = + get_element_from_ptree(node, "clip_value_after_normalization"); +} + +void read_histo(const boost::property_tree::ptree &node, + std::unordered_map ¶ms_map) { + params_map["max_incr_per_pixel"] = get_element_from_ptree(node, "max_incr_per_pixel"); + params_map["clip_value_after_normalization"] = + get_element_from_ptree(node, "clip_value_after_normalization"); + params_map["use_CHW"] = get_element_from_ptree(node, "use_CHW"); +} + +void read_event_cube(const boost::property_tree::ptree &node, + std::unordered_map ¶ms_map) { + params_map["delta_t"] = get_element_from_ptree(node, "delta_t"); + params_map["max_incr_per_pixel"] = get_element_from_ptree(node, "max_incr_per_pixel"); + params_map["clip_value_after_normalization"] = + get_element_from_ptree(node, "clip_value_after_normalization"); + params_map["num_utbins"] = get_element_from_ptree(node, "num_utbins"); + params_map["split_polarity"] = get_element_from_ptree(node, "split_polarity"); +} + +void read_time_surface(const boost::property_tree::ptree &node, + std::unordered_map ¶ms_map) { + params_map["nb_channels"] = get_element_from_ptree(node, "nb_channels"); +} + +void read_hardware_diff(const boost::property_tree::ptree &node, + std::unordered_map ¶ms_map) { + params_map["min_val"] = get_element_from_ptree(node, "min_val"); + params_map["max_val"] = get_element_from_ptree(node, "max_val"); + params_map["allow_rollover"] = get_element_from_ptree(node, "allow_rollover"); +} + +void read_hardware_histo(const boost::property_tree::ptree &node, + std::unordered_map ¶ms_map) { + params_map["neg_saturation"] = get_element_from_ptree(node, "neg_saturation"); + params_map["pos_saturation"] = get_element_from_ptree(node, "pos_saturation"); +} + +} // namespace detail + +boost::property_tree::ptree get_tree_from_file(const std::filesystem::path &file_path) { + std::stringstream file_buffer; + std::ifstream file; + + try { + file.open(file_path); + file_buffer << file.rdbuf(); + file.close(); + } catch (...) { throw std::runtime_error(std::string(" No such file: '") + file_path.string() + "'"); } + + boost::property_tree::ptree pt; + try { + boost::property_tree::read_json(file_buffer, pt); + } catch (const std::exception &e) { + throw std::runtime_error(e.what() + std::string(" reading '") + file_path.string() + "'"); + } catch (...) { throw std::runtime_error("Unknown exception thrown reading '" + file_path.string() + "'"); } + return pt; +} + +void parse_preprocessors_params( + const boost::property_tree::ptree &pt, + std::vector> &preprocess_maps) { + const auto read_parameters = [](const boost::property_tree::ptree &node, + std::unordered_map ¶ms_map) { + const EventPreprocessorType process_type = node.get_child("type").get_value(); + params_map["type"] = process_type; + switch (process_type) { + case EventPreprocessorType::DIFF: + detail::read_diff(node, params_map); + break; + case EventPreprocessorType::HISTO: + detail::read_histo(node, params_map); + break; + case EventPreprocessorType::EVENT_CUBE: + detail::read_event_cube(node, params_map); + break; + case EventPreprocessorType::TIME_SURFACE: + detail::read_time_surface(node, params_map); + break; + case EventPreprocessorType::HARDWARE_DIFF: + detail::read_hardware_diff(node, params_map); + break; + case EventPreprocessorType::HARDWARE_HISTO: + detail::read_hardware_histo(node, params_map); + break; + } + std::vector input_names; + const auto inputs_node = node.get_child("input_names"); + if (inputs_node.empty()) + throw std::runtime_error( + "No inputs provided for the current preprocessor. Provide names with the 'input_names' attribute."); + + if (inputs_node.count("") == 1) { + // If the value node has an empty key, it's a list + for (auto &name : inputs_node) + input_names.push_back(name.second.get_value()); + } else { + input_names.push_back(inputs_node.get_value()); + } + params_map["input_names"] = input_names; + }; + + if (pt.empty()) + return; + + if (pt.count("") == 1) { + // If the value node has an empty key, it's a list + for (const auto &process_node : pt) { + std::unordered_map proc; + read_parameters(process_node.second, proc); + preprocess_maps.emplace_back(proc); + } + } else { + std::unordered_map proc; + read_parameters(pt, proc); + preprocess_maps.emplace_back(proc); + } +} + +} // namespace Metavision diff --git a/sdk/modules/core/cpp/src/preprocessors/tensor.cpp b/sdk/modules/core/cpp/src/preprocessors/tensor.cpp new file mode 100644 index 000000000..e2bb9b431 --- /dev/null +++ b/sdk/modules/core/cpp/src/preprocessors/tensor.cpp @@ -0,0 +1,283 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/base/utils/sdk_log.h" +#include "metavision/sdk/core/preprocessors/tensor.h" + +namespace Metavision { + +static std::unordered_map const baseTypeToByteSizeMap{ + {BaseType::BOOL, 1}, {BaseType::UINT8, 1}, {BaseType::UINT16, 2}, {BaseType::UINT32, 4}, + {BaseType::UINT64, 8}, {BaseType::INT8, 1}, {BaseType::INT16, 2}, {BaseType::INT32, 4}, + {BaseType::INT64, 8}, {BaseType::FLOAT16, 2}, {BaseType::FLOAT32, 4}, {BaseType::FLOAT64, 8}}; + +static std::unordered_map const baseTypeToStringMap{ + {BaseType::BOOL, "BOOL"}, {BaseType::UINT8, "UINT8"}, {BaseType::UINT16, "UINT16"}, + {BaseType::UINT32, "UINT32"}, {BaseType::UINT64, "UINT64"}, {BaseType::INT8, "INT8"}, + {BaseType::INT16, "INT16"}, {BaseType::INT32, "INT32"}, {BaseType::INT64, "INT64"}, + {BaseType::FLOAT16, "FLOAT16"}, {BaseType::FLOAT32, "FLOAT32"}, {BaseType::FLOAT64, "FLOAT64"}}; + +static std::unordered_map const stringToBaseTypeMap{ + {"BOOL", BaseType::BOOL}, {"UINT8", BaseType::UINT8}, {"UINT16", BaseType::UINT16}, + {"UINT32", BaseType::UINT32}, {"UINT64", BaseType::UINT64}, {"INT8", BaseType::INT8}, + {"INT16", BaseType::INT16}, {"INT32", BaseType::INT32}, {"INT64", BaseType::INT64}, + {"FLOAT16", BaseType::FLOAT16}, {"FLOAT32", BaseType::FLOAT32}, {"FLOAT64", BaseType::FLOAT64}}; + +TensorShape::TensorShape() {} + +TensorShape::TensorShape(const std::vector &dimensions) : dimensions(dimensions) {} + +bool TensorShape::operator==(const TensorShape &other) const { + const auto &v1 = dimensions; + const auto &v2 = other.dimensions; + const size_t n = v1.size(); + const bool equal_dim = n == v2.size(); + if (!equal_dim) + return false; + + for (size_t i = 0; i < n; ++i) + if (v1[i].dim != v2[i].dim || v1[i].name != v2[i].name) + return false; + return true; +} + +bool TensorShape::operator!=(const TensorShape &other) const { + return !(*this == other); +} + +size_t TensorShape::get_nb_values() const { + int nb_values = 1; + for (auto k : dimensions) + nb_values *= k.dim; + return static_cast(std::abs(nb_values)); +} + +bool TensorShape::matches(const TensorShape &other) const { + const auto &v1 = dimensions; + const auto &v2 = other.dimensions; + const size_t n = v1.size(); + const bool equal_dim = n == v2.size(); + if (!equal_dim) + return false; + + for (size_t i = 0; i < n; ++i) + if ((v1[i].dim != v2[i].dim) && (v1[i].dim != -1) && (v2[i].dim != -1)) + return false; + + return true; +} + +bool TensorShape::is_valid() const { + for (auto k : dimensions) + if (k.dim <= 0) + return false; + return true; +} + +int get_dim(const Metavision::TensorShape &shape, const std::string &dim_name) { + for (const auto &d : shape.dimensions) { + if (d.name == dim_name) + return d.dim; + } + std::stringstream msg; + msg << "Didn't find dimension " << dim_name << " in provided tensor shape " << shape << std::endl; + throw std::runtime_error(msg.str()); +} + +void set_dim(Metavision::TensorShape &shape, const std::string &dim_name, int value) { + for (auto &d : shape.dimensions) { + if (d.name == dim_name) { + d.dim = value; + return; + } + } + std::stringstream msg; + msg << "Couldn't find dimension " << dim_name << " to set in provided tensor shape " << shape; + MV_SDK_LOG_WARNING() << msg.str(); +} + +void set_dynamic_dimensions_to_one(Metavision::TensorShape &shape) { + for (auto &d : shape.dimensions) { + if (d.dim == Dimension::kDynamic) + d.dim = 1; + } +} + +std::string to_string(const BaseType &type) { + return baseTypeToStringMap.at(type); +} + +BaseType from_string(const std::string name) { + return stringToBaseTypeMap.at(name); +} + +size_t byte_size(const BaseType &type) { + return baseTypeToByteSizeMap.at(type); +} + +Tensor::Tensor() : shape_(), type_(BaseType::BOOL), ptr_(nullptr) {} + +Tensor::Tensor(const TensorShape &shape, const BaseType &type) { + create(shape, type); +} + +Tensor::Tensor(const TensorShape &shape, const BaseType &type, std::byte *ptr, bool copy) { + create(shape, type, ptr, copy); +} + +Tensor::Tensor(const Tensor &other) : shape_(other.shape_), type_(other.type_) { + data_ = other.data_; + ptr_ = data_.data(); +} + +Tensor::Tensor(Tensor &&other) noexcept : + shape_(std::move(other.shape_)), + type_(std::move(other.type_)), + data_(std::move(other.data_)), + ptr_(std::exchange(other.ptr_, nullptr)) {} + +Tensor &Tensor::operator=(const Tensor &other) { + if (this != &other) { + shape_ = other.shape_; + type_ = other.type_; + data_ = other.data_; + ptr_ = data_.data(); + } + return *this; +} + +Tensor &Tensor::operator=(Tensor &&other) noexcept { + if (this != &other) { + shape_ = std::move(other.shape_); + type_ = std::move(other.type_); + ptr_ = std::exchange(other.ptr_, nullptr); + data_ = std::move(other.data_); + } + return *this; +} + +void Tensor::create(const TensorShape &shape, const BaseType &type, std::byte *ptr, bool copy) { + shape_ = shape; + type_ = type; + if (copy && shape_.is_valid()) { + const size_t nb_val = shape.get_nb_values(); + const size_t data_byte_length = Metavision::byte_size(type); + const size_t nb_val_byte = nb_val * data_byte_length; + data_.resize(nb_val_byte); + if (ptr) + std::copy(ptr, ptr + nb_val_byte, data_.data()); + else + memset(&data_[0], 0, nb_val_byte); + ptr_ = data_.data(); + } else { + MV_LOG_DEBUG() << "Tensor memory not allocated"; + data_.clear(); + ptr_ = ptr; + } +} + +void Tensor::create(const TensorShape &shape, const BaseType &type) { + create(shape, type, nullptr, true); +} + +TensorShape Tensor::shape() const { + return shape_; +} + +BaseType Tensor::type() const { + return type_; +} + +size_t Tensor::byte_size() const { + return shape_.get_nb_values() * baseTypeToByteSizeMap.at(type_); +} + +bool Tensor::empty() { + return shape_.get_nb_values() == 0; +} + +} // namespace Metavision + +namespace std { + +std::istream &operator>>(std::istream &in, Metavision::TensorShape &tensor_shape) { + std::string tensor_shape_str; + std::getline(in, tensor_shape_str); + + // Removes preceding and end brackets + tensor_shape_str = tensor_shape_str.substr(1, tensor_shape_str.size() - 2); + + if (!tensor_shape_str.empty()) + tensor_shape = {}; + + auto get_dimension = [](const std::string &s) { + const std::string name = s.substr(0, s.find(":")); + const int dim = stoi(s.substr(s.find(":") + 1, s.length())); + return Metavision::Dimension{name, dim}; + }; + + // Loop on the string to find dimensions 'name:dim' separated by ', ' delimiter + size_t pos = 0; + std::string token; + std::vector dims; + while ((pos = tensor_shape_str.find(", ")) != std::string::npos) { + token = tensor_shape_str.substr(0, pos); + dims.emplace_back(get_dimension(token)); + tensor_shape_str.erase(0, pos + 2); + } + + // Read last dimension + if (!tensor_shape_str.empty()) { + token = tensor_shape_str; + std::cout << token << std::endl; + dims.emplace_back(get_dimension(token)); + } + + tensor_shape = {dims}; + + return in; +} + +std::istream &operator>>(std::istream &in, Metavision::BaseType &base_type) { + std::string base_type_str; + in >> base_type_str; + + if (Metavision::stringToBaseTypeMap.count(base_type_str) == 0) + throw std::runtime_error("Unknown BaseType " + base_type_str); + + base_type = Metavision::stringToBaseTypeMap.at(base_type_str); + + return in; +} + +std::ostream &operator<<(std::ostream &os, const Metavision::TensorShape &tensor_shape) { + std::ostringstream oss; + oss << "["; + const auto &v = tensor_shape.dimensions; + for (size_t i = 0; i + 1 < v.size(); ++i) + oss << v[i].name << ":" << std::to_string(v[i].dim) << ", "; + if (v.size() > 0) + oss << v.back().name << ":" << std::to_string(v.back().dim); + oss << "]"; + os << oss.str(); + return os; +} + +std::ostream &operator<<(std::ostream &os, const Metavision::BaseType &tensor_type) { + os << Metavision::baseTypeToStringMap.at(tensor_type); + return os; +} + +} // namespace std diff --git a/sdk/modules/core/cpp/src/simple_displayer.cpp b/sdk/modules/core/cpp/src/simple_displayer.cpp deleted file mode 100644 index 354092051..000000000 --- a/sdk/modules/core/cpp/src/simple_displayer.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/core/utils/simple_displayer.h" - -namespace Metavision { -SimpleDisplayer::SimpleDisplayer(const std::string window_name, int fps) : window_name_(window_name) { - wait_time_ms_ = 1000 / fps; - on_key_pressed_cb_ = [](int) {}; -} - -/// @brief Quits the display -void SimpleDisplayer::stop() { - std::lock_guard lock(img_mutex_); - should_stop_ = true; - - started_cond_.notify_all(); -} - -/// @brief Updates current frame by swap -/// @param frame Frame to swap -void SimpleDisplayer::swap_frame(cv::Mat &frame) { - std::lock_guard lock(img_mutex_); - std::swap(frame, middle_img_); - updated_ = true; - - if (!started_) { - started_ = true; - started_cond_.notify_all(); - } -} - -/// @brief Updates current frame by copy -/// @param frame Frame to copy -void SimpleDisplayer::copy_frame(const cv::Mat &frame) { - std::lock_guard lock(img_mutex_); - frame.copyTo(middle_img_); - updated_ = true; - - if (!started_) { - started_ = true; - started_cond_.notify_all(); - } -} - -/// @brief Callback called when the display is exited -void SimpleDisplayer::set_on_key_pressed_cb(const OnKeyPressedCb &on_key_pressed_cb) { - on_key_pressed_cb_ = on_key_pressed_cb; -} - -/// @brief Runs displayer. Should be called in the main thread -void SimpleDisplayer::run() { - { - // Wait until we receive some data - std::unique_lock lock(img_mutex_); - started_cond_.wait(lock, [this]() { return started_ || should_stop_; }); - if (should_stop_) - return; - } - - cv::namedWindow(window_name_, cv::WINDOW_NORMAL); - - while (!should_stop_) { - { - std::lock_guard lock(img_mutex_); - if (updated_) { - updated_ = false; - std::swap(front_img_, middle_img_); - } - } - - cv::imshow(window_name_, front_img_); - - int key = cv::waitKey(wait_time_ms_); - on_key_pressed_cb_(key); - } -} - -} // namespace Metavision diff --git a/sdk/modules/core/cpp/src/cd_frame_generator.cpp b/sdk/modules/core/cpp/src/utils/cd_frame_generator.cpp similarity index 100% rename from sdk/modules/core/cpp/src/cd_frame_generator.cpp rename to sdk/modules/core/cpp/src/utils/cd_frame_generator.cpp diff --git a/sdk/modules/core/cpp/src/cv_video_recorder.cpp b/sdk/modules/core/cpp/src/utils/cv_video_recorder.cpp similarity index 76% rename from sdk/modules/core/cpp/src/cv_video_recorder.cpp rename to sdk/modules/core/cpp/src/utils/cv_video_recorder.cpp index 117793278..9f8ccbb27 100644 --- a/sdk/modules/core/cpp/src/cv_video_recorder.cpp +++ b/sdk/modules/core/cpp/src/utils/cv_video_recorder.cpp @@ -12,25 +12,25 @@ #include #include #include -#include +#include #include "metavision/sdk/core/utils/cv_video_recorder.h" namespace Metavision { -CvVideoRecorder::CvVideoRecorder(const std::string &output_video_file, const int fourcc, const uint32_t fps, +CvVideoRecorder::CvVideoRecorder(const std::filesystem::path &output_video_file, const int fourcc, const uint32_t fps, const cv::Size &size, bool colored) : - writer_(output_video_file, fourcc, fps, size, colored), data_to_write_pool_(DataPool::make_bounded()) { + writer_(output_video_file.string(), fourcc, fps, size, colored), data_to_write_pool_(DataPool::make_bounded()) { if (!writer_.isOpened()) { - std::string message = "'" + output_video_file + "' is not writable. "; - auto p = boost::filesystem::path(output_video_file); - if (p.has_parent_path() && !boost::filesystem::exists(p)) { - message += "The parent directory '" + p.string() + "' does not exist."; + std::stringstream message; + message << "'" << output_video_file << "' is not writable. "; + if (output_video_file.has_parent_path() && !std::filesystem::exists(output_video_file)) { + message << "The parent directory '" << output_video_file << "' does not exist."; } else { - message += "Check the output directory write permission."; + message << "Check the output directory write permission."; } - throw std::runtime_error(message); + throw std::runtime_error(message.str()); } } diff --git a/sdk/modules/core/cpp/src/data_synchronizer_from_triggers.cpp b/sdk/modules/core/cpp/src/utils/data_synchronizer_from_triggers.cpp similarity index 100% rename from sdk/modules/core/cpp/src/data_synchronizer_from_triggers.cpp rename to sdk/modules/core/cpp/src/utils/data_synchronizer_from_triggers.cpp diff --git a/sdk/modules/core/cpp/src/fast_math_functions.cpp b/sdk/modules/core/cpp/src/utils/fast_math_functions.cpp similarity index 100% rename from sdk/modules/core/cpp/src/fast_math_functions.cpp rename to sdk/modules/core/cpp/src/utils/fast_math_functions.cpp diff --git a/sdk/modules/core/cpp/src/misc.cpp b/sdk/modules/core/cpp/src/utils/misc.cpp similarity index 100% rename from sdk/modules/core/cpp/src/misc.cpp rename to sdk/modules/core/cpp/src/utils/misc.cpp diff --git a/sdk/modules/core/cpp/src/rate_estimator.cpp b/sdk/modules/core/cpp/src/utils/rate_estimator.cpp similarity index 100% rename from sdk/modules/core/cpp/src/rate_estimator.cpp rename to sdk/modules/core/cpp/src/utils/rate_estimator.cpp diff --git a/sdk/modules/core/cpp/src/raw_event_frame_converter.cpp b/sdk/modules/core/cpp/src/utils/raw_event_frame_converter.cpp similarity index 100% rename from sdk/modules/core/cpp/src/raw_event_frame_converter.cpp rename to sdk/modules/core/cpp/src/utils/raw_event_frame_converter.cpp diff --git a/sdk/modules/core/cpp/src/threaded_process.cpp b/sdk/modules/core/cpp/src/utils/threaded_process.cpp similarity index 100% rename from sdk/modules/core/cpp/src/threaded_process.cpp rename to sdk/modules/core/cpp/src/utils/threaded_process.cpp diff --git a/sdk/modules/core/cpp/src/video_writer.cpp b/sdk/modules/core/cpp/src/utils/video_writer.cpp similarity index 100% rename from sdk/modules/core/cpp/src/video_writer.cpp rename to sdk/modules/core/cpp/src/utils/video_writer.cpp diff --git a/sdk/modules/core/cpp/tests/CMakeLists.txt b/sdk/modules/core/cpp/tests/CMakeLists.txt index 7970ebcb8..e1f306544 100644 --- a/sdk/modules/core/cpp/tests/CMakeLists.txt +++ b/sdk/modules/core/cpp/tests/CMakeLists.txt @@ -11,22 +11,22 @@ set(metavision_sdk_core_tests_srcs ${CMAKE_CURRENT_SOURCE_DIR}/async_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/base_frame_generation_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cd_frame_generator_gtest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/concurrent_queue_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/counter_map_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cv_color_map_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/data_synchronizer_from_triggers_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/event_buffer_reslicer_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/event_frame_diff_generation_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/event_frame_histo_generation_algorithm_gtest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/event_preprocessor_gtest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/event_rescaler_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/flip_x_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/flip_y_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/frame_composer_gtest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/frame_composition_stage_gtest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/frame_generation_stage_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/generic_producer_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/index_generator_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/on_demand_frame_generation_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/periodic_frame_generation_algorithm_gtest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/pipeline_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/polarity_filter_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rate_estimator_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ring_gtest.cpp @@ -34,7 +34,6 @@ set(metavision_sdk_core_tests_srcs ${CMAKE_CURRENT_SOURCE_DIR}/rolling_event_buffer_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/shared_buffer_queue_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/shared_cd_events_buffer_producer_algorithm_gtest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/stage_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/stream_logger_algorithm_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/threaded_process_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/time_decay_frame_generation_algorithm_gtest.cpp diff --git a/sdk/modules/core/cpp/tests/base_frame_generation_algorithm_gtest.cpp b/sdk/modules/core/cpp/tests/base_frame_generation_algorithm_gtest.cpp index 253bdfb3e..b294d9d5b 100644 --- a/sdk/modules/core/cpp/tests/base_frame_generation_algorithm_gtest.cpp +++ b/sdk/modules/core/cpp/tests/base_frame_generation_algorithm_gtest.cpp @@ -106,3 +106,33 @@ TEST(BaseFrameGenerationAlgorithm_GTest, static_frame_generation_with_accumulati ASSERT_EQ(expected_frame.size(), frame.size()); ASSERT_TRUE(std::equal(expected_frame.begin(), expected_frame.end(), frame.begin())); } + +TEST(BaseFrameGenerationAlgorithm_GTest, static_frame_generation_no_accumulation_time_and_alpha) { + const int sensor_width = 10; + const int sensor_height = 10; + const timestamp accumulation_time_us = 10000; + cv::Mat frame(sensor_height, sensor_width, CV_8UC4); + + // GIVEN the following events + std::vector events{{EventCD{5, 1, 0, accumulation_time_us - 30}, + EventCD{5, 5, 0, accumulation_time_us - 10}, EventCD{5, 8, 1, accumulation_time_us}}}; + + // WHEN we generate a frame from the input events + BaseFrameGenerationAlgorithm::generate_frame_from_events(events.cbegin(), events.cend(), frame, 0, + Metavision::ColorPalette::Dark, + BaseFrameGenerationAlgorithm::Parameters::BGRA); + + // THEN we generate a frame that holds all events + auto bg_color = BaseFrameGenerationAlgorithm::bg_color_default(); + auto off_color = BaseFrameGenerationAlgorithm::off_color_default(); + auto on_color = BaseFrameGenerationAlgorithm::on_color_default(); + cv::Mat expected_frame(sensor_height, sensor_width, CV_8UC4, cv::Vec4b(bg_color[0], bg_color[1], bg_color[2], 255)); + expected_frame.at(1, 5) = cv::Vec4b(off_color[0], off_color[1], off_color[2], 255); + expected_frame.at(8, 5) = cv::Vec4b(on_color[0], on_color[1], on_color[2], 255); + expected_frame.at(5, 5) = cv::Vec4b(off_color[0], off_color[1], off_color[2], 255); + + ASSERT_EQ(CV_8UC4, frame.type()); + ASSERT_EQ(expected_frame.size(), frame.size()); + ASSERT_TRUE( + std::equal(expected_frame.begin(), expected_frame.end(), frame.begin())); +} \ No newline at end of file diff --git a/sdk/modules/core/cpp/tests/concurrent_queue_gtest.cpp b/sdk/modules/core/cpp/tests/concurrent_queue_gtest.cpp new file mode 100644 index 000000000..2b5287dbe --- /dev/null +++ b/sdk/modules/core/cpp/tests/concurrent_queue_gtest.cpp @@ -0,0 +1,118 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/core/utils/concurrent_queue.h" + +TEST(ConcurrentQueueTest, get_front_empty) { + // GIVEN an empty concurrent queue + Metavision::ConcurrentQueue queue; + + // WHEN we try to get the front element in a non-blocking way + // THEN the function returns a non-valid element + ASSERT_EQ(queue.pop_front(false), std::nullopt); + + // WHEN we try to get the front element (from a separate thread) + std::packaged_task()> task([&queue]() { return queue.pop_front(); }); + auto future_result = task.get_future(); + std::thread t(std::move(task)); + + // (make sure the thread is running) + while (!t.joinable()) + std::this_thread::yield(); + + // (wait a bit to make sure the thread is blocked on the get_front_or_wait call) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // THEN the function blocks + ASSERT_TRUE(t.joinable()); + + // WHEN we close the queue + queue.close(); + + // THEN the function returns a non-valid element + ASSERT_FALSE(future_result.get()); + + t.join(); +} + +TEST(ConcurrentQueueTest, get_front_non_empty) { + // GIVEN a concurrent queue with one element + Metavision::ConcurrentQueue queue; + queue.emplace(1); + + // WHEN we try to get the front element + // THEN the function returns a valid element and the front element is the one we added + const auto front = queue.pop_front(); + ASSERT_TRUE(*front); + ASSERT_EQ(1, *front); +} + +TEST(ConcurrentQueueTest, push_when_opened) { + // GIVEN an opened concurrent queue + Metavision::ConcurrentQueue queue; + queue.open(); + + // WHEN we try to push an element + // THEN the function returns true + ASSERT_TRUE(queue.emplace(1)); +} + +TEST(ConcurrentQueueTest, push_when_closed) { + // GIVEN a closed concurrent queue + Metavision::ConcurrentQueue queue; + queue.close(); + + // WHEN we try to push an element + // THEN the function returns false + ASSERT_FALSE(queue.emplace(1)); +} + +TEST(ConcurrentQueueTest, push_when_opened_and_full) { + // GIVEN a full opened concurrent queue + Metavision::ConcurrentQueue queue(1); + queue.open(); + queue.emplace(1); + + // WHEN we try to push a new element (from a separate thread) + std::packaged_task task([&queue]() { return queue.emplace(2); }); + auto future_result = task.get_future(); + std::thread t(std::move(task)); + + // (make sure the thread is running) + while (!t.joinable()) + std::this_thread::yield(); + + // (wait a bit to make sure the thread is blocked on the emplace call) + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + // THEN the function blocks + ASSERT_TRUE(t.joinable()); + + // WHEN we pop an element from the queue + const auto front = queue.pop_front(); + + // THEN + // - the popped element is valid + // - the emplace call succeeded + ASSERT_TRUE(front); + ASSERT_EQ(1, *front); + ASSERT_TRUE(future_result.get()); + + t.join(); + + // WHEN we try to push a new element in a non-blocking way + // THEN the function returns false + ASSERT_FALSE(queue.emplace(3, false)); +} \ No newline at end of file diff --git a/sdk/modules/core/cpp/tests/event_frame_diff_generation_algorithm_gtest.cpp b/sdk/modules/core/cpp/tests/event_frame_diff_generation_algorithm_gtest.cpp index 35fa5f28c..8a85729be 100644 --- a/sdk/modules/core/cpp/tests/event_frame_diff_generation_algorithm_gtest.cpp +++ b/sdk/modules/core/cpp/tests/event_frame_diff_generation_algorithm_gtest.cpp @@ -16,6 +16,7 @@ #include "metavision/sdk/core/algorithms/event_frame_diff_generation_algorithm.h" using namespace Metavision; +using InputIt = std::vector::const_iterator; TEST(EventFrameDiffGenerationAlgorithm_GTest, nominal) { // GIVEN a 3x2 toy event stream @@ -24,7 +25,7 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, nominal) { EventCD(0, 0, 1, 2), EventCD(2, 0, 1, 2), EventCD(0, 1, 1, 2), EventCD(2, 1, 0, 2), EventCD(0, 0, 0, 3), EventCD(2, 0, 1, 3), EventCD(0, 1, 0, 3), EventCD(2, 1, 0, 3)}; // GIVEN a EventFrameDiffGenerationAlgorithm instance - EventFrameDiffGenerationAlgorithm diff_generator(width, height); + EventFrameDiffGenerationAlgorithm diff_generator(width, height); // WHEN we process the event stream and generate the event frame diff_generator.process_events(events.cbegin(), events.cend()); @@ -56,7 +57,7 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, many_negatives_no_rollover) { // GIVEN a EventFrameDiffGenerationAlgorithm instance const unsigned int bit_size = 8; const bool allow_rollover = false; - EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); + EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); // WHEN we process the event stream and generate the event frame diff_generator.process_events(events.cbegin(), events.cend()); @@ -83,7 +84,7 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, many_negatives_with_rollover) { // GIVEN a EventFrameDiffGenerationAlgorithm instance const unsigned int bit_size = 8; const bool allow_rollover = true; - EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); + EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); // WHEN we process the event stream and generate the event frame diff_generator.process_events(events.cbegin(), events.cend()); @@ -106,7 +107,7 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, many_negatives_no_rollover_low_bit // GIVEN a EventFrameDiffGenerationAlgorithm instance const unsigned int bit_size = 3; const bool allow_rollover = false; - EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); + EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); // WHEN we process the event stream and generate the event frame diff_generator.process_events(events.cbegin(), events.cend()); @@ -133,7 +134,7 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, many_positives_no_rollover) { // GIVEN a EventFrameDiffGenerationAlgorithm instance const unsigned int bit_size = 8; const bool allow_rollover = false; - EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); + EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); // WHEN we process the event stream and generate the event frame diff_generator.process_events(events.cbegin(), events.cend()); @@ -160,7 +161,7 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, many_positives_with_rollover) { // GIVEN a EventFrameDiffGenerationAlgorithm instance const unsigned int bit_size = 8; const bool allow_rollover = true; - EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); + EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); // WHEN we process the event stream and generate the event frame diff_generator.process_events(events.cbegin(), events.cend()); @@ -183,7 +184,7 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, many_positives_no_rollover_low_bit // GIVEN a EventFrameDiffGenerationAlgorithm instance const unsigned int bit_size = 3; const bool allow_rollover = false; - EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); + EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover); // WHEN we process the event stream and generate the event frame diff_generator.process_events(events.cbegin(), events.cend()); @@ -207,8 +208,8 @@ TEST(EventFrameDiffGenerationAlgorithm_GTest, lowerbound_generation_period) { const unsigned int bit_size = 8; const bool allow_rollover = false; const timestamp lowerbound_generation_period_us = 10; - EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover, - lowerbound_generation_period_us); + EventFrameDiffGenerationAlgorithm diff_generator(width, height, bit_size, allow_rollover, + lowerbound_generation_period_us); // WHEN we process the event stream // THEN we can have feedback if the generation frequency is too high diff --git a/sdk/modules/core/cpp/tests/event_frame_histo_generation_algorithm_gtest.cpp b/sdk/modules/core/cpp/tests/event_frame_histo_generation_algorithm_gtest.cpp index 978022ed3..d24a6bb3a 100644 --- a/sdk/modules/core/cpp/tests/event_frame_histo_generation_algorithm_gtest.cpp +++ b/sdk/modules/core/cpp/tests/event_frame_histo_generation_algorithm_gtest.cpp @@ -13,10 +13,12 @@ #include #include +#include "metavision/sdk/base/events/event_cd.h" #include "metavision/sdk/core/algorithms/event_frame_histo_generation_algorithm.h" #include "metavision/sdk/core/utils/raw_event_frame_converter.h" using namespace Metavision; +using InputIt = std::vector::const_iterator; TEST(EventFrameHistoGenerationAlgorithm_GTest, nominal) { // GIVEN a 3x2 toy event stream @@ -27,7 +29,7 @@ TEST(EventFrameHistoGenerationAlgorithm_GTest, nominal) { // GIVEN a EventFrameHistoGenerationAlgorithm instance const unsigned int bit_size_neg = 4, bit_size_pos = 4; const bool packed = false; - EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); + EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); // WHEN we process the event stream and generate the event frame histo_generator.process_events(events.cbegin(), events.cend()); @@ -65,7 +67,7 @@ TEST(EventFrameHistoGenerationAlgorithm_GTest, saturation) { // GIVEN a EventFrameHistoGenerationAlgorithm instance const unsigned int bit_size_neg = 4, bit_size_pos = 4; const bool packed = false; - EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); + EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); // WHEN we process the event stream and generate the event frame histo_generator.process_events(events.cbegin(), events.cend()); @@ -88,7 +90,7 @@ TEST(EventFrameHistoGenerationAlgorithm_GTest, packed) { // GIVEN a EventFrameHistoGenerationAlgorithm instance const unsigned int bit_size_neg = 4, bit_size_pos = 4; const bool packed = true; - EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); + EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); // WHEN we process the event stream and generate the event frame histo_generator.process_events(events.cbegin(), events.cend()); @@ -115,7 +117,7 @@ TEST(EventFrameHistoGenerationAlgorithm_GTest, compatibility_with_RawEventFrameC // GIVEN a EventFrameHistoGenerationAlgorithm instance const unsigned int bit_size_neg = 4, bit_size_pos = 4; const bool packed = true; - EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); + EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); // GIVEN a RawEventFrameConverter instance RawEventFrameConverter converter(2, 3, 2, HistogramFormat::HWC); @@ -155,7 +157,7 @@ TEST(EventFrameHistoGenerationAlgorithm_GTest, saturation_low_bit_sizes) { // GIVEN a EventFrameHistoGenerationAlgorithm instance const unsigned int bit_size_neg = 2, bit_size_pos = 2; const bool packed = false; - EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); + EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed); // WHEN we process the event stream and generate the event frame histo_generator.process_events(events.cbegin(), events.cend()); @@ -180,8 +182,8 @@ TEST(EventFrameHistoGenerationAlgorithm_GTest, lowerbound_generation_period) { const unsigned int bit_size_neg = 4, bit_size_pos = 4; const bool packed = false; const timestamp lowerbound_generation_period_us = 10; - EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed, - lowerbound_generation_period_us); + EventFrameHistoGenerationAlgorithm histo_generator(width, height, bit_size_neg, bit_size_pos, packed, + lowerbound_generation_period_us); // WHEN we process the event stream // THEN we can have feedback if the generation frequency is too high diff --git a/sdk/modules/core/cpp/tests/event_preprocessor_gtest.cpp b/sdk/modules/core/cpp/tests/event_preprocessor_gtest.cpp new file mode 100644 index 000000000..04a5df33f --- /dev/null +++ b/sdk/modules/core/cpp/tests/event_preprocessor_gtest.cpp @@ -0,0 +1,63 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/base/utils/timestamp.h" +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" + +#include "metavision/sdk/core/preprocessors/diff_processor.h" +#include "metavision/sdk/core/preprocessors/event_cube_processor.h" +#include "metavision/sdk/core/preprocessors/hardware_diff_processor.h" +#include "metavision/sdk/core/preprocessors/hardware_histo_processor.h" +#include "metavision/sdk/core/preprocessors/histo_processor.h" +#include "metavision/sdk/core/preprocessors/time_surface_processor.h" + +using EventCD = Metavision::EventCD; + +class EventPreprocessor_GTest : public ::testing::Test { +public: + EventPreprocessor_GTest() {} + + virtual ~EventPreprocessor_GTest() {} + +protected: + virtual void SetUp() override {} + + virtual void TearDown() override {} +}; + +TEST_F(EventPreprocessor_GTest, invalid_arguments) { + // clip_value_after_normalization = 0 + ASSERT_THROW(new Metavision::HistoProcessor(480, 240, 5.f, 0.f), std::invalid_argument); + // event width = -1 + ASSERT_THROW(new Metavision::HistoProcessor(-1, 240, 5.f, 1.f), std::invalid_argument); + // event height = -1 + ASSERT_THROW(new Metavision::HistoProcessor(480, -1, 5.f, 1.f), std::invalid_argument); +} + +TEST_F(EventPreprocessor_GTest, valid_arguments) { + // check that the processing can be instantiated + std::unique_ptr> processing( + new Metavision::HistoProcessor(240, 120, 5.f, 1.f)); + EXPECT_TRUE(processing); + processing.reset(new Metavision::DiffProcessor(240, 120, 5.f, 1.f)); + EXPECT_TRUE(processing); + processing.reset(new Metavision::EventCubeProcessor(240, 120, 60, 5, true, 255.f, 1.f)); + EXPECT_TRUE(processing); + processing.reset(new Metavision::HardwareDiffProcessor(120, 100, -128, 127, true)); + EXPECT_TRUE(processing); + processing.reset(new Metavision::HardwareHistoProcessor(120, 100, 255, 255)); + EXPECT_TRUE(processing); + processing.reset(new Metavision::TimeSurfaceProcessor(120, 100)); + EXPECT_TRUE(processing); +} diff --git a/sdk/modules/core/cpp/tests/event_rescaler_algorithm_gtest.cpp b/sdk/modules/core/cpp/tests/event_rescaler_algorithm_gtest.cpp new file mode 100644 index 000000000..92b8f29ef --- /dev/null +++ b/sdk/modules/core/cpp/tests/event_rescaler_algorithm_gtest.cpp @@ -0,0 +1,62 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/core/algorithms/event_rescaler_algorithm.h" +#include "metavision/sdk/base/events/event2d.h" + +using Event2d = Metavision::Event2d; + +TEST(EventRescalerAlgorithm_GTest, constructor_valid_parameters) { + // GIVEN correct input scales + const float scale_width = 0.5f, scale_height = 0.5f; + + // WHEN instantiating the algorithm + // THEN no error is thrown + ASSERT_NO_THROW(Metavision::EventRescalerAlgorithm algo(scale_width, scale_height)); +} + +TEST(EventRescalerAlgorithm_GTest, constructor_invalid_parameters) { + // GIVEN incorrect input scales + float scale_width = -0.5f, scale_height = 0.5f; + + // WHEN instantiating the algorithm + // THEN an error is thrown + EXPECT_THROW(Metavision::EventRescalerAlgorithm algo(scale_width, scale_height), std::runtime_error); + + // GIVEN incorrect input scales + scale_width = 0.5f; + scale_height = 0.f; + + // WHEN instantiating the algorithm + // THEN an error is thrown + EXPECT_THROW(Metavision::EventRescalerAlgorithm algo(scale_width, scale_height), std::runtime_error); +} + +TEST(EventRescalerAlgorithm_GTest, process_events) { + // GIVEN an instance of rescaler + const float scale_width = 0.5f, scale_height = 0.5f; + Metavision::EventRescalerAlgorithm algo(scale_width, scale_height); + + // WHEN processing an input vector of events + std::vector events{Event2d(0, 0, 0, 0), Event2d(9, 10, 1, 10)}; + std::vector output_events; + algo.process_events(events.cbegin(), events.cend(), std::back_inserter(output_events)); + + // THEN the produced events are correct + ASSERT_TRUE(output_events.size() == events.size()); + ASSERT_TRUE(output_events[0].x == 0 && output_events[0].y == 0 && output_events[0].p == 0 && + output_events[0].t == 0); + ASSERT_TRUE(output_events[1].x == 4 && output_events[1].y == 5 && output_events[1].p == 1 && + output_events[1].t == 10); +} diff --git a/sdk/modules/core/cpp/tests/frame_composition_stage_gtest.cpp b/sdk/modules/core/cpp/tests/frame_composition_stage_gtest.cpp deleted file mode 100644 index 81c12dfca..000000000 --- a/sdk/modules/core/cpp/tests/frame_composition_stage_gtest.cpp +++ /dev/null @@ -1,428 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/core/pipeline/pipeline.h" -#include "metavision/sdk/core/pipeline/frame_composition_stage.h" - -using namespace Metavision; - -using FramePool = SharedObjectPool; -using FramePtr = FramePool::ptr_type; -using FrameData = std::pair; - -namespace { - -/// @brief Structure defining a colored dot in an image -struct Dot { - Dot(){}; - Dot(int x, int y, const cv::Vec3b &color) : x_(x), y_(y), color_(color) {} - - int x_, y_; - cv::Vec3b color_; -}; - -class FrameCompositionStageTest : public ::testing::Test { -protected: - virtual void SetUp() { - dots.reserve(10); - img_ptrs.reserve(10); - for (size_t i = 0; i < 10; i++) { - dots.emplace_back(Dot(i, 10 - i, cv::Vec3b(3 * i, 255 - 4 * i, 25 * i))); - img_ptrs.emplace_back(get_new_dot_img(width, height, dots.back())); - } - } - - virtual void TearDown() {} - - /// @brief Generates new image with a single colored dot on a gray background - FramePtr get_new_dot_img(int width, int height, const Dot &dot) { - auto img_ptr = pool.acquire(); - img_ptr->create(height, width, CV_8UC3); - img_ptr->setTo(bg_color); - img_ptr->at(dot.y_, dot.x_) = dot.color_; - return img_ptr; - } - - /// @brief Generates the horizontal concatenation of two images with a single colored dot on a gray background - FramePtr hconcat_dot_imgs(int width_left, int width_right, int height, const Dot &left_dot, const Dot &right_dot) { - auto img_ptr = pool.acquire(); - img_ptr->create(height, width_left + width_right, CV_8UC3); - img_ptr->setTo(bg_color); - img_ptr->at(left_dot.y_, left_dot.x_) = left_dot.color_; - img_ptr->at(right_dot.y_, width_left + right_dot.x_) = right_dot.color_; - return img_ptr; - } - - const int width = 10; - const int height = 15; - - std::vector dots; - std::vector img_ptrs; - FramePool pool; - cv::Vec3b bg_color = cv::Vec3b::all(128); -}; - -struct MockProducingStage : public BaseStage { - MockProducingStage(const std::vector &fs) : frames(fs), step(0) { - set_starting_callback([this] { - thread = std::thread([this] { - while (true) { - if (stopped) - break; - if (step < frames.size()) { - produce(frames[step++]); - } else { - break; - } - } - if (!stopped) - complete(); - }); - }); - set_stopping_callback([this] { - stopped = true; - if (thread.joinable()) { - thread.join(); - } - }); - } - - std::thread thread; - std::atomic stopped{false}; - std::vector frames; - size_t step; -}; - -struct MockConsumingStage : public BaseStage { - MockConsumingStage(std::vector &fs) : frames(fs) { - set_consuming_callback([this](const boost::any &data) { - try { - frames.emplace_back(boost::any_cast(data)); - } catch (boost::bad_any_cast &) {} - }); - } - std::vector &frames; -}; -} // namespace - -TEST_F(FrameCompositionStageTest, basic_sync) { - /// GIVEN a basic configuration with two synchronous left and right frame streams. - // - // Left : v0 v2 v - // Time : ---0--------1e5--------2e5--------3e5--- - // Right: ^1 ^3 ^ - // - // (The number besides ^ or v corresponds to the index of the test image. - // If there is none, it means the image is a nullptr) - - std::vector frames_left, frames_right; - frames_left.push_back(std::make_pair(1e5 - 10, img_ptrs[0])); - frames_right.push_back(std::make_pair(1e5 - 10, img_ptrs[1])); - - frames_left.push_back(std::make_pair(1e5 + 1, img_ptrs[2])); - frames_right.push_back(std::make_pair(1e5 + 1, img_ptrs[3])); - - /// WHEN we run the pipeline - std::vector full_frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(frames_left)); - auto &s2 = p.add_stage(std::make_unique(frames_right)); - auto &s3 = p.add_stage(std::make_unique(10)); // 10 FPS - auto &s4 = p.add_stage(std::make_unique(full_frames), s3); - s3.add_previous_frame_stage(s1, 0, 0, width, height); - s3.add_previous_frame_stage(s2, width, 0, width, height); - p.run(); - - /// THEN we get the expected composed images - std::vector full_frames_ref; - FramePtr first_ref_ptr = hconcat_dot_imgs(width, width, height, dots[0], dots[1]); - full_frames_ref.push_back(std::make_pair(1e5, first_ref_ptr)); - - FramePtr second_ref_ptr = hconcat_dot_imgs(width, width, height, dots[2], dots[3]); - full_frames_ref.push_back(std::make_pair(2e5, second_ref_ptr)); - - // Check the two first images - EXPECT_EQ(size_t(2), full_frames.size()); - for (size_t i = 0; i < 2; i++) { - EXPECT_EQ(full_frames_ref[i].first, full_frames[i].first); - ASSERT_EQ(full_frames_ref[i].second->size(), full_frames[i].second->size()); - EXPECT_GT(1e-6, cv::norm(*full_frames[i].second - *full_frames_ref[i].second)); - } -} - -TEST_F(FrameCompositionStageTest, basic_overwrite_and_sync) { - /// GIVEN two synchronous left and right frame streams, with an output frequency - /// larger than the display frequency. - // - // Left : v0 v2 v4 v - // Time : ---0--------1e5--------2e5--------3e5--- - // Right: ^1 ^3 ^5 ^ - // - // (The number besides ^ or v corresponds to the index of the test image. - // If there is none, it means the image is a nullptr) - - std::vector frames_left, frames_right; - frames_left.push_back(std::make_pair(1e5 - 100, img_ptrs[0])); - frames_right.push_back(std::make_pair(1e5 - 100, img_ptrs[1])); - frames_left.push_back(std::make_pair(1e5 - 10, img_ptrs[2])); - frames_right.push_back(std::make_pair(1e5 - 10, img_ptrs[3])); - - frames_left.push_back(std::make_pair(1e5 + 10, img_ptrs[4])); - frames_right.push_back(std::make_pair(1e5 + 10, img_ptrs[5])); - - /// WHEN we run the pipeline - std::vector full_frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(frames_left)); - auto &s2 = p.add_stage(std::make_unique(frames_right)); - auto &s3 = p.add_stage(std::make_unique(10)); // 10 FPS - auto &s4 = p.add_stage(std::make_unique(full_frames), s3); - s3.add_previous_frame_stage(s1, 0, 0, width, height); - s3.add_previous_frame_stage(s2, width, 0, width, height); - p.run(); - - /// THEN we get the expected composed images - std::vector full_frames_ref; - FramePtr first_ref_ptr = hconcat_dot_imgs(width, width, height, dots[2], dots[3]); - full_frames_ref.push_back(std::make_pair(1e5, first_ref_ptr)); - - FramePtr second_ref_ptr = hconcat_dot_imgs(width, width, height, dots[4], dots[5]); - full_frames_ref.push_back(std::make_pair(2e5, second_ref_ptr)); - - // Check the two first images - EXPECT_EQ(size_t(2), full_frames.size()); - for (size_t i = 0; i < 2; i++) { - EXPECT_EQ(full_frames_ref[i].first, full_frames[i].first); - ASSERT_EQ(full_frames_ref[i].second->size(), full_frames[i].second->size()); - EXPECT_GT(1e-6, cv::norm(*full_frames[i].second - *full_frames_ref[i].second)); - } -} - -TEST_F(FrameCompositionStageTest, unbalanced_streams) { - /// GIVEN two left and right frame streams, such as the frequency of the left stream - /// is much larger than the right one. - // - // Left : v0 v1 v2 v3 v4 v7 v8 v - // Time : ---0-------------------1e5-------------------2e5------ - // Right: ^5 ^6 ^9 ^ - // - // (The number besides ^ or v corresponds to the index of the test image. - // If there is none, it means the image is a nullptr) - - std::vector frames_left, frames_right; - frames_left.push_back(std::make_pair(1e5 - 100, img_ptrs[0])); - frames_left.push_back(std::make_pair(1e5 - 80, img_ptrs[1])); - frames_left.push_back(std::make_pair(1e5 - 60, img_ptrs[2])); - frames_left.push_back(std::make_pair(1e5 - 40, img_ptrs[3])); - frames_left.push_back(std::make_pair(1e5 - 20, img_ptrs[4])); - - frames_right.push_back(std::make_pair(1e5 - 100, img_ptrs[5])); - frames_right.push_back(std::make_pair(1e5 - 30, img_ptrs[6])); - - frames_left.push_back(std::make_pair(1e5 + 1, img_ptrs[7])); - frames_left.push_back(std::make_pair(1e5 + 10, img_ptrs[8])); - frames_right.push_back(std::make_pair(1e5 + 1, img_ptrs[9])); - - /// WHEN we run the pipeline - std::vector full_frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(frames_left)); - auto &s2 = p.add_stage(std::make_unique(frames_right)); - auto &s3 = p.add_stage(std::make_unique(10)); // 10 FPS - auto &s4 = p.add_stage(std::make_unique(full_frames), s3); - s3.add_previous_frame_stage(s1, 0, 0, width, height); - s3.add_previous_frame_stage(s2, width, 0, width, height); - p.run(); - - /// THEN we get the expected composed images - std::vector full_frames_ref; - FramePtr first_ref_ptr = hconcat_dot_imgs(width, width, height, dots[4], dots[6]); - full_frames_ref.push_back(std::make_pair(1e5, first_ref_ptr)); - - FramePtr second_ref_ptr = hconcat_dot_imgs(width, width, height, dots[8], dots[9]); - full_frames_ref.push_back(std::make_pair(2e5, second_ref_ptr)); - - // Check the two first images - EXPECT_EQ(size_t(2), full_frames.size()); - for (size_t i = 0; i < 2; i++) { - EXPECT_EQ(full_frames_ref[i].first, full_frames[i].first); - ASSERT_EQ(full_frames_ref[i].second->size(), full_frames[i].second->size()); - EXPECT_GT(1e-6, cv::norm(*full_frames[i].second - *full_frames_ref[i].second)); - } -} - -TEST_F(FrameCompositionStageTest, nullptrs_as_temporal_markers) { - /// GIVEN two synchronous left and right frame streams, using nullptrs as temporal markers. - // - // Left : v0 v2 v v - // Time : ---0--------1e5--------2e5--------3e5--------4e5--- - // Right: ^1 ^ ^3 ^ - // - // (The number besides ^ or v corresponds to the index of the test image. - // If there is none, it means the image is a nullptr) - - std::vector frames_left, frames_right; - frames_left.push_back(std::make_pair(1e5 - 10, img_ptrs[0])); - frames_right.push_back(std::make_pair(1e5 - 10, img_ptrs[1])); - - frames_left.push_back(std::make_pair(2e5 - 10, img_ptrs[2])); - frames_right.push_back(std::make_pair(2e5 - 10, FramePtr())); - - frames_left.push_back(std::make_pair(3e5 - 10, FramePtr())); - frames_right.push_back(std::make_pair(3e5 - 10, img_ptrs[3])); - - /// WHEN we run the pipeline - std::vector full_frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(frames_left)); - auto &s2 = p.add_stage(std::make_unique(frames_right)); - auto &s3 = p.add_stage(std::make_unique(10)); // 10 FPS - auto &s4 = p.add_stage(std::make_unique(full_frames), s3); - s3.add_previous_frame_stage(s1, 0, 0, width, height); - s3.add_previous_frame_stage(s2, width, 0, width, height); - p.run(); - - /// THEN we get the expected composed images - std::vector full_frames_ref; - FramePtr first_ref_ptr = hconcat_dot_imgs(width, width, height, dots[0], dots[1]); - full_frames_ref.push_back(std::make_pair(1e5, first_ref_ptr)); - - FramePtr second_ref_ptr = hconcat_dot_imgs(width, width, height, dots[2], dots[1]); - full_frames_ref.push_back(std::make_pair(2e5, second_ref_ptr)); - - FramePtr third_ref_ptr = hconcat_dot_imgs(width, width, height, dots[2], dots[3]); - full_frames_ref.push_back(std::make_pair(3e5, third_ref_ptr)); - - // Check the three first images - EXPECT_EQ(size_t(3), full_frames.size()); - for (size_t i = 0; i < 3; i++) { - EXPECT_EQ(full_frames_ref[i].first, full_frames[i].first); - ASSERT_EQ(full_frames_ref[i].second->size(), full_frames[i].second->size()); - EXPECT_GT(1e-6, cv::norm(*full_frames[i].second - *full_frames_ref[i].second)); - } -} - -TEST_F(FrameCompositionStageTest, nullptr_overwriting_risk) { - /// GIVEN two synchronous left and right frame streams, using nullptrs as temporal markers. - // - // Left : v0 v v1 v v v v2 v v - // Time : ---0---------------1e5---------------2e5--------3e5-- - // Right: ^3 ^ ^ ^4 ^ ^ - // - // (The number besides ^ or v corresponds to the index of the test image. - // If there is none, it means the image is a nullptr) - - std::vector frames_left, frames_right; - frames_left.push_back(std::make_pair(1e5 - 40, img_ptrs[0])); - frames_left.push_back(std::make_pair(1e5 - 30, FramePtr())); - frames_left.push_back(std::make_pair(1e5 - 20, img_ptrs[1])); - frames_left.push_back(std::make_pair(1e5 - 10, FramePtr())); - - frames_right.push_back(std::make_pair(1e5 - 20, img_ptrs[3])); - frames_right.push_back(std::make_pair(1e5 - 10, FramePtr())); - - frames_left.push_back(std::make_pair(2e5 - 40, FramePtr())); - frames_left.push_back(std::make_pair(2e5 - 30, FramePtr())); - frames_left.push_back(std::make_pair(2e5 - 20, img_ptrs[2])); - frames_left.push_back(std::make_pair(2e5 - 10, FramePtr())); - - frames_right.push_back(std::make_pair(2e5 - 30, FramePtr())); - frames_right.push_back(std::make_pair(2e5 - 20, img_ptrs[4])); - frames_right.push_back(std::make_pair(2e5 - 10, FramePtr())); - - /// WHEN we run the pipeline - std::vector full_frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(frames_left)); - auto &s2 = p.add_stage(std::make_unique(frames_right)); - auto &s3 = p.add_stage(std::make_unique(10)); // 10 FPS - auto &s4 = p.add_stage(std::make_unique(full_frames), s3); - s3.add_previous_frame_stage(s1, 0, 0, width, height); - s3.add_previous_frame_stage(s2, width, 0, width, height); - p.run(); - - /// THEN we get the expected composed images and the nulltprs haven't overwritten the valid ptrs - std::vector full_frames_ref; - FramePtr first_ref_ptr = hconcat_dot_imgs(width, width, height, dots[1], dots[3]); - full_frames_ref.push_back(std::make_pair(1e5, first_ref_ptr)); - - FramePtr second_ref_ptr = hconcat_dot_imgs(width, width, height, dots[2], dots[4]); - full_frames_ref.push_back(std::make_pair(2e5, second_ref_ptr)); - - // Check the three first images - EXPECT_EQ(size_t(2), full_frames.size()); - for (size_t i = 0; i < 2; i++) { - EXPECT_EQ(full_frames_ref[i].first, full_frames[i].first); - ASSERT_EQ(full_frames_ref[i].second->size(), full_frames[i].second->size()); - EXPECT_GT(1e-6, cv::norm(*full_frames[i].second - *full_frames_ref[i].second)); - } -} - -TEST_F(FrameCompositionStageTest, slow_streams) { - /// GIVEN two left and right frame streams, such as their output frequency is smaller - /// than the display frequency. - // - // Left : v0 v3 v - // Time : ---0--------1e5--------2e5--------3e5--------4e5--------5e5 - // Right: ^1 ^2 ^ - // - // (The number besides ^ or v corresponds to the index of the test image. - // If there is none, it means the image is a nullptr) - - std::vector frames_left, frames_right; - frames_left.push_back(std::make_pair(1e5 - 10, img_ptrs[0])); - frames_right.push_back(std::make_pair(1e5 - 10, img_ptrs[1])); - - frames_right.push_back(std::make_pair(3e5 - 10, img_ptrs[2])); - - frames_left.push_back(std::make_pair(4e5 - 10, img_ptrs[3])); - - /// WHEN we run the pipeline - std::vector full_frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(frames_left)); - auto &s2 = p.add_stage(std::make_unique(frames_right)); - auto &s3 = p.add_stage(std::make_unique(10)); // 10 FPS - auto &s4 = p.add_stage(std::make_unique(full_frames), s3); - s3.add_previous_frame_stage(s1, 0, 0, width, height); - s3.add_previous_frame_stage(s2, width, 0, width, height); - p.run(); - - /// THEN we get the expected composed images - std::vector full_frames_ref; - FramePtr first_ref_ptr = hconcat_dot_imgs(width, width, height, dots[0], dots[1]); - full_frames_ref.push_back(std::make_pair(1e5, first_ref_ptr)); - - FramePtr second_ref_ptr = hconcat_dot_imgs(width, width, height, dots[0], dots[1]); - full_frames_ref.push_back(std::make_pair(2e5, second_ref_ptr)); - - FramePtr third_ref_ptr = hconcat_dot_imgs(width, width, height, dots[0], dots[2]); - full_frames_ref.push_back(std::make_pair(3e5, third_ref_ptr)); - - FramePtr fourth_ref_ptr = hconcat_dot_imgs(width, width, height, dots[3], dots[2]); - full_frames_ref.push_back(std::make_pair(4e5, fourth_ref_ptr)); - - // Check the three first images - EXPECT_EQ(size_t(4), full_frames.size()); - for (size_t i = 0; i < 4; i++) { - EXPECT_EQ(full_frames_ref[i].first, full_frames[i].first); - ASSERT_EQ(full_frames_ref[i].second->size(), full_frames[i].second->size()); - EXPECT_GT(1e-6, cv::norm(*full_frames[i].second - *full_frames_ref[i].second)); - } -} diff --git a/sdk/modules/core/cpp/tests/frame_generation_stage_gtest.cpp b/sdk/modules/core/cpp/tests/frame_generation_stage_gtest.cpp deleted file mode 100644 index a41ea0bd0..000000000 --- a/sdk/modules/core/cpp/tests/frame_generation_stage_gtest.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/core/pipeline/pipeline.h" -#include "metavision/sdk/core/pipeline/frame_generation_stage.h" - -using namespace Metavision; - -using FramePool = SharedObjectPool; -using FramePtr = FramePool::ptr_type; -using FrameData = std::pair; - -namespace { -struct MockProducingStage : public BaseStage { - MockProducingStage(const std::vector> &evts) : - events(evts), step(0), pool(EventBufferPool::make_bounded()) { - set_starting_callback([this] { - thread = std::thread([this] { - while (true) { - if (stopped) - break; - if (step < events.size()) { - auto buffer = pool.acquire(); - *buffer = events[step++]; - produce(buffer); - } else { - break; - } - } - if (!stopped) - complete(); - }); - }); - set_stopping_callback([this] { - stopped = true; - if (thread.joinable()) { - thread.join(); - } - }); - } - - std::thread thread; - std::atomic stopped{false}; - std::vector> events; - EventBufferPool pool; - size_t step; -}; - -struct MockConsumingStage : public BaseStage { - MockConsumingStage(std::vector &ds) : datas(ds) { - set_consuming_callback([this](const boost::any &data) { - try { - datas.emplace_back(boost::any_cast(data)); - } catch (boost::bad_any_cast &) {} - }); - } - std::vector &datas; -}; -} // namespace - -// Prophesee Colors -namespace { -cv::Vec3b bg_color = BaseFrameGenerationAlgorithm::bg_color_default(); -cv::Vec3b on_color = BaseFrameGenerationAlgorithm::on_color_default(); -cv::Vec3b off_color = BaseFrameGenerationAlgorithm::off_color_default(); -} // namespace - -TEST(FrameGenerationStageTest, basic) { - // GIVEN 2 events in [0, 1e5[ and 1 event in [1e5, 2e5[ - std::vector> events; - - events.push_back({Metavision::EventCD{5, 5, 0, 0}, // Event used to set the first timestamp at 0 - Metavision::EventCD{5, 5, 0, 101}, Metavision::EventCD{5, 8, 1, 95001}, - Metavision::EventCD{0, 0, 0, 100001}}); - - // WHEN we run the pipeline with a display period of 1e5us and an accumulation time of 1e4us to generate images - std::vector frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(events)); - auto &s2 = p.add_stage(std::make_unique(10, 10, 10, 10), s1); - auto &s3 = p.add_stage(std::make_unique(frames), s2); - p.run(); - - // THEN we only display the event in the last 1e4us of the time slice - cv::Mat frame(10, 10, CV_8UC3, bg_color); - frame.at(8, 5) = on_color; - - ASSERT_EQ(size_t(1), frames.size()); - ASSERT_EQ(100000, frames[0].first); - ASSERT_EQ(frame.size(), frames[0].second->size()); - ASSERT_TRUE(std::equal(frame.begin(), frame.end(), frames[0].second->begin())); -} - -TEST(FrameGenerationStageTest, round_timeshift) { - // GIVEN 2 events in [0, 1e5[ and 1 event in [1e5, 2e5[, with an overall time shift of 10s - const uint32_t accumulation_time_ms = 10, timeshift = 10000000; - const int fps = 1000 / accumulation_time_ms; // We generate exactly one frame over the input events - std::vector> events; - events.push_back({Metavision::EventCD{5, 5, 0, timeshift}, - Metavision::EventCD{5, 8, 1, timeshift + accumulation_time_ms * 1000 - 10}, - Metavision::EventCD{0, 0, 0, timeshift + accumulation_time_ms * 1000}}); - - // WHEN we run the pipeline with a display period of 1e5us and an accumulation time of 1e4us to generate images - std::vector frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(events)); - auto &s2 = p.add_stage(std::make_unique(10, 10, accumulation_time_ms, fps), s1); - auto &s3 = p.add_stage(std::make_unique(frames), s2); - p.run(); - - // THEN we only display the event between [timeshift , timeshift + accumulation_time_ms[ - // accumulation time of the frame - cv::Mat frame(10, 10, CV_8UC3, bg_color); - frame.at(5, 5) = off_color; - frame.at(8, 5) = on_color; - frame.at(0, 0) = bg_color; - - ASSERT_EQ(size_t(1), frames.size()); - ASSERT_EQ(timeshift + accumulation_time_ms * 1000, frames[0].first); - ASSERT_EQ(frame.size(), frames[0].second->size()); - - ASSERT_TRUE(std::equal(frame.begin(), frame.end(), frames[0].second->begin())); -} - -TEST(FrameGenerationStageTest, not_round_timeshift) { - // GIVEN 2 events in [0, 1e5[, 2 events in [1e5, 2e5[ and 1 event in [2e5, 3e5[, - // with an overall time shift of 10s+5us - const timestamp step_us = 100000, timeshift = 10000000, ts_first = 5; - std::vector> events; - events.push_back({Metavision::EventCD{5, 5, 0, timeshift + ts_first}, - Metavision::EventCD{5, 8, 1, timeshift + step_us - 10}, - Metavision::EventCD{0, 0, 0, timeshift + step_us + 1}}); - - // WHEN we run the pipeline with a display period of 1e5us and an accumulation time of 1e4us to generate images - std::vector frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(events)); - auto &s2 = p.add_stage(std::make_unique(10, 10, 10, 10), s1); - auto &s3 = p.add_stage(std::make_unique(frames), s2); - p.run(); - - // THEN we only display the event in the last 1e4us of the time slice - cv::Mat frame(10, 10, CV_8UC3, bg_color); - frame.at(8, 5) = on_color; - frame.at(5, 5) = bg_color; - - ASSERT_EQ(size_t(1), frames.size()); - ASSERT_EQ(timeshift + step_us, frames[0].first); - ASSERT_EQ(frame.size(), frames[0].second->size()); - - ASSERT_TRUE(std::equal(frame.begin(), frame.end(), frames[0].second->begin())); -} - -TEST(FrameGenerationStageTest, overflow_pool) { - // GIVEN a lot of dummy eventbuffers exhausting the producing stage's object pool memory - std::vector> events; - for (int i = 0; i < 300; ++i) { - events.push_back({Metavision::EventCD{5, 5, 0, 10000 + i}}); - } - events.push_back({Metavision::EventCD{5, 5, 0, 95001}, Metavision::EventCD{0, 0, 0, 100001}}); - - // WHEN we run the pipeline with a display period of 1e5us and an accumulation time of 1e4us to generate images - std::vector frames; - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(events)); - auto &s2 = p.add_stage(std::make_unique(10, 10, 10, 10), s1); - auto &s3 = p.add_stage(std::make_unique(frames), s2); - p.run(); - - // THEN the frame generation stage does not stall or block, since it does not store - // directly the buffer's shared pointer and the eventbuffers can be reused. - cv::Mat frame(10, 10, CV_8UC3, bg_color); - frame.at(5, 5) = off_color; - - ASSERT_EQ(size_t(1), frames.size()); - ASSERT_EQ(100000, frames[0].first); - ASSERT_EQ(frame.size(), frames[0].second->size()); - - ASSERT_TRUE(std::equal(frame.begin(), frame.end(), frames[0].second->begin())); -} diff --git a/sdk/modules/core/cpp/tests/pipeline_gtest.cpp b/sdk/modules/core/cpp/tests/pipeline_gtest.cpp deleted file mode 100644 index 37fc3d85b..000000000 --- a/sdk/modules/core/cpp/tests/pipeline_gtest.cpp +++ /dev/null @@ -1,739 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/core/pipeline/pipeline.h" -#include "metavision/sdk/core/pipeline/stage.h" - -using namespace Metavision; - -namespace { -struct MockAlgorithm { - template - void process_events(InputIt begin, InputIt end, OutputIt d_begin) { - std::copy(begin, end, d_begin); - } -}; - -struct MockProducingStage : public BaseStage { - MockProducingStage() { - set_starting_callback([this] { - thread_ = std::thread([this] { - while (true) { - if (stopped_) - break; - if (!produce_impl()) { - break; - } - } - if (!stopped_) - complete(); - }); - }); - set_stopping_callback([this] { - stopped_ = true; - if (thread_.joinable()) { - thread_.join(); - } - }); - } - - virtual bool produce_impl() { - return true; - } - std::thread thread_; - std::atomic stopped_{false}; -}; - -struct VectorProducingStage : public MockProducingStage { - VectorProducingStage(const std::vector &datas) : datas(datas), step(0) {} - bool produce_impl() override { - if (step < datas.size()) { - produce(datas[step++]); - return true; - } - return false; - } - std::vector datas; - size_t step; -}; - -struct MockConsumingStage : public BaseStage { - MockConsumingStage(bool delayed_start = false) { - set_starting_callback([delayed_start, this] { - if (delayed_start) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - started_ = true; - }); - set_consuming_callback([this](const boost::any &data) { - try { - if (started_) - datas.emplace_back(boost::any_cast(data)); - } catch (boost::bad_any_cast &) {} - }); - } - std::vector datas; - std::atomic started_{false}; -}; -} // namespace - -TEST(PipelineTest, no_stages) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a default constructed pipeline does not contain any stages - Pipeline p; - EXPECT_EQ(size_t(0), p.count()); - EXPECT_TRUE(p.empty()); -} - -TEST(PipelineTest, add_stage) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline with one added stage has the correct invariants - Pipeline p; - EXPECT_EQ(size_t(0), p.count()); - EXPECT_TRUE(p.empty()); - p.add_stage(std::make_unique()); - EXPECT_EQ(size_t(1), p.count()); - EXPECT_FALSE(p.empty()); -} - -TEST(PipelineTest, add_algorithm_stage) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline with one added (algorithm) stage has the correct invariants - Pipeline p; - EXPECT_EQ(size_t(0), p.count()); - EXPECT_TRUE(p.empty()); - p.add_algorithm_stage(std::make_unique()); - EXPECT_EQ(size_t(1), p.count()); - EXPECT_FALSE(p.empty()); -} - -TEST(PipelineTest, add_stage_default_auto_detach) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a default constructed pipeline does not automatically detach stages - Pipeline p; - auto &stage = p.add_stage(std::make_unique()); - EXPECT_FALSE(stage.is_detached()); -} - -TEST(PipelineTest, add_stage_auto_detach) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline with auto-detach automatically detaches stages - Pipeline p(true); - auto &stage = p.add_stage(std::make_unique()); - EXPECT_TRUE(stage.is_detached()); -} - -TEST(PipelineTest, add_stage_no_auto_detach) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline with disabled auto-detach does not automatically detach stages - Pipeline p(false); - auto &stage = p.add_stage(std::make_unique()); - EXPECT_FALSE(stage.is_detached()); -} - -TEST(PipelineTest, add_stage_auto_detach_precedence) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline with auto-detach can not detach un-detachable stages - Pipeline p(true); - auto &stage = p.add_stage(std::make_unique(false)); - EXPECT_FALSE(stage.is_detached()); -} - -TEST(PipelineTest, add_stage_with_previous) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that add_stage correctly passes the previous stage arg - Pipeline p; - Stage s1; - auto &s2 = p.add_stage(std::make_unique(), s1); - EXPECT_EQ(std::unordered_set{&s1}, s2.previous_stages()); -} - -TEST(PipelineTest, add_algorithm_stage_with_previous) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that add_algorithm_stage correctly passes the previous stage arg - Pipeline p; - Stage s1; - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - EXPECT_EQ(std::unordered_set{&s1}, s2.previous_stages()); -} - -TEST(PipelineTest, add_algorithm_stage_default_enabled) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that add_algorithm_stage correctly passes the enabled flag to the algo by default - Pipeline p; - auto &s = p.add_algorithm_stage(std::make_unique()); - EXPECT_TRUE(s.is_enabled()); -} - -TEST(PipelineTest, add_algorithm_stage_disabled) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that add_algorithm_stage correctly passes the enabled flag to the algo - Pipeline p; - auto &s = p.add_algorithm_stage(std::make_unique(), false); - EXPECT_FALSE(s.is_enabled()); -} - -TEST(PipelineTest, add_algorithm_stage_with_previous_disabled) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that add_algorithm_stage correctly passes the previous stages and - // the enabled flag to the algo - Pipeline p; - Stage s1; - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1, false); - EXPECT_EQ(std::unordered_set{&s1}, s2.previous_stages()); - EXPECT_FALSE(s2.is_enabled()); -} - -TEST(PipelineTest, remove_stage) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that after removing a stage from a pipeline, the count is OK - Pipeline p; - auto &stage = p.add_stage(std::make_unique(false)); - EXPECT_EQ(size_t(1), p.count()); - EXPECT_FALSE(p.empty()); - p.remove_stage(stage); - EXPECT_EQ(size_t(0), p.count()); - EXPECT_TRUE(p.empty()); -} - -TEST(PipelineTest, destructor_when_empty) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block when the pipeline is empty - Pipeline p; -} - -TEST(PipelineTest, destructor_with_no_consumers) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block when the pipeline does not contain consumer - Pipeline p; - p.add_stage(std::make_unique()); - p.add_stage(std::make_unique()); -} - -TEST(PipelineTest, destructor_with_one_undetached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block if the producer and consumer are - // both run on the main thread - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - p.add_algorithm_stage(std::make_unique(), s1); -} - -TEST(PipelineTest, destructor_with_one_detached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block on a (well behaving) pipeline - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - p.add_algorithm_stage(std::make_unique(), s1); -} - -TEST(PipelineTest, step_when_empty) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that step returns false when the pipeline is empty - Pipeline p; - EXPECT_FALSE(p.step()); -} - -TEST(PipelineTest, step_with_no_consumers) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that step finishes immediately when the pipeline does not contain consumer - Pipeline p; - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_stage(std::make_unique()); - EXPECT_FALSE(p.step()); -} - -TEST(PipelineTest, step_with_one_undetached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that step returns true at least once if the producer and consumer are - // both run on the main thread - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - EXPECT_TRUE(p.step()); - while (p.step()) {} -} - -TEST(PipelineTest, step_with_one_detached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that repeatedly calling step does not block (returns at some point) on a (well behaving) pipeline - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - while (p.step()) {} -} - -TEST(PipelineTest, run_when_empty) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that run does not block (returns at some point) when the pipeline is empty - Pipeline p; - p.run(); -} - -TEST(PipelineTest, run_with_no_consumers) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that run does not block (returns at some point) when the pipeline does not contain consumer - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(std::vector{1})); - auto &s2 = p.add_stage(std::make_unique(std::vector{2})); - p.run(); -} - -TEST(PipelineTest, run_with_one_undetached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that run does not block (returns at some point) if the producer and consumer are - // both run on the main thread - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - p.run(); -} - -TEST(PipelineTest, run_with_one_detached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that run does not block (returns at some point) on a (well behaving) pipeline - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - p.run(); -} - -TEST(PipelineTest, destructor_when_empty_pipeline_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block when the pipeline is empty and started (with step) - Pipeline p; - p.step(); -} - -TEST(PipelineTest, destructor_with_no_consumers_pipeline_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block when the pipeline does not contain consumer and is started (with step) - Pipeline p; - p.add_stage(std::make_unique()); - p.add_stage(std::make_unique()); -} - -TEST(PipelineTest, destructor_with_one_undetached_consumer_pipeline_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block if the producer and consumer are - // both run on the main thread and the pipeline is started (with step) - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - p.add_algorithm_stage(std::make_unique(), s1); -} - -TEST(PipelineTest, destructor_with_one_detached_consumer_pipeline_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the destructor does not block on a (well behaving) pipeline, started (with step) - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - p.add_algorithm_stage(std::make_unique(), s1); -} - -TEST(PipelineTest, detach_when_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that adding a stage on a started pipeline throws - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - p.step(); - EXPECT_FALSE(s1.detach()); -} - -TEST(PipelineTest, add_stage_when_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that adding a stage on a started pipeline throws - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - p.step(); - EXPECT_THROW(p.add_stage(std::make_unique(), s1), std::runtime_error); -} - -TEST(PipelineTest, remove_stage_when_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that removing a stage on a started pipeline throws - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - p.step(); - EXPECT_THROW(p.remove_stage(s2), std::runtime_error); -} - -TEST(PipelineTest, status_when_empty) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the status of a default constructed pipeline is Inactive - Pipeline p; - EXPECT_EQ(Pipeline::Status::Inactive, p.status()); -} - -TEST(PipelineTest, status_when_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that status of a pipeline that was started but not finished is Started - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - p.add_stage(std::make_unique(), s1); - p.step(); - EXPECT_EQ(Pipeline::Status::Started, p.status()); -} - -TEST(PipelineTest, status_when_cancelled) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that status of a pipeline that was cancelled is Cancelled - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - p.add_stage(std::make_unique(), s1); - p.step(); - p.cancel(); - EXPECT_EQ(Pipeline::Status::Cancelled, p.status()); -} - -TEST(PipelineTest, status_when_completed) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that status of a pipeline that has finished is Completed - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_algorithm_stage(std::make_unique(), s1); - while (p.step()) {} - EXPECT_EQ(Pipeline::Status::Completed, p.status()); -} - -TEST(PipelineTest, process_all_data_one_producer_one_undetached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline actually produces and forward data to all stages before - // completing - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_stage(std::make_unique(), s1); - while (p.step()) {} - EXPECT_EQ(Pipeline::Status::Completed, p.status()); - EXPECT_EQ(std::vector({1, 2}), s2.datas); -} - -TEST(PipelineTest, process_all_data_one_producer_one_detached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline actually produces and forward data to all stages before - // completing - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_stage(std::make_unique(), s1); - while (p.step()) {} - EXPECT_EQ(Pipeline::Status::Completed, p.status()); - EXPECT_EQ(std::vector({1, 2}), s2.datas); -} - -TEST(PipelineTest, process_all_data_two_producer_two_undetached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline actually produces and forward data to all stages before - // completing - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_stage(std::make_unique(std::vector{3, 4, 5})); - auto &s3 = p.add_stage(std::make_unique(), s1); - auto &s4 = p.add_stage(std::make_unique(), s2); - while (p.step()) {} - EXPECT_EQ(Pipeline::Status::Completed, p.status()); - EXPECT_EQ(std::vector({1, 2}), s3.datas); - EXPECT_EQ(std::vector({3, 4, 5}), s4.datas); -} - -TEST(PipelineTest, process_all_data_two_producer_two_detached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a pipeline actually produces and forward data to all stages before - // completing - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_stage(std::make_unique(std::vector{3, 4, 5})); - auto &s3 = p.add_stage(std::make_unique(), s1); - auto &s4 = p.add_stage(std::make_unique(), s2); - while (p.step()) {} - EXPECT_EQ(Pipeline::Status::Completed, p.status()); - EXPECT_EQ(std::vector({1, 2}), s3.datas); - EXPECT_EQ(std::vector({3, 4, 5}), s4.datas); -} - -TEST(PipelineTest, cancel_when_consuming_with_undetached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that calling cancel from the consuming callback of an undetached consumer - // actually cancels the pipeline, at multiple stages of consumption - size_t count = 5; - std::vector datas(count); - for (size_t i = 0; i < count; ++i) { - datas[i] = i; - } - for (size_t i = 1; i <= count; ++i) { - Pipeline p; - auto &s1 = p.add_stage(std::make_unique(datas)); - auto &s2 = p.add_stage(std::make_unique(), s1); - std::vector cdatas; - s2.set_consuming_callback([&p, &cdatas, i](const boost::any &data) { - try { - cdatas.emplace_back(boost::any_cast(data)); - if (cdatas.size() == i) - p.cancel(); - } catch (boost::bad_any_cast &) { FAIL() << "Bad cast not supposed to be caught"; } - }); - p.run(); - EXPECT_EQ(Pipeline::Status::Cancelled, p.status()); - EXPECT_EQ(std::vector(datas.begin(), datas.begin() + i), cdatas); - } -} - -TEST(PipelineTest, cancel_when_consuming_with_detached_consumer) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that calling cancel from the consuming callback of an undetached consumer - // actually cancels the pipeline, at multiple stages of consumption - size_t count = 5; - std::vector datas(count); - for (size_t i = 0; i < count; ++i) { - datas[i] = i; - } - for (size_t i = 0; i < count; ++i) { - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(datas)); - auto &s2 = p.add_stage(std::make_unique(), s1); - size_t j = 0; - s2.set_consuming_callback([&p, &j, i](const boost::any &data) { - try { - if (j++ == i) - p.cancel(); - } catch (boost::bad_any_cast &) { FAIL() << "Bad cast not supposed to be caught"; } - }); - p.run(); - EXPECT_EQ(Pipeline::Status::Cancelled, p.status()); - } -} - -TEST(PipelineTest, cancel_with_no_remaining_tasks_on_main_thread) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that calling cancel when one stage is undetached and waiting for tasks - // does not block forever - Pipeline p(false); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_stage(std::make_unique(), s1); - s2.detach(); - auto &s3 = p.add_stage(std::make_unique(), s1); - std::atomic run{false}; - // clang-format off - std::thread([&run, &p] { - while (!run) { - } - p.cancel(); - }).detach(); - // clang-format on - while (p.step()) { - run = true; - } - EXPECT_EQ(Pipeline::Status::Cancelled, p.status()); -} - -TEST(PipelineTest, DISABLED_consume_before_start) { // TODO Intermittently fails on Jenkins - To be fixed with MV-980"; - - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that when a stage takes time to start, no data is lost, e.g. if the consuming - // callback is called too soon. - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_stage(std::make_unique(true), s1); - while (p.step()) {} - EXPECT_EQ(Pipeline::Status::Completed, p.status()); - EXPECT_EQ(std::vector({1, 2}), s2.datas); -} - -TEST(PipelineTest, step_callbacks_are_called_in_sequence) { - static constexpr int PRE_STEP_DATA_ID = 1; // Id pushed in the output vector by the pre step callback - static constexpr int PRODUCED_DATA_ID = 2; // Id pushed in the output vector by the consuming callback - static constexpr int POST_STEP_DATA_ID = 3; // Id pushed in the output vector by the post callback - - // GIVEN a pipeline with: - // - a global output vector - // - a producer, executing from a separate thread, that produces integers of the same value (i.e. PRODUCED_DATA_ID) - // - a consumer, executing from the main thread, that pushes the incoming data in the global output vector - // - a pre-step callback, called from the main thread, that pushes its ID (i.e. PRE_STEP_DATA_ID) in the global - // output vector - // - a post-step callback, called from the main thread, that pushes its ID (i.e. POST_STEP_DATA_ID) in the global - // output vector - Pipeline p(true); - - std::vector inputs(2, PRODUCED_DATA_ID); - auto &s1 = p.add_stage(std::make_unique(inputs)); - - std::vector outputs; - auto s2 = std::make_unique(false); - s2->set_consuming_callback([&outputs](const boost::any &in) { - try { - outputs.emplace_back(boost::any_cast(in)); - } catch (boost::bad_any_cast &) {} - }); - p.add_stage(std::move(s2), s1); - - p.add_pre_step_callback([&outputs]() { outputs.emplace_back(PRE_STEP_DATA_ID); }); - p.add_post_step_callback([&outputs]() { outputs.emplace_back(POST_STEP_DATA_ID); }); - - // WHEN we run the pipeline - p.run(); - - // THEN - // - the pipeline completes - // - the consumer is called in between a pre-step and a post-step callback - // - because of the multi-threaded aspect of both the producer and the pipeline, there may be several calls to the - // pre and post-step callbacks before and after the consumer is called. The final output data looks like - // 1 3 1 3 ... 1 2 3 ... 1 2 3 ... 1 3 1 3 - EXPECT_EQ(Pipeline::Status::Completed, p.status()); - - auto step_cb_data_it = outputs.cbegin(); - auto consumed_data_it = outputs.cend(); - using SizeType = std::vector::size_type; - for (SizeType i = 0; i < inputs.size(); ++i) { - consumed_data_it = std::find(step_cb_data_it, outputs.cend(), PRODUCED_DATA_ID); - EXPECT_TRUE(consumed_data_it != outputs.cend()); // the produced data is found in the output vector - EXPECT_TRUE(std::prev(consumed_data_it) != outputs.cend()); // there is data before the produced data - EXPECT_TRUE(std::next(consumed_data_it) != outputs.cend()); // there is data after the produced data - EXPECT_EQ(1, *std::prev(consumed_data_it)); // the data before corresponds to the pre-step callback's - EXPECT_EQ(3, *std::next(consumed_data_it)); // the data after corresponds to the post-step callback's - - const auto step_cb_data_range_begin = step_cb_data_it; - const auto step_cb_data_range_end = std::prev(consumed_data_it); - const auto n_elts = std::distance(step_cb_data_range_begin, step_cb_data_range_end); - - // the pre and post-step callbacks may have been called several times before the consumer - EXPECT_LE(0, n_elts); - EXPECT_EQ(0, n_elts % 2); // if so, they have been called the same number of times - - // even indexes correspond to the pre-step callbacks while the odd ones correspond to the post-step callbacks - for (int j = 0; j < n_elts; ++j) - EXPECT_EQ((j % 2) ? POST_STEP_DATA_ID : PRE_STEP_DATA_ID, *(step_cb_data_it + j)); - - step_cb_data_it = consumed_data_it + 2; - } - - // the pre and post-step callbacks may also have been called several times after the consumer - if (step_cb_data_it != outputs.cend()) { - const auto n_elts = std::distance(step_cb_data_it, outputs.cend()); - EXPECT_EQ(0, n_elts % 2); - - for (int j = 0; j < n_elts; ++j) - EXPECT_EQ((j % 2) ? POST_STEP_DATA_ID : PRE_STEP_DATA_ID, *(step_cb_data_it + j)); - } -} - -TEST(PipelineTest, all_step_callbacks_are_called) { - static constexpr int N_STEP_CBS = 3; - - // GIVEN a pipeline with: - // - a producer - // - a consumer - // - a global output map where step callbacks' ids are registered - // - N_STEP_CBS pre-step callbacks pushing their unique id in the global output map - // - N_STEP_CBS post-step callbacks pushing their unique id in the global output map - std::map called_step_cbs; - - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique(std::vector{1, 2})); - auto &s2 = p.add_stage(std::make_unique(true), s1); - - for (int i = 0; i < N_STEP_CBS; ++i) { - p.add_pre_step_callback([=, &called_step_cbs]() { called_step_cbs[i] = true; }); - p.add_post_step_callback([=, &called_step_cbs]() { called_step_cbs[N_STEP_CBS + i] = true; }); - } - - // WHEN we run the pipeline - p.run(); - - // THEN all the step callbacks' ids are found in the global output map meaning that all the registered step - // callbacks have been called - for (int i = 0; i < 2 * N_STEP_CBS; ++i) { - const auto it = called_step_cbs.find(i); - EXPECT_TRUE(it != called_step_cbs.cend()); - EXPECT_EQ(true, it->second); - } -} - -TEST(PipelineTest, on_setup_callback_is_called) { - // GIVEN a pipeline with a single stage that sets a setup callback and a pre step callback from inside the latter - Pipeline p; - auto stage = std::make_unique(false); - - bool has_setup_cb_been_called = false; - bool has_pre_step_cb_been_called = false; - - auto &stage_ref = *stage; - - stage->set_setup_callback([&]() { - has_setup_cb_been_called = true; - - // We add this callback to detect potential deadlocks when setting callbacks from the setup one (if a deadlock - // occurs, the test will hang on and a timeout will expire making this test fail, and as a result, make - // the deadlock detectable). - stage_ref.pipeline().add_post_step_callback([&]() { has_pre_step_cb_been_called = true; }); - }); - - p.add_stage(std::move(stage)); - - // WHEN we run the pipeline - p.run(); - - // THEN all the callbacks are called - EXPECT_TRUE(has_setup_cb_been_called); - EXPECT_TRUE(has_pre_step_cb_been_called); -} diff --git a/sdk/modules/core/cpp/tests/stage_gtest.cpp b/sdk/modules/core/cpp/tests/stage_gtest.cpp deleted file mode 100644 index 91a231382..000000000 --- a/sdk/modules/core/cpp/tests/stage_gtest.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/core/pipeline/pipeline.h" -#include "metavision/sdk/core/pipeline/stage.h" - -using namespace Metavision; - -class MockStage : public Stage { -public: - void complete() { - Stage::complete(); - } -}; - -TEST(StageTest, default_constructor) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a default constructed stage is not detached - Stage s; - EXPECT_FALSE(s.is_detached()); -} - -TEST(StageTest, undetachable_constructor) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that an undetachable stage can not be detached - Stage s(false); - EXPECT_FALSE(s.is_detached()); - EXPECT_FALSE(s.detach()); - EXPECT_FALSE(s.is_detached()); -} - -TEST(StageTest, detachable_constructor) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a detachable stage can be detached - Stage s; - EXPECT_FALSE(s.is_detached()); - EXPECT_TRUE(s.detach()); - EXPECT_TRUE(s.is_detached()); -} - -TEST(StageTest, previous_stage_constructor) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that previous stage of a stage can be recovered - Stage s1; - Stage s2(s1); - EXPECT_EQ(std::unordered_set({&s1}), s2.previous_stages()); -} - -TEST(StageTest, previous_stage_undetachable_constructor) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that previous stage of an undetachable stage can be recovered and can not be detached - Stage s1; - Stage s2(s1, false); - EXPECT_FALSE(s2.is_detached()); - EXPECT_FALSE(s2.detach()); - EXPECT_FALSE(s2.is_detached()); - EXPECT_EQ(std::unordered_set({&s1}), s2.previous_stages()); -} - -TEST(StageTest, previous_stage_detachable_constructor) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that previous stage of a detachable stage can be recovered and can be detached - Stage s1; - Stage s2(s1); - EXPECT_FALSE(s2.is_detached()); - EXPECT_TRUE(s2.detach()); - EXPECT_TRUE(s2.is_detached()); - EXPECT_EQ(std::unordered_set({&s1}), s2.previous_stages()); -} - -TEST(StageTest, empty_previous_stages) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a default constructed stage has no previous stages - Stage s; - EXPECT_EQ(std::unordered_set(), s.previous_stages()); -} - -TEST(StageTest, set_previous_stage) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that calling set_previous_stage sets the correct previous stage - Stage s1, s2; - s1.set_previous_stage(s2); - EXPECT_EQ(std::unordered_set({&s2}), s1.previous_stages()); -} - -TEST(StageTest, add_previous_stages) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that adding multiple previous stages using consuming callbacks sets - // the correct previous stages - Stage s1, s2, s3; - s1.set_consuming_callback(s2, [](const boost::any &) {}); - s1.set_consuming_callback(s3, [](const boost::any &) {}); - EXPECT_EQ(std::unordered_set({&s2, &s3}), s1.previous_stages()); -} - -TEST(StageTest, set_add_previous_stages) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that adding multiple previous stages using set_previous_stage and consuming - // callbacks sets the correct previous stages - Stage s1, s2, s3; - s1.set_previous_stage(s2); - s1.set_consuming_callback(s3, [](const boost::any &) {}); - EXPECT_EQ(std::unordered_set({&s2, &s3}), s1.previous_stages()); -} - -TEST(StageTest, empty_next_stages) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a default constructed stage has no next stages - Stage s; - EXPECT_EQ(std::unordered_set(), s.next_stages()); -} - -TEST(StageTest, set_next_stage) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that calling set_previous_stage sets the correct next stage - Stage s1, s2; - s1.set_previous_stage(s2); - EXPECT_EQ(std::unordered_set({&s1}), s2.next_stages()); -} - -TEST(StageTest, add_next_stages) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that adding multiple previous stages using consuming callbacks sets - // the correct next stages - Stage s1, s2, s3; - s1.set_consuming_callback(s2, [](const boost::any &) {}); - s1.set_consuming_callback(s3, [](const boost::any &) {}); - EXPECT_EQ(std::unordered_set({&s1}), s2.next_stages()); - EXPECT_EQ(std::unordered_set({&s1}), s3.next_stages()); -} - -TEST(StageTest, set_add_next_stages) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that adding multiple previous stages using set_previous_stage and consuming - // callbacks sets the correct next stages - Stage s1, s2, s3; - s1.set_previous_stage(s2); - s1.set_consuming_callback(s3, [](const boost::any &) {}); - EXPECT_EQ(std::unordered_set({&s1}), s2.next_stages()); - EXPECT_EQ(std::unordered_set({&s1}), s3.next_stages()); -} - -TEST(StageTest, invalid_pipeline) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a stage not added to a pipeline has a null pointer pipeline - Stage s; - EXPECT_THROW(s.pipeline(), std::runtime_error); - EXPECT_THROW(const_cast(s).pipeline(), std::runtime_error); -} - -TEST(StageTest, valid_pipeline) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a stage not added to a pipeline has a null pointer pipeline - Pipeline p; - auto &s = p.add_stage(std::make_unique()); - EXPECT_EQ(&p, &s.pipeline()); - EXPECT_EQ(&p, &const_cast(s).pipeline()); -} - -TEST(StageTest, status_inactive) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the default status of a stage is inactive - Stage s; - EXPECT_EQ(BaseStage::Status::Inactive, s.status()); -} - -TEST(StageTest, status_completed) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a stage that completes has the completed status - MockStage s; - s.complete(); - EXPECT_EQ(BaseStage::Status::Completed, s.status()); -} - -TEST(StageTest, status_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a stage in a started pipeline has the started status - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - // we need to add at least a consumer, otherwise the pipeline will immediately stop - auto &s2 = p.add_stage(std::make_unique(), s1); - // start the pipeline - p.step(); - EXPECT_EQ(BaseStage::Status::Started, s1.status()); -} - -TEST(StageTest, status_cancelled) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that a stage in a started pipeline has the started status - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - // we need to add at least a consumer, otherwise the pipeline will immediately stop - auto &s2 = p.add_stage(std::make_unique(), s1); - // start the pipeline - p.step(); - p.cancel(); - EXPECT_EQ(BaseStage::Status::Cancelled, s1.status()); -} - -TEST(StageTest, remove_stage) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that removing a stage does not break the pipeline - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_stage(std::make_unique(), s1); - // remove a stage - p.remove_stage(s2); - // start the pipeline - p.step(); - SUCCEED(); -} - -TEST(StageTest, receiving_callbacks) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that when a stage changes status, the next stages are notified - std::atomic called_any_stage{false}, called_spec_stage{false}, called_no_stage{false}; - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_stage(std::make_unique()); - auto &s3 = p.add_stage(std::make_unique()); - auto &s4 = p.add_stage(std::make_unique(), s1); - auto &s5 = p.add_stage(std::make_unique(), s2); - auto &s6 = p.add_stage(std::make_unique(), s3); - s4.set_receiving_callback(s1, [&called_spec_stage](const BaseStage::NotificationType &t, const boost::any &d) { - called_spec_stage = true; - }); - s5.set_receiving_callback([&called_any_stage](const BaseStage &ps, const BaseStage::NotificationType &t, - const boost::any &d) { called_any_stage = true; }); - s6.set_receiving_callback( - [&called_no_stage](const BaseStage::NotificationType &t, const boost::any &d) { called_no_stage = true; }); - // start the pipeline - p.step(); - s1.complete(); - s2.complete(); - s3.complete(); - while (p.step()) {} - EXPECT_TRUE(called_spec_stage); - EXPECT_TRUE(called_any_stage); - EXPECT_TRUE(called_no_stage); -} - -TEST(StageTest, receiving_callback_started) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that when a stage changes status, the next stages are notified - std::atomic called{0}; - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_stage(std::make_unique(), s1); - s2.set_receiving_callback( - [&s1, &s2, &called](const BaseStage &ps, const BaseStage::NotificationType &t, const boost::any &d) { - switch (called) { - case 0: - try { - EXPECT_EQ(&s1, &ps); - EXPECT_EQ(BaseStage::NotificationType::Status, t); - auto status = boost::any_cast(d); - EXPECT_EQ(BaseStage::Status::Started, status); - } catch (boost::bad_any_cast &) { FAIL() << "Bad cast not supposed to be caught"; } - called++; - break; - } - }); - // start the pipeline - p.step(); - while (called < 1) {} -} - -TEST(StageTest, receiving_callback_completed) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that when a stage changes status, the next stages are notified - std::atomic called{0}; - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_stage(std::make_unique(), s1); - s2.set_receiving_callback( - [&s1, &called](const BaseStage &ps, const BaseStage::NotificationType &t, const boost::any &d) { - switch (called) { - case 0: - called++; - break; - case 1: - try { - EXPECT_EQ(&s1, &ps); - EXPECT_EQ(BaseStage::NotificationType::Status, t); - auto status = boost::any_cast(d); - EXPECT_EQ(BaseStage::Status::Completed, status); - } catch (boost::bad_any_cast &) { FAIL() << "Bad cast not supposed to be caught"; } - called++; - break; - } - }); - // start the pipeline - p.step(); - s1.complete(); - while (called < 2) {} -} - -TEST(StageTest, receiving_callback_cancelled) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that when a stage changes status, the next stages are notified - std::atomic called{0}; - Pipeline p(true); - auto &s1 = p.add_stage(std::make_unique()); - auto &s2 = p.add_stage(std::make_unique(), s1); - s2.set_receiving_callback( - [&s1, &called](const BaseStage &ps, const BaseStage::NotificationType &t, const boost::any &d) { - switch (called) { - case 0: - called++; - break; - case 1: - try { - EXPECT_EQ(&s1, &ps); - EXPECT_EQ(BaseStage::NotificationType::Status, t); - auto status = boost::any_cast(d); - EXPECT_EQ(BaseStage::Status::Cancelled, status); - } catch (boost::bad_any_cast &) { FAIL() << "Bad cast not supposed to be caught"; } - called++; - break; - } - }); - // start the pipeline - p.step(); - p.cancel(); - while (called < 2) {} -} diff --git a/sdk/modules/core/cpp/tests/time_surface_producer_algorithm_gtest.cpp b/sdk/modules/core/cpp/tests/time_surface_producer_algorithm_gtest.cpp index b838edc96..6323c1c35 100644 --- a/sdk/modules/core/cpp/tests/time_surface_producer_algorithm_gtest.cpp +++ b/sdk/modules/core/cpp/tests/time_surface_producer_algorithm_gtest.cpp @@ -12,174 +12,136 @@ #include #include -#include "metavision/sdk/core/algorithms/time_surface_producer_algorithm.h" +#include "metavision/sdk/core/preprocessors/time_surface_processor.h" +#include "metavision/sdk/core/utils/mostrecent_timestamp_buffer.h" -class TimesurfaceProducerAlgorithmGTest : public ::testing::Test { +using InputIt = std::vector::const_iterator; + +class TimeSurfaceProcessorGTest : public ::testing::Test { public: - TimesurfaceProducerAlgorithmGTest() = default; - virtual ~TimesurfaceProducerAlgorithmGTest() = default; + TimeSurfaceProcessorGTest() = default; + virtual ~TimeSurfaceProcessorGTest() = default; }; -TEST_F(TimesurfaceProducerAlgorithmGTest, test_output_n_positive_events) { - Metavision::TimeSurfaceProducerAlgorithm<1> producer(3, 3); - Metavision::timestamp ts; - Metavision::MostRecentTimestampBuffer timesurface; - - producer.set_output_callback([&ts, ×urface](Metavision::timestamp output_ts, - const Metavision::MostRecentTimestampBuffer &output_timesurface) { - ts = output_ts; - timesurface = output_timesurface; - }); +TEST_F(TimeSurfaceProcessorGTest, test_output_n_positive_events) { + Metavision::TimeSurfaceProcessor producer(3, 3); + Metavision::MostRecentTimestampBuffer timesurface(3, 3, 1); // GIVEN - // - a producer that produces a one-channel time surface every 5 events, and + // - a producer that produces a one-channel time surface, and // - a buffer of 6 positive events - producer.set_processing_n_events(5); - std::vector events = {{0, 0, 1, 0}, {1, 0, 1, 1}, {2, 0, 1, 2}, {0, 1, 1, 3}, {1, 1, 1, 4}, {2, 1, 1, 5}}; // WHEN // We process the events - producer.process_events(events.cbegin(), events.cend()); + producer.process_events(events.cbegin(), events.cend(), timesurface); // THEN // One time surface is produced and // |0 1 2| - // timesurface = |3 4 0| + // timesurface = |3 4 5| // |0 0 0| - ASSERT_EQ(ts, 4); ASSERT_EQ(timesurface.at(0, 0), 0); ASSERT_EQ(timesurface.at(0, 1), 1); ASSERT_EQ(timesurface.at(0, 2), 2); ASSERT_EQ(timesurface.at(1, 0), 3); ASSERT_EQ(timesurface.at(1, 1), 4); - ASSERT_EQ(timesurface.at(1, 2), 0); + ASSERT_EQ(timesurface.at(1, 2), 5); ASSERT_EQ(timesurface.at(2, 0), 0); ASSERT_EQ(timesurface.at(2, 1), 0); ASSERT_EQ(timesurface.at(2, 2), 0); } -TEST_F(TimesurfaceProducerAlgorithmGTest, test_output_n_negative_events) { - Metavision::TimeSurfaceProducerAlgorithm<1> producer(3, 3); - Metavision::timestamp ts; - Metavision::MostRecentTimestampBuffer timesurface; - - producer.set_output_callback([&ts, ×urface](Metavision::timestamp output_ts, - const Metavision::MostRecentTimestampBuffer &output_timesurface) { - ts = output_ts; - timesurface = output_timesurface; - }); +TEST_F(TimeSurfaceProcessorGTest, test_output_n_negative_events) { + Metavision::TimeSurfaceProcessor producer(3, 3); + Metavision::MostRecentTimestampBuffer timesurface(3, 3, 1); // GIVEN - // - a producer that produces a one-channel time surface every 5 events, and + // - a producer that produces a one-channel time surface, and // - a buffer of 6 negative events - producer.set_processing_n_events(5); - std::vector events = {{0, 0, 0, 0}, {1, 0, 0, 1}, {2, 0, 0, 2}, {0, 1, 0, 3}, {1, 1, 0, 4}, {2, 1, 0, 5}}; // WHEN // We process the events - producer.process_events(events.cbegin(), events.cend()); + producer.process_events(events.cbegin(), events.cend(), timesurface); // THEN // One time surface is produced and // |0 1 2| - // timesurface = |3 4 0| + // timesurface = |3 4 5| // |0 0 0| - ASSERT_EQ(ts, 4); ASSERT_EQ(timesurface.at(0, 0), 0); ASSERT_EQ(timesurface.at(0, 1), 1); ASSERT_EQ(timesurface.at(0, 2), 2); ASSERT_EQ(timesurface.at(1, 0), 3); ASSERT_EQ(timesurface.at(1, 1), 4); - ASSERT_EQ(timesurface.at(1, 2), 0); + ASSERT_EQ(timesurface.at(1, 2), 5); ASSERT_EQ(timesurface.at(2, 0), 0); ASSERT_EQ(timesurface.at(2, 1), 0); ASSERT_EQ(timesurface.at(2, 2), 0); } -TEST_F(TimesurfaceProducerAlgorithmGTest, test_output_n_mixed_positive_and_negative_events) { - Metavision::TimeSurfaceProducerAlgorithm<1> producer(3, 3); - Metavision::timestamp ts; - Metavision::MostRecentTimestampBuffer timesurface; - - producer.set_output_callback([&ts, ×urface](Metavision::timestamp output_ts, - const Metavision::MostRecentTimestampBuffer &output_timesurface) { - ts = output_ts; - timesurface = output_timesurface; - }); +TEST_F(TimeSurfaceProcessorGTest, test_output_n_mixed_positive_and_negative_events) { + Metavision::TimeSurfaceProcessor producer(3, 3); + Metavision::MostRecentTimestampBuffer timesurface(3, 3, 1); // GIVEN - // - a producer that produces a one-channel time surface every 5 events, and + // - a producer that produces a one-channel time surface, and // - a buffer of 6 events (mix of positive and negative) - producer.set_processing_n_events(5); - std::vector events = {{0, 0, 1, 0}, {1, 0, 0, 1}, {2, 0, 1, 2}, {0, 1, 1, 3}, {1, 1, 0, 4}, {2, 1, 0, 5}}; // WHEN // We process the events - producer.process_events(events.cbegin(), events.cend()); + producer.process_events(events.cbegin(), events.cend(), timesurface); // THEN // One time surface is produced and // |0 1 2| - // timesurface = |3 4 0| + // timesurface = |3 4 5| // |0 0 0| - ASSERT_EQ(ts, 4); ASSERT_EQ(timesurface.at(0, 0), 0); ASSERT_EQ(timesurface.at(0, 1), 1); ASSERT_EQ(timesurface.at(0, 2), 2); ASSERT_EQ(timesurface.at(1, 0), 3); ASSERT_EQ(timesurface.at(1, 1), 4); - ASSERT_EQ(timesurface.at(1, 2), 0); + ASSERT_EQ(timesurface.at(1, 2), 5); ASSERT_EQ(timesurface.at(2, 0), 0); ASSERT_EQ(timesurface.at(2, 1), 0); ASSERT_EQ(timesurface.at(2, 2), 0); } -TEST_F(TimesurfaceProducerAlgorithmGTest, test_output_n_mixed_events_two_channels) { - Metavision::TimeSurfaceProducerAlgorithm<2> producer(3, 3); - Metavision::timestamp ts; - Metavision::MostRecentTimestampBuffer timesurface; - - producer.set_output_callback([&ts, ×urface](Metavision::timestamp output_ts, - const Metavision::MostRecentTimestampBuffer &output_timesurface) { - ts = output_ts; - timesurface = output_timesurface; - }); +TEST_F(TimeSurfaceProcessorGTest, test_output_n_mixed_events_two_channels) { + Metavision::TimeSurfaceProcessor producer(3, 3); + Metavision::MostRecentTimestampBuffer timesurface(3, 3, 2); // GIVEN - // - a producer that produces a two-channels time surface every 5 events, and + // - a producer that produces a two-channels time surface, and // - a buffer of 6 events (mix of positive and negative) - producer.set_processing_n_events(5); - std::vector events = {{0, 0, 1, 0}, {1, 0, 0, 1}, {2, 0, 1, 2}, {0, 1, 1, 3}, {1, 1, 0, 4}, {2, 1, 0, 5}}; // WHEN // We process the events - producer.process_events(events.cbegin(), events.cend()); + producer.process_events(events.cbegin(), events.cend(), timesurface); // THEN // Two time surfaces are produced (one for each channel) // |0 1 0| - // timesurface for positive events = |0 4 0| + // timesurface for positive events = |0 4 5| // |0 0 0| // // |0 0 2| // timesurface for negative events = |3 0 0| // |0 0 0| - ASSERT_EQ(ts, 4); - ASSERT_EQ(timesurface.at(0, 0, 0), 0); ASSERT_EQ(timesurface.at(0, 1, 0), 1); ASSERT_EQ(timesurface.at(0, 2, 0), 0); ASSERT_EQ(timesurface.at(1, 0, 0), 0); ASSERT_EQ(timesurface.at(1, 1, 0), 4); - ASSERT_EQ(timesurface.at(1, 2, 0), 0); + ASSERT_EQ(timesurface.at(1, 2, 0), 5); ASSERT_EQ(timesurface.at(2, 0, 0), 0); ASSERT_EQ(timesurface.at(2, 1, 0), 0); ASSERT_EQ(timesurface.at(2, 2, 0), 0); @@ -195,62 +157,13 @@ TEST_F(TimesurfaceProducerAlgorithmGTest, test_output_n_mixed_events_two_channel ASSERT_EQ(timesurface.at(2, 2, 1), 0); } -TEST_F(TimesurfaceProducerAlgorithmGTest, test_output_n_us) { - Metavision::TimeSurfaceProducerAlgorithm<1> producer(3, 3); - Metavision::timestamp ts; - Metavision::MostRecentTimestampBuffer timesurface; - - producer.set_output_callback([&ts, ×urface](Metavision::timestamp output_ts, - const Metavision::MostRecentTimestampBuffer &output_timesurface) { - ts = output_ts; - timesurface = output_timesurface; - }); - - // GIVEN - // - a producer that produces a time surface every 5us, and - // - a buffer of 5us of events - producer.set_processing_n_us(5); - - std::vector events = {{0, 0, 1, 0}, {1, 0, 0, 1}, {2, 0, 1, 2}, - {0, 1, 1, 3}, {1, 1, 0, 4}, {2, 1, 1, 5}}; - - // WHEN - // We process the events - producer.process_events(events.cbegin(), events.cend()); - - // THEN - // One time surface is produced and - // |0 1 2| - // timesurface = |3 4 0| - // |0 0 0| - ASSERT_EQ(ts, 5); - ASSERT_EQ(timesurface.at(0, 0), 0); - ASSERT_EQ(timesurface.at(0, 1), 1); - ASSERT_EQ(timesurface.at(0, 2), 2); - ASSERT_EQ(timesurface.at(1, 0), 3); - ASSERT_EQ(timesurface.at(1, 1), 4); - ASSERT_EQ(timesurface.at(1, 2), 0); - ASSERT_EQ(timesurface.at(2, 0), 0); - ASSERT_EQ(timesurface.at(2, 1), 0); - ASSERT_EQ(timesurface.at(2, 2), 0); -} - -TEST_F(TimesurfaceProducerAlgorithmGTest, test_keeping_history) { - Metavision::TimeSurfaceProducerAlgorithm<1> producer(3, 3); - Metavision::timestamp ts; - Metavision::MostRecentTimestampBuffer timesurface; - - producer.set_output_callback([&ts, ×urface](Metavision::timestamp output_ts, - const Metavision::MostRecentTimestampBuffer &output_timesurface) { - ts = output_ts; - timesurface = output_timesurface; - }); +TEST_F(TimeSurfaceProcessorGTest, test_keeping_history) { + Metavision::TimeSurfaceProcessor producer(3, 3); + Metavision::MostRecentTimestampBuffer timesurface(3, 3, 1); // GIVEN - // - a producer that produces a time surface every 4 events, and + // - a producer that produces a time surface, and // - a buffer of 9 events - producer.set_processing_n_events(4); - // clang-format off std::vector events = {{0, 0, 0, 0}, {1, 0, 0, 1}, {2, 0, 1, 2}, {0, 1, 1, 3}, {1, 1, 1, 4}, {2, 1, 0, 5}, @@ -259,14 +172,13 @@ TEST_F(TimesurfaceProducerAlgorithmGTest, test_keeping_history) { // WHEN // We process the events - producer.process_events(events.cbegin(), events.cend()); + producer.process_events(events.cbegin(), events.cend(), timesurface); // THEN // Two copies of the internal time surface are done and the last // |0 1 2| |0 0 0| // timesurface = |3 4 5| and not |0 4 5| - // |6 7 0| |6 7 0| - ASSERT_EQ(ts, 7); + // |6 7 8| |6 7 0| ASSERT_EQ(timesurface.at(0, 0), 0); ASSERT_EQ(timesurface.at(0, 1), 1); ASSERT_EQ(timesurface.at(0, 2), 2); @@ -275,5 +187,5 @@ TEST_F(TimesurfaceProducerAlgorithmGTest, test_keeping_history) { ASSERT_EQ(timesurface.at(1, 2), 5); ASSERT_EQ(timesurface.at(2, 0), 6); ASSERT_EQ(timesurface.at(2, 1), 7); - ASSERT_EQ(timesurface.at(2, 2), 0); -} \ No newline at end of file + ASSERT_EQ(timesurface.at(2, 2), 8); +} diff --git a/sdk/modules/core/python/bindings/CMakeLists.txt b/sdk/modules/core/python/bindings/CMakeLists.txt index c3e3a52c1..4cae5673a 100644 --- a/sdk/modules/core/python/bindings/CMakeLists.txt +++ b/sdk/modules/core/python/bindings/CMakeLists.txt @@ -10,8 +10,11 @@ set(sdk_core_python_srcs ${CMAKE_CURRENT_SOURCE_DIR}/adaptive_rate_events_splitter_algorithm_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/base_frame_generation_algorithm_python.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/event_bbox_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/colors_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/event_bbox_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/event_rescaler_algorithm_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/event_preprocessor_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/event_tracked_box_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/flip_x_algorithm_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/flip_y_algorithm_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/on_demand_frame_generation_algorithm_python.cpp @@ -24,7 +27,6 @@ set(sdk_core_python_srcs ${CMAKE_CURRENT_SOURCE_DIR}/rolling_buffer_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/shared_cd_events_buffer_producer_wrapper_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/stream_logger_algorithm_python.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/timesurface_producer_algorithm_python.cpp ${CMAKE_CURRENT_SOURCE_DIR}/metavision_sdk_core_bindings.cpp ) diff --git a/sdk/modules/core/python/bindings/event_preprocessor_python.cpp b/sdk/modules/core/python/bindings/event_preprocessor_python.cpp new file mode 100644 index 000000000..2a47f0010 --- /dev/null +++ b/sdk/modules/core/python/bindings/event_preprocessor_python.cpp @@ -0,0 +1,315 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/base/events/event_cd.h" +#include "metavision/sdk/core/preprocessors/event_preprocessor.h" +#include "metavision/sdk/core/preprocessors/diff_processor.h" +#include "metavision/sdk/core/preprocessors/hardware_diff_processor.h" +#include "metavision/sdk/core/preprocessors/hardware_histo_processor.h" +#include "metavision/sdk/core/preprocessors/histo_processor.h" +#include "metavision/sdk/core/preprocessors/event_cube_processor.h" +#include "metavision/sdk/core/preprocessors/time_surface_processor.h" + +#include "metavision/utils/pybind/pod_event_buffer.h" +#include "metavision/utils/pybind/sync_algorithm_process_helper.h" + +#include "pb_doc_core.h" + +#include +#include +#include + +namespace py = pybind11; + +namespace { + +using ArrayIt = typename Metavision::EventCD *; +using EventPreprocessorArray = Metavision::EventPreprocessor; + +bool are_same_type(const py::buffer_info &b, Metavision::BaseType t) { + switch (t) { + case Metavision::BaseType::BOOL: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::UINT8: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::UINT16: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::UINT32: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::UINT64: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::INT8: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::INT16: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::INT32: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::INT64: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::FLOAT32: + return py::detail::compare_buffer_info::compare(b); + case Metavision::BaseType::FLOAT64: + return py::detail::compare_buffer_info::compare(b); + default: + throw std::runtime_error("No comparison available for type " + Metavision::to_string(t)); + } +}; + +std::string compute_descriptor(Metavision::BaseType t) { + switch (t) { + case Metavision::BaseType::BOOL: + return py::format_descriptor::format(); + case Metavision::BaseType::UINT8: + return py::format_descriptor::format(); + case Metavision::BaseType::UINT16: + return py::format_descriptor::format(); + case Metavision::BaseType::UINT32: + return py::format_descriptor::format(); + case Metavision::BaseType::UINT64: + return py::format_descriptor::format(); + case Metavision::BaseType::INT8: + return py::format_descriptor::format(); + case Metavision::BaseType::INT16: + return py::format_descriptor::format(); + case Metavision::BaseType::INT32: + return py::format_descriptor::format(); + case Metavision::BaseType::INT64: + return py::format_descriptor::format(); + case Metavision::BaseType::FLOAT32: + return py::format_descriptor::format(); + case Metavision::BaseType::FLOAT64: + return py::format_descriptor::format(); + default: + throw std::runtime_error("No description available for type " + Metavision::to_string(t)); + } +} + +void EventPreprocessorArray_check_output_frame_validity(const EventPreprocessorArray &cdproc, py::array &frame_np) { + const auto info_frame = frame_np.request(); + const auto &shape = cdproc.get_output_shape(); + const auto &dimensions = shape.dimensions; + const size_t nb_dim = dimensions.size(); + if (info_frame.ndim != static_cast(nb_dim)) { + std::ostringstream oss; + oss << "Frame dim should be " << nb_dim << ". frame_np.ndim : " << info_frame.ndim << std::endl; + throw std::runtime_error(oss.str()); + } + const auto type_descr = compute_descriptor(cdproc.get_output_type()); + if (!are_same_type(info_frame, cdproc.get_output_type())) { + std::ostringstream oss; + oss << "Frame type don't match ! Got py array " << info_frame.format << " but expected " << type_descr + << std::endl; + throw std::runtime_error(oss.str()); + } + if (static_cast(info_frame.size) != shape.get_nb_values()) { + std::ostringstream oss; + oss << "Frame size should be: " << shape.get_nb_values(); + oss << ". frame_np.size: " << info_frame.size << std::endl; + throw std::runtime_error(oss.str()); + } + for (unsigned int i = 0; i < nb_dim; ++i) { + if (dimensions[i].dim != static_cast(info_frame.shape[i])) { + std::stringstream msg; + msg << "Incompatible dimension " << i << ". Expected " << dimensions[i].dim << " but got " + << info_frame.shape[i] << std::endl; + throw std::runtime_error(msg.str()); + } + } +} + +void EventPreprocessorArray_process_events_array(const EventPreprocessorArray &cdproc, + const Metavision::timestamp cur_frame_start_ts, + const py::array_t &events, py::array &frame_np) { + const auto info_events = events.request(); + if (info_events.ndim != 1) { + throw std::runtime_error("Wrong events dim"); + } + const auto events_ptr = static_cast(info_events.ptr); + const int nb_events = info_events.shape[0]; + + EventPreprocessorArray_check_output_frame_validity(cdproc, frame_np); + auto info_frame = frame_np.request(); + + Metavision::Tensor t(cdproc.get_output_shape(), cdproc.get_output_type(), + reinterpret_cast(info_frame.ptr), false); + cdproc.process_events(cur_frame_start_ts, events_ptr, events_ptr + nb_events, t); +} + +template +py::array_t produce_array(const Metavision::TensorShape &shape, const Metavision::BaseType type) { + const auto &dimensions = shape.dimensions; + auto frame_np = py::array_t({dimensions[0].dim, dimensions[1].dim, dimensions[2].dim}); + memset(frame_np.request().ptr, 0, shape.get_nb_values() * sizeof(T)); + return frame_np; +} + +py::array EventPreprocessorArray_init_output_tensor(const EventPreprocessorArray &cdproc) { + const auto &shape = cdproc.get_output_shape(); + const auto &type = cdproc.get_output_type(); + switch (type) { + case Metavision::BaseType::BOOL: + return produce_array(shape, type); + case Metavision::BaseType::UINT8: + return produce_array(shape, type); + case Metavision::BaseType::UINT16: + return produce_array(shape, type); + case Metavision::BaseType::UINT32: + return produce_array(shape, type); + case Metavision::BaseType::UINT64: + return produce_array(shape, type); + case Metavision::BaseType::INT8: + return produce_array(shape, type); + case Metavision::BaseType::INT16: + return produce_array(shape, type); + case Metavision::BaseType::INT32: + return produce_array(shape, type); + case Metavision::BaseType::INT64: + return produce_array(shape, type); + case Metavision::BaseType::FLOAT32: + return produce_array(shape, type); + case Metavision::BaseType::FLOAT64: + return produce_array(shape, type); + default: + throw std::runtime_error("No implementation for type " + Metavision::to_string(type)); + }; +} + +// End Helpers for EventPreprocessor + +// Helpers factory +EventPreprocessorArray *create_EventPreprocessorArrayDiff(int event_input_width, int event_input_height, + float max_incr_per_pixel, + float clip_value_after_normalization, float width_scale = 1.f, + float height_scale = 1.f) { + return new Metavision::DiffProcessor(event_input_width, event_input_height, max_incr_per_pixel, + clip_value_after_normalization, width_scale, height_scale); +} + +EventPreprocessorArray *create_EventPreprocessorArrayHisto(int event_input_width, int event_input_height, + float max_incr_per_pixel, + float clip_value_after_normalization, bool use_CHW = true, + float width_scale = 1.f, float height_scale = 1.f) { + return new Metavision::HistoProcessor(event_input_width, event_input_height, max_incr_per_pixel, + clip_value_after_normalization, use_CHW, width_scale, height_scale); +} + +EventPreprocessorArray *create_EventPreprocessorArrayEventCube(Metavision::timestamp delta_t, int event_input_width, + int event_input_height, int num_utbins, + bool split_polarity, float max_incr_per_pixel, + float clip_value_after_normalization = 0.f, + float width_scale = 1.f, float height_scale = 1.f) { + return new Metavision::EventCubeProcessor(delta_t, event_input_width, event_input_height, num_utbins, + split_polarity, max_incr_per_pixel, + clip_value_after_normalization, width_scale, height_scale); +} + +EventPreprocessorArray *create_EventPreprocessorArrayHardwareDiff(int sensor_width, int sensor_height, int8_t min_val, + int8_t max_val, bool allow_rollover = true) { + return new Metavision::HardwareDiffProcessor(sensor_width, sensor_height, min_val, max_val, + allow_rollover); +} + +EventPreprocessorArray *create_EventPreprocessorArrayHardwareHisto(int sensor_width, int sensor_height, + uint8_t neg_saturation = 255, + uint8_t pos_saturation = 255) { + return new Metavision::HardwareHistoProcessor(sensor_width, sensor_height, neg_saturation, pos_saturation); +} + +EventPreprocessorArray *create_EventPreprocessorArrayTimeSurface(int sensor_width, int sensor_height, + bool split_polarity = true) { + if (split_polarity) + return new Metavision::TimeSurfaceProcessorSplitPolarities(sensor_width, sensor_height); + else + return new Metavision::TimeSurfaceProcessorMergePolarities(sensor_width, sensor_height); +} + +// End Helpers factory + +} // namespace + +namespace Metavision { + +void export_event_preprocessor(py::module &m) { + py::class_(m, "EventPreprocessor", pybind_doc_core["Metavision::EventPreprocessor"]) + .def_static("create_DiffProcessor", &create_EventPreprocessorArrayDiff, py::arg("input_event_width"), + py::arg("input_event_height"), py::arg("max_incr_per_pixel") = 5, + py::arg("clip_value_after_normalization") = 1.0, py::arg("scale_width") = 1.f, + py::arg("scale_height") = 1.f, pybind_doc_core["Metavision::DiffProcessor::DiffProcessor"]) + .def_static("create_HistoProcessor", &create_EventPreprocessorArrayHisto, py::arg("input_event_width"), + py::arg("input_event_height"), py::arg("max_incr_per_pixel") = 5, + py::arg("clip_value_after_normalization") = 1.0, py::arg("use_CHW") = true, + py::arg("scale_width") = 1.f, py::arg("scale_height") = 1.f, + pybind_doc_core["Metavision::HistoProcessor::HistoProcessor"]) + .def_static("create_EventCubeProcessor", &create_EventPreprocessorArrayEventCube, py::arg("delta_t"), + py::arg("input_event_width"), py::arg("input_event_height"), py::arg("num_utbins"), + py::arg("split_polarity"), py::arg("max_incr_per_pixel") = 63.75, + py::arg("clip_value_after_normalization") = 1.0, py::arg("scale_width") = 1.f, + py::arg("scale_height") = 1.f, + pybind_doc_core["Metavision::EventCubeProcessor::EventCubeProcessor"]) + .def_static("create_HardwareDiffProcessor", &create_EventPreprocessorArrayHardwareDiff, + py::arg("input_event_width"), py::arg("input_event_height"), py::arg("min_val"), py::arg("max_val"), + py::arg("allow_rollover") = true, + pybind_doc_core["Metavision::HardwareDiffProcessor::HardwareDiffProcessor"]) + .def_static("create_HardwareHistoProcessor", &create_EventPreprocessorArrayHardwareHisto, + py::arg("input_event_width"), py::arg("input_event_height"), py::arg("neg_saturation") = 255, + py::arg("pos_saturation") = 255, + pybind_doc_core["Metavision::HardwareHistoProcessor::HardwareHistoProcessor"]) + .def_static("create_TimeSurfaceProcessor", &create_EventPreprocessorArrayTimeSurface, + py::arg("input_event_width"), py::arg("input_event_height"), py::arg("split_polarity") = true, + R"doc( + Creates a TimeSurfaceProcessor instance. + + :input_event_width: Width of the input event stream. + :input_event_height: Height of the input event stream. + :split_polarity: (optional) If True, polarities will be managed separately in the + TimeSurface. Else, a single channel will be used for both + polarities. + )doc") + .def("init_output_tensor", &EventPreprocessorArray_init_output_tensor, py::return_value_policy::move) + .def("process_events", &EventPreprocessorArray_process_events_array, py::arg("cur_frame_start_ts"), + py::arg("events_np"), py::arg("frame_tensor_np"), + "Takes a chunk of events (numpy array of EventCD) and updates the frame_tensor (numpy array of float)") + .def( + "get_frame_size", + [](const EventPreprocessorArray &cdproc) { return cdproc.get_output_shape().get_nb_values(); }, + "Returns the number of values in the output frame.") + .def( + "get_frame_width", + [](const EventPreprocessorArray &cdproc) { return get_dim(cdproc.get_output_shape(), "W"); }, + "Returns the width of the output frame.") + .def( + "get_frame_height", + [](const EventPreprocessorArray &cdproc) { return get_dim(cdproc.get_output_shape(), "H"); }, + "Returns the height of the output frame.") + .def( + "get_frame_channels", + [](const EventPreprocessorArray &cdproc) { return get_dim(cdproc.get_output_shape(), "C"); }, + "Returns the number of channels of the output frame.") + .def( + "get_frame_shape", + [](const EventPreprocessorArray &cdproc) { + const auto &dimensions = cdproc.get_output_shape().dimensions; + std::vector shape; + for (const auto &dim : dimensions) + shape.push_back(dim.dim); + return shape; + }, + "Returns the frame shape.") + .def( + "is_CHW", + [](const EventPreprocessorArray &cdproc) { + const auto &dimensions = cdproc.get_output_shape().dimensions; + return dimensions[0].name == "C" && dimensions[1].name == "H" && dimensions[2].name == "W"; + }, + "Returns true if the output tensor shape has CHW layout."); +} + +} // namespace Metavision diff --git a/sdk/modules/core/python/bindings/event_rescaler_algorithm_python.cpp b/sdk/modules/core/python/bindings/event_rescaler_algorithm_python.cpp new file mode 100644 index 000000000..2b70697e1 --- /dev/null +++ b/sdk/modules/core/python/bindings/event_rescaler_algorithm_python.cpp @@ -0,0 +1,36 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/base/events/event_cd.h" +#include "metavision/utils/pybind/sync_algorithm_process_helper.h" +#include "metavision/sdk/core/algorithms/event_rescaler_algorithm.h" +#include "pb_doc_core.h" + +namespace Metavision { + +void export_event_rescaler_algorithm(py::module &m) { + py::class_(m, "EventRescalerAlgorithm", + pybind_doc_core["Metavision::EventRescalerAlgorithm"]) + .def(py::init(), py::arg("scale_width"), py::arg("scale_height"), + pybind_doc_core["Metavision::EventRescalerAlgorithm::EventRescalerAlgorithm"]) + .def("process_events", &process_events_array_sync, py::arg("input_np"), + py::arg("output_buf"), doc_process_events_array_sync_str) + .def("process_events", &process_events_buffer_sync, py::arg("input_buf"), + py::arg("output_buf"), doc_process_events_buffer_sync_str) + .def("process_events_", &process_events_array_sync_inplace, + py::arg("events_np"), doc_process_events_array_sync_inplace_str) + .def_static("get_empty_output_buffer", &getEmptyPODBuffer, doc_get_empty_output_buffer_str); +} + +} // namespace Metavision diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/geometry.h b/sdk/modules/core/python/bindings/event_tracked_box_python.cpp similarity index 67% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/geometry.h rename to sdk/modules/core/python/bindings/event_tracked_box_python.cpp index ee5cb0d70..3a44ba521 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/geometry.h +++ b/sdk/modules/core/python/bindings/event_tracked_box_python.cpp @@ -9,35 +9,23 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_GEOMETRY_H -#define METAVISION_SDK_DRIVER_GEOMETRY_H +#include +#include -#include "metavision/hal/facilities/i_geometry.h" +#include "metavision/sdk/core/events/event_tracked_box.h" +#include "metavision/utils/pybind/pod_event_buffer.h" -namespace Metavision { - -/// @brief Facility class to get the geometry of a Device -class Geometry { -public: - /// @brief Constructor - Geometry(I_Geometry *geom); - - /// @brief Destructor - ~Geometry(); +namespace py = pybind11; - /// @brief Width of the sensor - int width() const; - - /// @brief Height of the sensor - int height() const; +namespace Metavision { - /// @brief Gets corresponding facility in HAL library - I_Geometry *get_facility() const; +void export_event_tracked_box(py::module &m) { + PYBIND11_NUMPY_DTYPE(EventTrackedBox, t, x, y, w, h, class_id, track_id, class_confidence, tracking_confidence, + last_detection_update_time, nb_detections); + py::array_t array; + m.attr("EventTrackedBox") = array.dtype(); -private: - I_Geometry *pimpl_; -}; + Metavision::export_PODEventBuffer(m, "EventTrackedBoxBuffer"); +} } // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_GEOMETRY_H diff --git a/sdk/modules/core/python/bindings/metavision_sdk_core_bindings.cpp b/sdk/modules/core/python/bindings/metavision_sdk_core_bindings.cpp index c991251a8..f52cb8a86 100644 --- a/sdk/modules/core/python/bindings/metavision_sdk_core_bindings.cpp +++ b/sdk/modules/core/python/bindings/metavision_sdk_core_bindings.cpp @@ -40,7 +40,10 @@ PythonBindingsDoc pybind_doc_core; #endif void export_event_bbox(py::module &); +void export_event_tracked_box(py::module &); void export_base_frame_generation_algorithm(py::module &); +void export_event_preprocessor(py::module &); +void export_event_rescaler_algorithm(py::module &m); void export_colors(py::module &); void export_adaptive_rate_events_splitter_algorithm(py::module &); void export_flip_x_algorithm(py::module &); @@ -54,7 +57,6 @@ void export_raw_event_frame_converter(py::module &); void export_roi_filter_algorithm(py::module &); void export_shared_cd_events_buffer_producer(py::module &); void export_stream_logger_algorithm(py::module &); -void export_timesurface_producer_algorithm(py::module &); void export_rolling_event_cd_buffer(py::module &); } // namespace Metavision @@ -74,12 +76,15 @@ PYBIND11_MODULE(MODULE_NAME, m) { // 2. Export event types Metavision::export_event_bbox(m); + Metavision::export_event_tracked_box(m); Metavision::export_colors(m); Metavision::export_mostrecent_timestamp_buffer(m); // 3. Export algos Metavision::export_base_frame_generation_algorithm(m); Metavision::export_adaptive_rate_events_splitter_algorithm(m); + Metavision::export_event_preprocessor(m); + Metavision::export_event_rescaler_algorithm(m); Metavision::export_flip_x_algorithm(m); Metavision::export_flip_y_algorithm(m); Metavision::export_on_demand_frame_generation_algorithm(m); @@ -90,7 +95,6 @@ PYBIND11_MODULE(MODULE_NAME, m) { Metavision::export_roi_filter_algorithm(m); Metavision::export_shared_cd_events_buffer_producer(m); Metavision::export_stream_logger_algorithm(m); - Metavision::export_timesurface_producer_algorithm(m); // 4. Export utils Metavision::export_rolling_event_cd_buffer(m); diff --git a/sdk/modules/core/python/bindings/mostrecent_timestamp_buffer_python.cpp b/sdk/modules/core/python/bindings/mostrecent_timestamp_buffer_python.cpp index 293bb5d81..c25232300 100644 --- a/sdk/modules/core/python/bindings/mostrecent_timestamp_buffer_python.cpp +++ b/sdk/modules/core/python/bindings/mostrecent_timestamp_buffer_python.cpp @@ -21,10 +21,7 @@ namespace Metavision { namespace { py::array_t numpy_time_surface_helper(MostRecentTimestampBuffer &time_surface, bool copy = false) { - std::vector shape = {time_surface.rows(), time_surface.cols()}; - if (time_surface.channels() != 1) - shape.emplace_back(time_surface.channels()); - + std::vector shape = {time_surface.rows(), time_surface.cols(), time_surface.channels()}; if (time_surface.empty() || copy) return py::array_t(shape, time_surface.ptr()); diff --git a/sdk/modules/core/python/bindings/periodic_frame_generation_algorithm_python.cpp b/sdk/modules/core/python/bindings/periodic_frame_generation_algorithm_python.cpp index 66498608e..9d03bebdc 100644 --- a/sdk/modules/core/python/bindings/periodic_frame_generation_algorithm_python.cpp +++ b/sdk/modules/core/python/bindings/periodic_frame_generation_algorithm_python.cpp @@ -61,14 +61,14 @@ void export_periodic_frame_generation_algorithm(py::module &m) { if (frame->channels() == 1) { pybind11::array::StridesContainer strides( - {static_cast(frame->step), static_cast(frame->elemSize1())}); + {static_cast(frame->step), static_cast(frame->elemSize1())}); pybind11::array::ShapeContainer shape({frame->rows, frame->cols}); py::array py_array(py::dtype::of(), shape, strides, frame->data, capsule); object(ts, py_array); } else if (frame->channels() == 3) { - pybind11::array::StridesContainer strides({static_cast(frame->step), - static_cast(frame->channels()), - static_cast(frame->elemSize1())}); + pybind11::array::StridesContainer strides({static_cast(frame->step), + static_cast(frame->channels()), + static_cast(frame->elemSize1())}); pybind11::array::ShapeContainer shape({frame->rows, frame->cols, 3}); py::array py_array(py::dtype::of(), shape, strides, frame->data, capsule); object(ts, py_array); diff --git a/sdk/modules/core/python/bindings/timesurface_producer_algorithm_python.cpp b/sdk/modules/core/python/bindings/timesurface_producer_algorithm_python.cpp deleted file mode 100644 index 2e19a8f83..000000000 --- a/sdk/modules/core/python/bindings/timesurface_producer_algorithm_python.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/base/events/event_cd.h" -#include "metavision/utils/pybind/sync_algorithm_process_helper.h" -#include "metavision/utils/pybind/async_algorithm_process_helper.h" -#include "metavision/sdk/core/algorithms/time_surface_producer_algorithm.h" -#include "pb_doc_core.h" - -namespace Metavision { - -void export_timesurface_producer_algorithm(py::module &m) { - using TimeSurfaceProducerAlgorithmMergePolarities = TimeSurfaceProducerAlgorithm<1>; - - const std::string tsa = pybind_doc_core["Metavision::TimeSurfaceProducerAlgorithm"]; - const std::string ts_doc_merge_pol_end = - "This timesurface contains only one channel (events with different polarities are stored all together " - "in the same channel).\n" - "To use separate channels for polarities, use TimeSurfaceProducerAlgorithmSplitPolarities instead\n"; - const std::string ts_doc_mege_pol_full = tsa + "\n\n" + ts_doc_merge_pol_end; - - py::class_(m, "TimeSurfaceProducerAlgorithmMergePolarities", - ts_doc_mege_pol_full.c_str()) - .def(py::init(), py::arg("width"), py::arg("height"), - pybind_doc_core["Metavision::TimeSurfaceProducerAlgorithm::TimeSurfaceProducerAlgorithm"]) - .def( - "set_output_callback", - [](TimeSurfaceProducerAlgorithmMergePolarities &algo, const py::object &object) { - TimeSurfaceProducerAlgorithmMergePolarities::OutputCb cb = - [object](timestamp ts, const MostRecentTimestampBuffer &most_recent_timestamp_buffer) { - assert(most_recent_timestamp_buffer.channels() == 1); - object(ts, most_recent_timestamp_buffer); - }; - algo.set_output_callback(cb); - }, - "Sets a callback to retrieve the produced time surface") - .def("process_events", &process_events_array_async, - py::arg("events_np"), doc_process_events_array_async_str); - - using TimeSurfaceProducerAlgorithmSplitPolarities = TimeSurfaceProducerAlgorithm<2>; - - const std::string ts_doc_split_pol_end = - "This timesurface contains two channels (events with different polarities are stored in separate channels\n" - "To use single channel, use TimeSurfaceProducerAlgorithmMergePolarities instead\n"; - const std::string ts_doc_split_pol_full = tsa + "\n\n" + ts_doc_split_pol_end; - - py::class_(m, "TimeSurfaceProducerAlgorithmSplitPolarities", - ts_doc_split_pol_full.c_str()) - .def(py::init(), py::arg("width"), py::arg("height"), - pybind_doc_core["Metavision::TimeSurfaceProducerAlgorithm::TimeSurfaceProducerAlgorithm"]) - .def( - "set_output_callback", - [](TimeSurfaceProducerAlgorithmSplitPolarities &algo, const py::object &object) { - TimeSurfaceProducerAlgorithmSplitPolarities::OutputCb cb = - [object](timestamp ts, const MostRecentTimestampBuffer &most_recent_timestamp_buffer) { - assert(most_recent_timestamp_buffer.channels() == 2); - object(ts, most_recent_timestamp_buffer); - }; - algo.set_output_callback(cb); - }, - "Sets a callback to retrieve the produced time surface") - .def("process_events", &process_events_array_async, - py::arg("events_np"), doc_process_events_array_async_str); -} - -} // namespace Metavision diff --git a/sdk/modules/core/python/samples/metavision_adaptive_rate/metavision_adaptive_rate_events_splitter.py b/sdk/modules/core/python/samples/metavision_adaptive_rate/metavision_adaptive_rate_events_splitter.py index 1ef59ce8e..ed35c6494 100644 --- a/sdk/modules/core/python/samples/metavision_adaptive_rate/metavision_adaptive_rate_events_splitter.py +++ b/sdk/modules/core/python/samples/metavision_adaptive_rate/metavision_adaptive_rate_events_splitter.py @@ -12,6 +12,10 @@ import numpy as np import cv2 import os +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ from skvideo.io import FFmpegWriter @@ -40,7 +44,7 @@ def events_to_diff_image(events, sensor_size, strict_coord=True): return img -def split_into_frames(filename_raw, thr_var_per_event=5e-4, downsampling_factor=2, disable_display=False, +def split_into_frames(input_event_file, thr_var_per_event=5e-4, downsampling_factor=2, disable_display=False, filename_output_video=None): """ This function loads a sequence, splits it into sharp event frames, and displays the result @@ -53,7 +57,7 @@ def split_into_frames(filename_raw, thr_var_per_event=5e-4, downsampling_factor= dropping some of the frames to cope with limited computational budget (detection). Args: - filename_raw (str): input sequence filename to process + input_event_file (str): path to input event file (RAW or HDF5) to process thr_var_per_event (float): minimum variance per event to reach before generating a new frame downsampling_factor (int): reduction factor to apply to input frame. Original coordinates will be multiplied by 2**(-downsampling_factor) @@ -64,7 +68,7 @@ def split_into_frames(filename_raw, thr_var_per_event=5e-4, downsampling_factor= assert downsampling_factor == int(downsampling_factor), "Error: downsampling_factor must be an integer" assert downsampling_factor >= 0, "Error: downsampling_factor must be >= 0" - mv_adaptive_rate_iterator = AdaptiveRateEventsIterator(input_path=filename_raw, + mv_adaptive_rate_iterator = AdaptiveRateEventsIterator(input_path=input_event_file, thr_var_per_event=thr_var_per_event, downsampling_factor=downsampling_factor) diff --git a/sdk/modules/core/python/samples/metavision_event_frame_viewer/metavision_event_frame_viewer.py b/sdk/modules/core/python/samples/metavision_event_frame_viewer/metavision_event_frame_viewer.py index 47100e6f2..8566197a3 100644 --- a/sdk/modules/core/python/samples/metavision_event_frame_viewer/metavision_event_frame_viewer.py +++ b/sdk/modules/core/python/samples/metavision_event_frame_viewer/metavision_event_frame_viewer.py @@ -17,6 +17,10 @@ import os import numpy as np import cv2 +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ from skvideo.io import FFmpegWriter diff --git a/sdk/modules/core/python/samples/metavision_time_surface/metavision_time_surface.py b/sdk/modules/core/python/samples/metavision_time_surface/metavision_time_surface.py index cf89e94f1..0e068d057 100644 --- a/sdk/modules/core/python/samples/metavision_time_surface/metavision_time_surface.py +++ b/sdk/modules/core/python/samples/metavision_time_surface/metavision_time_surface.py @@ -12,7 +12,7 @@ """ from metavision_core.event_io import EventsIterator, LiveReplayEventsIterator, is_live_camera -from metavision_sdk_core import TimeSurfaceProducerAlgorithmMergePolarities, MostRecentTimestampBuffer +from metavision_sdk_core import EventPreprocessor, MostRecentTimestampBuffer from metavision_sdk_ui import EventLoop, BaseWindow, MTWindow, UIAction, UIKeyEvent import numpy as np import cv2 @@ -55,27 +55,24 @@ def keyboard_cb(key, scancode, action, mods): window.set_keyboard_callback(keyboard_cb) time_surface = MostRecentTimestampBuffer(rows=height, cols=width, channels=1) - ts_prod = TimeSurfaceProducerAlgorithmMergePolarities(width=width, height=height) + ts_prod = EventPreprocessor.create_TimeSurfaceProcessor(input_event_width=width, input_event_height=height, split_polarity=False) - def cb_time_surface(timestamp, data): - nonlocal last_processed_timestamp - nonlocal time_surface - last_processed_timestamp = timestamp - time_surface = data - - ts_prod.set_output_callback(cb_time_surface) img = np.empty((height, width), dtype=np.uint8) # Process events for evs in mv_iterator: # Dispatch system events to the window EventLoop.poll_and_dispatch() - ts_prod.process_events(evs) + if len(evs) == 0: + continue + ts_prod.process_events(cur_frame_start_ts=evs[0][3], events_np=evs, frame_tensor_np=time_surface.numpy()) + last_processed_timestamp = evs[-1][3] time_surface.generate_img_time_surface(last_processed_timestamp, 10000, img) window.show_async(cv2.applyColorMap(img, cv2.COLORMAP_JET)) if window.should_close(): break + if __name__ == "__main__": main() diff --git a/sdk/modules/core/python/tests/extended_events_iterator_pytest.py b/sdk/modules/core/python/tests/extended_events_iterator_pytest.py index a88dd9a42..599a15a8f 100644 --- a/sdk/modules/core/python/tests/extended_events_iterator_pytest.py +++ b/sdk/modules/core/python/tests/extended_events_iterator_pytest.py @@ -14,20 +14,15 @@ import numpy as np import pytest -try: - test_dir_path = os.path.dirname(os.path.realpath(__file__)) - sample_dir_path = os.path.join(test_dir_path, '..', 'samples', 'metavision_interop') - assert os.path.isdir(sample_dir_path) - import sys - sys.path.append(sample_dir_path) - from extended_events_iterator import ExtendedEventsIterator - imports_error = False -except ImportError as e: - print(e) - imports_error = True - - -@pytest.mark.skipif(imports_error, reason="Could not import ExtendedEventsIterator") +test_dir_path = os.path.dirname(os.path.realpath(__file__)) +sample_dir_path = os.path.join(test_dir_path, '..', 'samples', 'metavision_interop') +assert os.path.isdir(sample_dir_path) +import sys +sys.path.append(sample_dir_path) + +from extended_events_iterator import ExtendedEventsIterator + + def pytestcase_iterator_csv_zip_eth(dataset_dir): """Tests initialization of all member variables after creation of RawReader object from a file""" # GIVEN diff --git a/sdk/modules/core/python/tests/metavision_sdk_core_bindings_pytest.py b/sdk/modules/core/python/tests/metavision_sdk_core_bindings_pytest.py index 4ec14eda8..bfb1cc5a5 100644 --- a/sdk/modules/core/python/tests/metavision_sdk_core_bindings_pytest.py +++ b/sdk/modules/core/python/tests/metavision_sdk_core_bindings_pytest.py @@ -7,13 +7,165 @@ # 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. +import os +import pytest + import numpy as np import metavision_sdk_base import metavision_sdk_core +from metavision_core.event_io import EventsIterator, EventDatReader # pylint: disable=no-member +def get_cd_events_filename(dataset_dir): + filename_cd_events = os.path.join( + dataset_dir, + "openeb", "core", "event_io", "recording_td.dat") + assert os.path.isfile(filename_cd_events) + return filename_cd_events + + +def pytestcase_EventRescalerAlgorithm(): + events = np.zeros(2, dtype=metavision_sdk_base.EventCD) + events["x"] = [0, 9] + events["y"] = [0, 10] + events["t"] = [0, 10] + + evt_rescaler = metavision_sdk_core.EventRescalerAlgorithm(0.5, 0.5) + + rescaled_evts_array = evt_rescaler.get_empty_output_buffer() + evt_rescaler.process_events(events, rescaled_evts_array) + + assert(rescaled_evts_array.numpy()["x"].tolist() == [0, 4]) + assert(rescaled_evts_array.numpy()["y"].tolist() == [0, 5]) + assert(rescaled_evts_array.numpy()["t"].tolist() == [0, 10]) + + +def pytestcase_EventPreprocessor(dataset_dir): + dat_reader = EventDatReader(get_cd_events_filename(dataset_dir)) + height, width = dat_reader.get_size() + + network_input_width = int(width // 2) + network_input_height = int(height // 2) + evt_rescaler = metavision_sdk_core.EventRescalerAlgorithm( + network_input_width/float(width), network_input_height/float(height)) + evt_preproc = metavision_sdk_core.EventPreprocessor.create_HistoProcessor(input_event_width=network_input_width, + input_event_height=network_input_height, + max_incr_per_pixel=5, + clip_value_after_normalization=1.) + assert evt_preproc.get_frame_shape() == [2, 240, 320] + ev = dat_reader.load_delta_t(50000) + rescaled_evts_array = evt_rescaler.get_empty_output_buffer() + evt_rescaler.process_events(ev, rescaled_evts_array) + frame_array = evt_preproc.init_output_tensor() + evt_preproc.process_events(0, rescaled_evts_array, frame_array) + assert frame_array.shape == (2, 240, 320) + assert len(frame_array[frame_array != 0]) != 0 + assert np.max(frame_array) <= 1. + ev = dat_reader.load_delta_t(50000) + + evt_rescaler.process_events(ev, rescaled_evts_array) + frame_array.fill(0) + evt_preproc.process_events(50000, rescaled_evts_array, frame_array) + assert (frame_array.shape == (2, 240, 320)) + assert (len(frame_array[frame_array != 0]) != 0) + assert (np.max(frame_array) <= 1.) + + delta_t = 50000 + mv_it = EventsIterator(get_cd_events_filename(dataset_dir), delta_t=delta_t) + height, width = mv_it.get_size() + + network_input_width = int(width // 2) + network_input_height = int(height // 2) + evt_rescaler = metavision_sdk_core.EventRescalerAlgorithm( + network_input_width/float(width), network_input_height/float(height)) + evt_preproc = metavision_sdk_core.EventPreprocessor.create_HistoProcessor(input_event_width=network_input_width, + input_event_height=network_input_height, + max_incr_per_pixel=5, + clip_value_after_normalization=1.) + + rescaled_evts_array = evt_rescaler.get_empty_output_buffer() + frame_array = evt_preproc.init_output_tensor() + for idx, ev in enumerate(mv_it): + cur_frame_start_ts = idx * delta_t + if idx % 5 == 0: + frame_array.fill(0) + evt_rescaler.process_events(ev, rescaled_evts_array) + evt_preproc.process_events(cur_frame_start_ts, rescaled_evts_array, frame_array) + if idx >= 20: + break + + # Check with wrong parameters + frame_array_double = frame_array.astype(np.double) + with pytest.raises(RuntimeError): + mv_it = EventsIterator(get_cd_events_filename(dataset_dir), delta_t=delta_t) + for idx, ev in enumerate(mv_it): + cur_frame_start_ts = idx * delta_t + if idx % 5 == 0: + frame_array_double.fill(0) + evt_rescaler.process_events(ev, rescaled_evts_array) + evt_preproc.process_events(cur_frame_start_ts, rescaled_evts_array, + frame_array_double) # KO: frame_array should be double + if idx >= 20: + break + + frame_wrong_size = np.zeros((evt_preproc.get_frame_width(), + evt_preproc.get_frame_height() + 1, + evt_preproc.get_frame_channels()), dtype=np.float32) + + with pytest.raises(RuntimeError): + mv_it = EventsIterator(get_cd_events_filename(dataset_dir), delta_t=delta_t) + for idx, ev in enumerate(mv_it): + cur_frame_start_ts = idx * delta_t + if idx % 5 == 0: + frame_wrong_size.fill(0) + evt_rescaler.process_events(ev, rescaled_evts_array) + evt_preproc.process_events(cur_frame_start_ts, rescaled_evts_array, + frame_wrong_size) # KO: height is not correct + if idx >= 20: + break + + assert evt_preproc.get_frame_width() % 2 == 0 + frame_wrong_shape = np.zeros((evt_preproc.get_frame_width() // 2, + evt_preproc.get_frame_height() * 2, + evt_preproc.get_frame_channels()), dtype=np.float32) + assert frame_wrong_shape.size == evt_preproc.get_frame_size() + + with pytest.raises(RuntimeError): + mv_it = EventsIterator(get_cd_events_filename(dataset_dir), delta_t=delta_t) + for idx, ev in enumerate(mv_it): + cur_frame_start_ts = idx * delta_t + if idx % 5 == 0: + frame_wrong_shape.fill(0) + evt_rescaler.process_events(ev, rescaled_evts_array) + evt_preproc.process_events(cur_frame_start_ts, rescaled_evts_array, + frame_wrong_shape) # KO: shape is not correct + if idx >= 20: + break + + if evt_preproc.is_CHW(): + frame_wrong_dim_order = np.zeros((evt_preproc.get_frame_height(), + evt_preproc.get_frame_width(), + evt_preproc.get_frame_channels()), dtype=np.float32) + else: + frame_wrong_dim_order = np.zeros((evt_preproc.get_frame_channels(), + evt_preproc.get_frame_height(), + evt_preproc.get_frame_width()), dtype=np.float32) + + with pytest.raises(RuntimeError): + mv_it = EventsIterator(get_cd_events_filename(dataset_dir), delta_t=delta_t) + for idx, ev in enumerate(mv_it): + cur_frame_start_ts = idx * delta_t + if idx % 5 == 0: + frame_wrong_dim_order.fill(0) + evt_rescaler.process_events(ev, rescaled_evts_array) + evt_preproc.process_events(cur_frame_start_ts, rescaled_evts_array, + frame_wrong_dim_order) # KO: dimension order is not correct + if idx >= 20: + break + + def pytestcase_RoiFilterAlgorithm(): events = np.zeros(5, dtype=metavision_sdk_base.EventCD) events["x"] = range(10, 60, 10) @@ -258,17 +410,9 @@ def pytestcase_TimeSurfaceProducerAlgoritm(): last_processed_timestamp = 0 time_surface_single_channel = metavision_sdk_core.MostRecentTimestampBuffer(5, 5, 1) - ts_prod_single_channel = metavision_sdk_core.TimeSurfaceProducerAlgorithmMergePolarities(5, 5) + ts_prod_single_channel = metavision_sdk_core.EventPreprocessor.create_TimeSurfaceProcessor(5, 5, False) - def callback_single_channel(ts, time_surface): - nonlocal last_processed_timestamp - nonlocal time_surface_single_channel - last_processed_timestamp = ts - time_surface_single_channel.numpy()[...] = time_surface.numpy()[...] - ts_prod_single_channel.set_output_callback(callback_single_channel) - - ts_prod_single_channel.process_events(events) - assert last_processed_timestamp == 6 + ts_prod_single_channel.process_events(last_processed_timestamp, events, time_surface_single_channel.numpy()) assert (time_surface_single_channel.numpy()[1:, :] == 0).all() assert time_surface_single_channel.numpy()[0, 0] == 0 assert time_surface_single_channel.numpy()[0, 1] == 5 @@ -280,17 +424,9 @@ def callback_single_channel(ts, time_surface): last_processed_timestamp = 0 time_surface_double_channel = metavision_sdk_core.MostRecentTimestampBuffer(5, 5, 2) - ts_prod_double_channel = metavision_sdk_core.TimeSurfaceProducerAlgorithmSplitPolarities(5, 5) - - def callback_double_channel(ts, time_surface): - nonlocal last_processed_timestamp - nonlocal time_surface_double_channel - last_processed_timestamp = ts - time_surface_double_channel.numpy()[...] = time_surface.numpy()[...] - ts_prod_double_channel.set_output_callback(callback_double_channel) + ts_prod_double_channel = metavision_sdk_core.EventPreprocessor.create_TimeSurfaceProcessor(5, 5, True) - ts_prod_double_channel.process_events(events) - assert last_processed_timestamp == 6 + ts_prod_double_channel.process_events(last_processed_timestamp, events, time_surface_double_channel.numpy()) assert (time_surface_double_channel.numpy()[1:, :] == 0).all() assert (time_surface_double_channel.numpy()[0, 0] == 0).all() assert time_surface_double_channel.numpy()[0, 1].tolist() == [1, 5] diff --git a/sdk/modules/core_ml/CMakeLists.txt b/sdk/modules/core_ml/CMakeLists.txt index 6ff042a1e..6ff121ba9 100644 --- a/sdk/modules/core_ml/CMakeLists.txt +++ b/sdk/modules/core_ml/CMakeLists.txt @@ -7,6 +7,9 @@ # 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. +# Models +lfs_download("sdk/modules/core_ml/models" COMPILATION VALIDATION) + if(COMPILE_PYTHON3_BINDINGS) add_subdirectory(python) endif(COMPILE_PYTHON3_BINDINGS) diff --git a/sdk/modules/core_ml/python/models/corner_detection_10_heatmaps.ckpt b/sdk/modules/core_ml/models/corner_detection_10_heatmaps.ckpt similarity index 100% rename from sdk/modules/core_ml/python/models/corner_detection_10_heatmaps.ckpt rename to sdk/modules/core_ml/models/corner_detection_10_heatmaps.ckpt diff --git a/sdk/modules/core_ml/python/models/e2v.ckpt b/sdk/modules/core_ml/models/e2v.ckpt similarity index 100% rename from sdk/modules/core_ml/python/models/e2v.ckpt rename to sdk/modules/core_ml/models/e2v.ckpt diff --git a/sdk/modules/core_ml/python/CMakeLists.txt b/sdk/modules/core_ml/python/CMakeLists.txt index af924e6a6..e6f8664c4 100644 --- a/sdk/modules/core_ml/python/CMakeLists.txt +++ b/sdk/modules/core_ml/python/CMakeLists.txt @@ -10,10 +10,6 @@ # Cpack add_cpack_component(PUBLIC metavision-sdk-core-ml-python metavision-sdk-core-ml-python-samples) -# Models -lfs_download("sdk/modules/core_ml/python/models" COMPILATION) -lfs_download("sdk/modules/core_ml/python/models" VALIDATION) - # Add Python library add_subdirectory(pypkg) diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/image_planar_motion_stream.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/image_planar_motion_stream.py index 9232befd8..9d5781d94 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/image_planar_motion_stream.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/image_planar_motion_stream.py @@ -19,6 +19,12 @@ import cv2 from metavision_core_ml.data.camera_poses import CameraPoseGenerator +from metavision_core_ml.utils.files import is_image, is_video, is_tiff_image + +import torch +from metavision_core_ml.utils.color_utils import from_linear_rgb +import random +import skimage.io class PlanarMotionStream(object): @@ -36,21 +42,49 @@ class PlanarMotionStream(object): max_optical_flow_threshold (float): maximum optical flow between two consecutive frames max_interp_consecutive_frames (int): maximum number of interpolated frames between two consecutive frames crop_image (bool): crop images or resize them + saturation_max_factor (float): multiplicative factor of saturated pixels (only for tiff 16 bits images. Use 1.0 to disable) """ def __init__(self, image_filename, height, width, max_frames=1000, rgb=False, infinite=True, pause_probability=0.5, - max_optical_flow_threshold=2., max_interp_consecutive_frames=20, crop_image=False): + max_optical_flow_threshold=2., max_interp_consecutive_frames=20, crop_image=False, + saturation_max_factor=1.0): self.height = height self.width = width self.crop_image = crop_image self.max_frames = max_frames self.rgb = rgb self.filename = image_filename - if not self.rgb: - frame = cv2.imread(image_filename, cv2.IMREAD_GRAYSCALE) + if is_tiff_image(image_filename): + assert saturation_max_factor >= 1.0, f"Error: saturation_max_factor should be >= 1.0 for tiff images ({saturation_max_factor})" + img_tiff = skimage.io.imread(image_filename) + H, W, C = img_tiff.shape + assert C == 3 + lrgb_frame_np = (img_tiff.transpose(2, 0, 1).astype(np.float32) / (2**16 - 1))[None].astype(np.float16) + lrgb_frame = torch.from_numpy(lrgb_frame_np) + B, C, H, W = lrgb_frame.shape + assert B == 1 and C == 3 + + lab_frame = from_linear_rgb(lrgb_frame, "lab") + assert lab_frame.shape == (1, 3, H, W) + mask_saturated = lab_frame[:, [0]] >= 1. + nb_saturated_pixels = mask_saturated.sum() + if nb_saturated_pixels > 0: + lrgb_frame[0, :, mask_saturated.squeeze()] *= 1.0 + random.random() * (saturation_max_factor - 1.0) + + frame = lrgb_frame.numpy() + assert frame.ndim == 4 + assert frame.shape == (B, C, H, W) + frame = np.ascontiguousarray(frame.squeeze(axis=0).transpose(1, 2, 0)) + assert frame.shape == (H, W, C) + elif is_image(image_filename): + assert saturation_max_factor == 1.0, f"Error: saturation_max_factor should be 1.0 for non-tiff images ({saturation_max_factor})" + if not self.rgb: + frame = cv2.imread(image_filename, cv2.IMREAD_GRAYSCALE) + else: + frame = cv2.imread(image_filename)[..., ::-1] else: - frame = cv2.imread(image_filename)[..., ::-1] + raise ValueError(f"Unhandled type of file: {image_filename} (should be image or npy image)") self.frame = frame self.frame_height, self.frame_width = self.frame.shape[:2] if self.height == -1 or self.width == -1: diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/raw_image_planar_motion_stream.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/raw_image_planar_motion_stream.py new file mode 100644 index 000000000..3848c94da --- /dev/null +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/raw_image_planar_motion_stream.py @@ -0,0 +1,147 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +""" +6-DOF motion in front of image plane +All in numpy + OpenCV +Applies continuous homographies to your picture in time. +Also you can get the optical flow for this motion. +""" +from __future__ import absolute_import + +import numpy as np +import cv2 +import rawpy +import kornia +import torch +import random + +from metavision_core_ml.data.camera_poses import CameraPoseGenerator +from kornia.color import raw_to_rgb, rgb_to_raw, CFA +from metavision_core_ml.utils.color_utils import bayer2kornia + + +class RawPlanarMotionStream(object): + """ + Generates a planar motion in front of the raw image + + Returns the image as 4 channels unshuffled H/2, W/2 + + Args: + image_filename (str): path to raw image + height (int): expected height (or crop). Must be a even + width (int): expected width (or crop). Must be even + max_frames (int): number of frames to stream + bayer_pattern (str): type of bayer pattern + bpp (int): number of bits per pixel + black_level (int): black level + pause_probability (float): probability to add a pause during the stream + max_optical_flow_threshold (float): maximum optical flow between two consecutive frames + max_interp_consecutive_frames (int): maximum number of interpolated frames between two consecutive frames + """ + + def __init__(self, image_filename, height, width, max_frames=1000, + bayer_pattern="BGGR", bpp=10, black_level=0, + pause_probability=0.5, + max_optical_flow_threshold=1., max_interp_consecutive_frames=20): + assert height % 2 == 0 + assert width % 2 == 0 + self.height_unshuffled = height // 2 + self.width_unshuffled = width // 2 + self.max_frames = max_frames + self.bayer_pattern = bayer_pattern + self.bpp = bpp + self.black_level = black_level + self.max_val_raw = 2**bpp - 1 + self.filename = image_filename + raw_frame = rawpy.imread(image_filename).raw_image + assert raw_frame.min() >= 0 + assert raw_frame.max() <= self.max_val_raw + raw_frame = np.clip(raw_frame, black_level, self.max_val_raw) - black_level + + H, W = raw_frame.shape + margin_h, margin_w = (H - height) // 2, (W - width) // 2 + assert margin_h >= 0 + assert margin_w >= 0 + + self.width = width + self.height = height + + offset_h, offset_w = random.randint(0, margin_h) * 2, random.randint(0, margin_w) * 2 + self.offset_h = offset_h + self.offset_w = offset_w + raw_frame = raw_frame[offset_h:offset_h + height, offset_w:offset_w + width] + + assert raw_frame.shape == (2 * self.height_unshuffled, 2 * self.width_unshuffled) + raw_frame_th = torch.from_numpy(raw_frame.astype(np.float32)).unsqueeze(dim=0).unsqueeze(dim=0).float() / self.max_val_raw + + self.pixel_unshuffle = torch.nn.PixelUnshuffle(2) + + self.cfa = kornia.color.CFA(bayer2kornia(bayer_pattern)) + self.frame_rgb = raw_to_rgb(raw_frame_th, self.cfa) + assert self.frame_rgb.shape == (1, 3, self.height, self.width) + + self.camera = CameraPoseGenerator(self.height_unshuffled, self.width_unshuffled, self.max_frames, pause_probability, + max_optical_flow_threshold=max_optical_flow_threshold, + max_interp_consecutive_frames=max_interp_consecutive_frames) + self.iter = 0 + self.dt = np.random.randint(10000, 20000) + + + def get_unshuffled_size(self): + """ + Returns the size of the unshuffled raw frame: (1, 4, H / 2, W / 2), where (H, W) is the size of the initial raw + """ + return (self.height_unshuffled, self.width_unshuffled) + + def get_shuffled_size(self): + """ + Returns the size of the shuffled (initial) raw: (1, 1, H, W) + """ + assert self.height_unshuffled == self.height // 2 + assert self.width_unshuffled == self.width // 2 + return (2 * self.height_unshuffled, 2 * self.width_unshuffled) + + def pos_frame(self): + return self.iter + + def __len__(self): + return self.max_frames + + def __next__(self): + if self.iter >= len(self.camera): + raise StopIteration + + G_0to2, ts = self.camera() + G_0to2_th = torch.from_numpy(G_0to2).unsqueeze(dim=0).float() + + + out_rgb = kornia.geometry.warp_perspective(src=self.frame_rgb, M=G_0to2_th, + dsize=(self.height, self.width), + mode="bilinear", padding_mode="reflection") + assert out_rgb.shape == (1, 3, self.height, self.width) + + out_raw = rgb_to_raw(out_rgb, self.cfa) + assert out_raw.shape == (1, 1, self.height, self.width) + out = self.pixel_unshuffle(out_raw) + assert out.shape == (1, 4, self.height_unshuffled, self.width_unshuffled) + + self.iter += 1 + ts *= self.dt + + return out, ts + + def __iter__(self): + return self + + def get_relative_homography(self, time_step): + rvec1, tvec1 = self.camera.rvecs[time_step], self.camera.tvecs[time_step] + rvec2, tvec2 = self.camera.rvecs[self.iter-1], self.camera.tvecs[self.iter-1] + H_2_1 = self.camera.get_transform(rvec2, tvec2, rvec1, tvec1, self.height_unshuffled, self.width_unshuffled) + return H_2_1 diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/scheduling.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/scheduling.py index 459aed1b5..e207ec90e 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/scheduling.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/scheduling.py @@ -12,9 +12,13 @@ import os import random import numpy as np +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ import skvideo.io import json -from metavision_core_ml.utils.files import grab_videos, grab_images +from metavision_core_ml.utils.files import grab_videos, grab_images, grab_tiff_images class Metadata(object): @@ -92,6 +96,28 @@ def build_image_metadata(folder, min_size, max_size, denominator=1): """ paths = grab_images(folder, recursive=False) sizes = np.round(np.random.randint(min_size, max_size, size=len(paths)) / float(denominator)) * denominator + sizes = sizes.astype(np.int32) + sizes[sizes == 0] = denominator + out = [] + for path, num_frames in zip(paths, sizes): + out.append(Metadata(path, 0, num_frames)) + return out + + +def build_tiff_image_metadata(folder, min_size, max_size, denominator=1): + """ + Build Metadata from images + + Args: + folder (str): path to pictures + min_size (int): minimum number of frames + max_size (int): maximum number of frames + denominator (int): num_frames will always be a multiple of denominator. + It is used to avoid having batches that are missing some frames and need to be padded. This + happens when the number of time steps is not a multiple of num_frames. + """ + paths = grab_tiff_images(folder, recursive=True) + sizes = np.round(np.random.randint(min_size, max_size, size=len(paths)) / float(denominator)) * denominator sizes = sizes.astype(np.int) sizes[sizes == 0] = denominator out = [] @@ -132,4 +158,7 @@ def build_metadata(folder, min_length, max_length, denominator=1): if not len(metadata): print('no video, grabbing pictures') metadata = build_image_metadata(folder, min_length, max_length, denominator=denominator) + if not len(metadata): + print('no video nor image, grabbing numpy float images') + metadata = build_tiff_image_metadata(folder, min_length, max_length, denominator=denominator) return metadata diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/video_stream.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/video_stream.py index 7197c1683..79b939243 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/video_stream.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/data/video_stream.py @@ -14,6 +14,10 @@ import random import numpy as np import cv2 +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ import skvideo.io diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/event_to_video/lightning_model.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/event_to_video/lightning_model.py index 605fe618f..1bff61a12 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/event_to_video/lightning_model.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/event_to_video/lightning_model.py @@ -130,16 +130,11 @@ def validation_step(self, batch, batch_nb): logs = {'val_loss': loss} logs.update({'val_' + k: v.item() for k, v in loss_dict.items()}) - self.log('val_loss', loss) + self.log('val_loss', loss, on_epoch=True) for k, v in loss_dict.items(): self.log('val_' + k, v) return loss - def validation_epoch_end(self, outputs): - val_loss_avg = torch.FloatTensor([item for item in outputs]).mean() - self.log('val_acc', val_loss_avg) - return val_loss_avg - def configure_optimizers(self): return torch.optim.Adam(self.parameters(), lr=self.hparams.lr) diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/files.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/files.py index 06f488042..e09f297d9 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/files.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/files.py @@ -15,7 +15,7 @@ VIDEO_EXTENSIONS = [".mp4", ".mov", ".m4v", ".avi"] IMAGE_EXTENSIONS = [".jpg", ".png"] - +TIFF_IMAGE_EXTENSIONS = [".tiff", ".tif"] def is_image(path): """Checks if a path is an image @@ -40,6 +40,16 @@ def is_video(path): return os.path.splitext(path)[1].lower() in VIDEO_EXTENSIONS +def is_tiff_image(path): + """Checks if a path is a tiff image + + Args: + path: file path + Returns: + is_image (bool): True or False + """ + return os.path.splitext(path)[1].lower() in TIFF_IMAGE_EXTENSIONS + def grab_images_and_videos(adir, recursive=True): """Grabs image and video files @@ -66,6 +76,19 @@ def grab_images(adir, recursive=True): return grab_files(adir, IMAGE_EXTENSIONS, recursive=recursive) +def grab_tiff_images(adir, recursive=True): + """Grabs tiff image files + + Args: + adir: directory with tiff images + + Returns: + files: image files + """ + assert os.path.isdir(adir) + return grab_files(adir, TIFF_IMAGE_EXTENSIONS, recursive=recursive) + + def grab_h5s(adir, recursive=True): """Grabs h5 files diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/show_or_write.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/show_or_write.py index d587a4b66..83c9e9f67 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/show_or_write.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/utils/show_or_write.py @@ -10,6 +10,11 @@ This wrapper shows and/or writes a video """ import cv2 +import numpy as np +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ from skvideo.io import FFmpegWriter import os diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/simu_events_iterator.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/simu_events_iterator.py index eb6c7faa7..180810074 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/simu_events_iterator.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/simu_events_iterator.py @@ -18,6 +18,10 @@ from metavision_core_ml.data.video_stream import TimedVideoStream from metavision_sdk_core import SharedCdEventsBufferProducer as EventsBufferProducer from collections import deque +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ import skvideo.io import cv2 diff --git a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/video_stream_dataset.py b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/video_stream_dataset.py index 2b14599cd..44bc19794 100644 --- a/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/video_stream_dataset.py +++ b/sdk/modules/core_ml/python/pypkg/metavision_core_ml/video_to_event/video_stream_dataset.py @@ -16,7 +16,7 @@ from metavision_core_ml.data.image_planar_motion_stream import PlanarMotionStream from metavision_core_ml.data.stream_dataloader import StreamDataset, StreamDataLoader from metavision_core_ml.data.scheduling import build_metadata -from metavision_core_ml.utils.files import is_image, is_video +from metavision_core_ml.utils.files import is_image, is_video, is_tiff_image class VideoDatasetIterator(object): @@ -39,23 +39,26 @@ class VideoDatasetIterator(object): max_interp_consecutive_frames (int): maximum number of interpolated frames between two consecutive frames (works only with PlanarMotionStream) max_number_of_batches_to_produce (int): maximum number of batches to produce crop_image (bool): crop images or resize them + saturation_max_factor (float): multiplicative factor of saturated pixels (only for tiff 16 bits images. Use 1.0 to disable) """ def __init__(self, metadata, height, width, rgb, mode='frames', min_tbins=3, max_tbins=10, min_dt=3000, max_dt=50000, batch_times=1, pause_probability=0.5, max_optical_flow_threshold=2., max_interp_consecutive_frames=20, - max_number_of_batches_to_produce=None, crop_image=False): + max_number_of_batches_to_produce=None, crop_image=False, + saturation_max_factor=1.0): assert mode in ["frames", "delta_t", "random"] if is_video(metadata.path): self.image_stream = TimedVideoStream(metadata.path, height, width, rgb=rgb, start_frame=metadata.start_frame, max_frames=len(metadata)) - elif is_image(metadata.path): + elif is_image(metadata.path) or is_tiff_image(metadata.path): self.image_stream = PlanarMotionStream(metadata.path, height, width, len(metadata), rgb=rgb, pause_probability=pause_probability, max_optical_flow_threshold=max_optical_flow_threshold, max_interp_consecutive_frames=max_interp_consecutive_frames, - crop_image=crop_image) + crop_image=crop_image, + saturation_max_factor=saturation_max_factor) self.height = height self.width = width self.rgb = rgb @@ -106,7 +109,7 @@ def __iter__(self): assert target_indices[-1] == len(out) - 1 assert len(target_indices) == self.batch_times target_indices = torch.FloatTensor(target_indices)[None, :] # (1, self.batch_times=1) - yield sequence, timestamps, target_indices, first_time + yield sequence, timestamps, target_indices, first_time, self.metadata.path nb_batches_produced += 1 if self.max_number_of_batches_to_produce and nb_batches_produced >= self.max_number_of_batches_to_produce: @@ -128,14 +131,14 @@ def __iter__(self): assert len(target_indices) == self.batch_times target_indices = torch.FloatTensor(target_indices)[None, :] # B,T - yield sequence, timestamps, target_indices, first_time + yield sequence, timestamps, target_indices, first_time, self.metadata.path def pad_collate_fn(data_list): """ Here we pad with last image/ timestamp to get a contiguous batch """ - images, timestamps, target_indices, first_times = zip(*data_list) + images, timestamps, target_indices, first_times, metadata_paths = zip(*data_list) video_len = [item.shape[-1] for item in images] max_len = max([item.shape[-1] for item in images]) b = len(images) @@ -160,14 +163,15 @@ def pad_collate_fn(data_list): 'first_times': first_times, 'video_len': torch.tensor( video_len, - dtype=torch.int32)} + dtype=torch.int32), + 'paths': metadata_paths } def make_video_dataset( path, num_workers, batch_size, height, width, min_length, max_length, mode='frames', min_frames=5, max_frames=30, min_delta_t=5000, max_delta_t=50000, rgb=False, seed=None, batch_times=1, pause_probability=0.5, max_optical_flow_threshold=2., max_interp_consecutive_frames=20, - max_number_of_batches_to_produce=None, crop_image=False): + max_number_of_batches_to_produce=None, crop_image=False, saturation_max_factor=1.0): """ Makes a video / moving picture dataset. @@ -192,6 +196,8 @@ def make_video_dataset( max_number_of_batches_to_produce (int): maximum number of batches to produce. Makes sure the stream will not produce more than this number of consecutive batches using the same image or video. + crop_image (bool): crop images or resize them + saturation_max_factor (float): multiplicative factor of saturated pixels (only for tiff 16 bits images. Use 1.0 to disable) """ metadatas = build_metadata(path, min_length, max_length) print('scheduled streams: ', len(metadatas)) @@ -201,7 +207,8 @@ def iterator_fun(metadata): metadata, height, width, rgb=rgb, mode=mode, min_tbins=min_frames, max_tbins=max_frames, min_dt=min_delta_t, max_dt=max_delta_t, batch_times=batch_times, pause_probability=pause_probability, max_optical_flow_threshold=max_optical_flow_threshold, - max_interp_consecutive_frames=max_interp_consecutive_frames, crop_image=crop_image) + max_interp_consecutive_frames=max_interp_consecutive_frames, crop_image=crop_image, + saturation_max_factor=saturation_max_factor) dataset = StreamDataset(metadatas, iterator_fun, batch_size, "data", None, seed) dataloader = StreamDataLoader(dataset, num_workers, pad_collate_fn) # TODO: one day unify make_video_dataset and make_video_dataset_with_events_cpu diff --git a/sdk/modules/core_ml/python/samples/demo_corner_detection/eval_corner_detection.py b/sdk/modules/core_ml/python/samples/demo_corner_detection/eval_corner_detection.py index d0a2217b8..c217289f0 100644 --- a/sdk/modules/core_ml/python/samples/demo_corner_detection/eval_corner_detection.py +++ b/sdk/modules/core_ml/python/samples/demo_corner_detection/eval_corner_detection.py @@ -22,7 +22,7 @@ from metavision_core_ml.corner_detection.lightning_model import CornerDetectionLightningModel from metavision_core_ml.preprocessing.event_to_tensor_torch import event_cd_to_torch, event_volume -from metavision_core_ml.corner_detection.corner_tracker import CornerTracker, CCLTracker +from metavision_core_ml.corner_detection.corner_tracker import CornerTracker from metavision_core_ml.corner_detection.utils import update_nn_tracker, save_nn_corners, clean_pred, events_as_pol from metavision_core.event_io.py_reader import EventDatReader diff --git a/sdk/modules/core_ml/python/samples/train_corner_detection/train_corner_detection.py b/sdk/modules/core_ml/python/samples/train_corner_detection/train_corner_detection.py index 4d6e07da7..2149074bc 100644 --- a/sdk/modules/core_ml/python/samples/train_corner_detection/train_corner_detection.py +++ b/sdk/modules/core_ml/python/samples/train_corner_detection/train_corner_detection.py @@ -122,18 +122,16 @@ def main(raw_args=None): default_root_dir=params.root_dir, callbacks=[checkpoint_callback, demo_callback], logger=logger, - accelerator="cpu" if params.cpu else "gpu", - gpus=0 if params.cpu else 1, + accelerator="cpu" if params.cpu else "auto", precision=params.precision, accumulate_grad_batches=params.accumulate_grad_batches, max_epochs=params.epochs, - resume_from_checkpoint=ckpt, log_every_n_steps=5, limit_train_batches=params.limit_train_batches, limit_val_batches=params.limit_val_batches, ) - trainer.fit(model, data) + trainer.fit(model, data, ckpt_path=ckpt) if __name__ == '__main__': diff --git a/sdk/modules/core_ml/python/samples/train_event_to_video/train_event_to_video.py b/sdk/modules/core_ml/python/samples/train_event_to_video/train_event_to_video.py index b52edbd72..137328de1 100644 --- a/sdk/modules/core_ml/python/samples/train_event_to_video/train_event_to_video.py +++ b/sdk/modules/core_ml/python/samples/train_event_to_video/train_event_to_video.py @@ -126,17 +126,15 @@ def train(params: argparse.Namespace): default_root_dir=params.root_dir, callbacks=[checkpoint_callback, demo_callback], logger=logger, - gpus=0 if params.cpu else 1, precision=params.precision, accumulate_grad_batches=params.accumulate_grad_batches, max_epochs=params.epochs, - resume_from_checkpoint=ckpt, log_every_n_steps=5, limit_train_batches=params.limit_train_batches, limit_val_batches=params.limit_val_batches, - accelerator="cpu" if params.cpu else None + accelerator="cpu" if params.cpu else "auto" ) - trainer.fit(model, data) + trainer.fit(model, data, ckpt_path=ckpt) def main(): diff --git a/sdk/modules/core_ml/python/tests/CMakeLists.txt b/sdk/modules/core_ml/python/tests/CMakeLists.txt index 825053674..598284466 100644 --- a/sdk/modules/core_ml/python/tests/CMakeLists.txt +++ b/sdk/modules/core_ml/python/tests/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. lfs_download("datasets/openeb/core_ml" VALIDATION) -lfs_download("sdk/modules/core_ml/python/models/corner_detection_10_heatmaps.ckpt" VALIDATION) +lfs_download("sdk/modules/core_ml/models/corner_detection_10_heatmaps.ckpt" VALIDATION) get_filename_component(CORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../core/python/pypkg" ABSOLUTE) get_filename_component(CORE_ML_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../pypkg" ABSOLUTE) @@ -18,4 +18,4 @@ set(PYTHON_MODULES_PATHS ${CORE_DIR} ${CORE_ML_DIR}) add_sdk_python_module_test(core_ml ${PYTHON_MODULES_PATHS}) set_property(TEST pytests_core_ml APPEND PROPERTY ENVIRONMENT "SAMPLES=${CMAKE_CURRENT_SOURCE_DIR}/../samples/") -set_property(TEST pytests_core_ml APPEND PROPERTY ENVIRONMENT "MODELS=${CMAKE_CURRENT_SOURCE_DIR}/../models/") \ No newline at end of file +set_property(TEST pytests_core_ml APPEND PROPERTY ENVIRONMENT "MODELS=${CMAKE_CURRENT_SOURCE_DIR}/../models/") diff --git a/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py b/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py index 17591cbe7..ca46507d5 100644 --- a/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py +++ b/sdk/modules/core_ml/python/tests/demo_corner_detection_pytest.py @@ -20,8 +20,8 @@ def pytestcase_demo_corner_detection(tmpdir, dataset_dir): """ video_path = os.path.join(tmpdir, "demo_video.avi") datfile = os.path.join(dataset_dir, "openeb/core_ml/corner_detection/guernica_small_for_pytest.dat") - - models_dir = os.path.join(dataset_dir, '..', 'sdk', 'modules', 'core_ml', 'python', 'models') + + models_dir = os.path.join(dataset_dir, '..', 'sdk', 'modules', 'core_ml', 'models') checkpoint = os.path.join(models_dir, "corner_detection_10_heatmaps.ckpt") assert os.path.exists(checkpoint) diff --git a/sdk/modules/core_ml/python/tests/event_to_video_inference_pytest.py b/sdk/modules/core_ml/python/tests/event_to_video_inference_pytest.py index 7b0c3a83f..fa02e2230 100644 --- a/sdk/modules/core_ml/python/tests/event_to_video_inference_pytest.py +++ b/sdk/modules/core_ml/python/tests/event_to_video_inference_pytest.py @@ -12,32 +12,26 @@ """ import os import sys - import numpy as np import pytest +import torch test_dir_path = os.path.dirname(os.path.realpath(__file__)) sample_dir_path = os.path.join(test_dir_path, '..', 'samples', 'demo_event_to_video') assert os.path.isdir(sample_dir_path) sys.path.append(sample_dir_path) -try: - import torch - from demo_event_to_video import parse_args, run - imports_error = False -except ImportError as e: - print(e) - imports_error = True + +from demo_event_to_video import parse_args, run -@pytest.mark.skipif(imports_error, reason="some imports are failing, please install requirements.txt") class TestEvent2VideoInferenceMain(object): def pytestcase_CLI_test(self, tmpdir, dataset_dir): """checks that the box are split correctly.""" # GIVEN video_path = os.path.join(dataset_dir, 'openeb', 'gen4_evt2_hand.raw') - model_path = os.path.join(dataset_dir, '..', 'sdk', 'modules', 'core_ml', 'python', 'models', + model_path = os.path.join(dataset_dir, '..', 'sdk', 'modules', 'core_ml', 'models', 'e2v.ckpt') # WHEN diff --git a/sdk/modules/core_ml/python/tests/event_to_video_training_pytest.py b/sdk/modules/core_ml/python/tests/event_to_video_training_pytest.py index 4061cdb8d..0d8407061 100644 --- a/sdk/modules/core_ml/python/tests/event_to_video_training_pytest.py +++ b/sdk/modules/core_ml/python/tests/event_to_video_training_pytest.py @@ -19,12 +19,7 @@ assert os.path.isdir(sample_dir_path) sys.path.append(sample_dir_path) -try: - from train_event_to_video import train_parser, train - imports_error = False -except ImportError as e: - print(e) - imports_error = True +from train_event_to_video import train_parser, train def get_argparse_defaults(parser): @@ -35,7 +30,6 @@ def get_argparse_defaults(parser): return defaults -@pytest.mark.skipif(imports_error, reason="some imports are failing, please install requirements.txt") def pytestcase_training_mini_dataset(tmpdir, dataset_dir): """ This is a functional test diff --git a/sdk/modules/core_ml/python/tests/simu_events_iterator_pytest.py b/sdk/modules/core_ml/python/tests/simu_events_iterator_pytest.py index 1206547ea..fdc55625c 100644 --- a/sdk/modules/core_ml/python/tests/simu_events_iterator_pytest.py +++ b/sdk/modules/core_ml/python/tests/simu_events_iterator_pytest.py @@ -12,8 +12,12 @@ """ import os import pytest -import skvideo.io import numpy as np +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ +import skvideo.io from metavision_core_ml.video_to_event.simu_events_iterator import SimulatedEventsIterator from metavision_core_ml.data.video_stream import TimedVideoStream from metavision_core_ml.video_to_event.simulator import EventSimulator diff --git a/sdk/modules/core_ml/python/tests/tiff_images_read_write_pytest.py b/sdk/modules/core_ml/python/tests/tiff_images_read_write_pytest.py new file mode 100644 index 000000000..4c26645d0 --- /dev/null +++ b/sdk/modules/core_ml/python/tests/tiff_images_read_write_pytest.py @@ -0,0 +1,25 @@ +import os +import numpy as np +import skimage.io + +def pytestcase_tiff_images_read_write(tmpdir): + # construct a random image with values in [0; 1] + B, C, H, W = (1, 3, 8, 12) + img_np = np.random.rand(B, C, H , W).astype(np.float16) + img_np = (img_np - img_np.min()) / (img_np.max() - img_np.min()) + assert img_np.min() == 0.0 and img_np.max() == 1.0 + + # save the image as a tiff unit16 + img_tiff = (img_np.squeeze().transpose(1, 2, 0) * (2**16 - 1)).astype(np.uint16) + assert img_tiff.shape == (H, W, C) + filename = os.path.join(tmpdir, "test.tiff") + skimage.io.imsave(filename, img_tiff) + assert os.path.isfile(filename) + + # reload the tiff image and check that it is the same as the original + img_tiff_reloaded = skimage.io.imread(filename) + assert img_tiff_reloaded.shape == (H, W, C) + assert (img_tiff_reloaded == img_tiff).all() + img_np_reloaded = (img_tiff_reloaded.transpose(2, 0, 1).astype(np.float32) / (2**16 - 1))[None].astype(np.float16) + assert img_np_reloaded.shape == (B, C, H, W) + assert np.allclose(img_np_reloaded, img_np, atol=1e-4) \ No newline at end of file diff --git a/sdk/modules/core_ml/python/tests/timed_videostream_pytest.py b/sdk/modules/core_ml/python/tests/timed_videostream_pytest.py index 32c0e912a..6b091e6a9 100644 --- a/sdk/modules/core_ml/python/tests/timed_videostream_pytest.py +++ b/sdk/modules/core_ml/python/tests/timed_videostream_pytest.py @@ -12,8 +12,12 @@ """ import os import pytest -import skvideo.io import numpy as np +# Temporary solution to fix the numpy deprecated alias in skvideo: https://github.com/scikit-video/scikit-video/issues/154#issuecomment-1445239790 +# Will be deleted in MV-2134 when skvideo makes the correction +np.float = np.float64 +np.int = np.int_ +import skvideo.io import cv2 import random diff --git a/sdk/modules/core_ml/python/tests/video_stream_dataset_with_events_cpu_pytest.py b/sdk/modules/core_ml/python/tests/video_stream_dataset_with_events_cpu_pytest.py index c8a949213..82e22f7bd 100644 --- a/sdk/modules/core_ml/python/tests/video_stream_dataset_with_events_cpu_pytest.py +++ b/sdk/modules/core_ml/python/tests/video_stream_dataset_with_events_cpu_pytest.py @@ -12,16 +12,10 @@ import numpy as np import pytest -try: - from metavision_core_ml.video_to_event.video_stream_dataset_with_events_cpu import VideoDatasetWithEventsIterator - from metavision_core_ml.data.scheduling import Metadata - imports_error = False -except ImportError as e: - print(e) - imports_error = True +from metavision_core_ml.video_to_event.video_stream_dataset_with_events_cpu import VideoDatasetWithEventsIterator +from metavision_core_ml.data.scheduling import Metadata -@pytest.mark.skipif(imports_error, reason="some imports are failing, please install requirements.txt") def pytestcase_load_video_with_events(tmpdir, dataset_dir): timestamps_filename = os.path.join(dataset_dir, "openeb", "core_ml", "ultimate_frisbee", "frames_ts.npy") video_filename = os.path.join(dataset_dir, "openeb", "core_ml", "ultimate_frisbee", "frames.mp4") @@ -44,6 +38,6 @@ def pytestcase_load_video_with_events(tmpdir, dataset_dir): discard_events_between_batches=True) video_dataset_it = iter(video_dataset) batch = next(video_dataset_it) - images, timestamps, target_indices, first_times, events_cd, simu_params = batch + _, _, _, _, _, events_cd, simu_params = batch print(simu_params) assert events_cd.size > 0 diff --git a/sdk/modules/driver/cmake/MetavisionSDK_driverCPackConfig.cmake b/sdk/modules/driver/cmake/MetavisionSDK_driverCPackConfig.cmake deleted file mode 100644 index c1ba3a45a..000000000 --- a/sdk/modules/driver/cmake/MetavisionSDK_driverCPackConfig.cmake +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) Prophesee S.A. -# -# 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. - -########################################################## -# -# Metavision SDK Driver - debian packages information -# - -# File and package name of the components are automatically set, just need to set the package description -# and potential dependencies - -# Runtime (library) -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-LIB_DESCRIPTION "Metavision SDK Driver library.\n${OPEN_PACKAGE_LICENSE}") -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-LIB_DEPENDS metavision-hal-lib metavision-sdk-base-lib metavision-sdk-core-lib) -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-LIB_PACKAGE_DEPENDS "libprotobuf-dev") -if (HDF5_FOUND) - list(APPEND CPACK_DEBIAN_METAVISION-SDK-DRIVER-LIB_PACKAGE_DEPENDS "hdf5-ecf-codec-lib") -endif (HDF5_FOUND) -string(REPLACE ";" ", " CPACK_DEBIAN_METAVISION-SDK-DRIVER-LIB_PACKAGE_DEPENDS "${CPACK_DEBIAN_METAVISION-SDK-DRIVER-LIB_PACKAGE_DEPENDS}") - -# Runtime (apps) -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-BIN_DESCRIPTION "Binaries for the Metavision SDK Driver applications.\n${OPEN_PACKAGE_LICENSE}") -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-BIN_DEPENDS metavision-sdk-driver-lib metavision-sdk-core-lib metavision-hal-prophesee-hw-layer-lib) - -# Development package -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-DEV_DESCRIPTION "Development (C++) files for Metavision SDK Driver library.\n${OPEN_PACKAGE_LICENSE}") -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-DEV_DEPENDS metavision-sdk-driver-lib metavision-sdk-base-dev metavision-sdk-core-dev metavision-hal-dev) -if (HDF5_FOUND) - list(APPEND CPACK_DEBIAN_METAVISION-SDK-DRIVER-DEV_PACKAGE_DEPENDS "hdf5-ecf-codec-dev") -endif (HDF5_FOUND) -string(REPLACE ";" ", " CPACK_DEBIAN_METAVISION-SDK-DRIVER-DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_METAVISION-SDK-DRIVER-DEV_PACKAGE_DEPENDS}") - -# Samples -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-SAMPLES_DESCRIPTION "Samples for Metavision SDK Driver library.\n${OPEN_PACKAGE_LICENSE}") -set(CPACK_COMPONENT_METAVISION-SDK-DRIVER-SAMPLES_DEPENDS - metavision-hal-prophesee-hw-layer-dev - metavision-sdk-base-dev - metavision-sdk-core-dev - metavision-sdk-driver-dev - metavision-sdk-ui-dev) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/antiflicker_module.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/antiflicker_module.h deleted file mode 100644 index da92eee95..000000000 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/antiflicker_module.h +++ /dev/null @@ -1,61 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_DRIVER_ANTIFLICKER_MODULE_H -#define METAVISION_SDK_DRIVER_ANTIFLICKER_MODULE_H - -#include - -#include "metavision/hal/facilities/i_antiflicker_module.h" - -namespace Metavision { - -/// @brief Facility class to handle anti-flicker configuration on the hardware side -class AntiFlickerModule { -public: - /// @brief Constructor - AntiFlickerModule(I_AntiFlickerModule *afk); - - /// @brief Destructor - ~AntiFlickerModule(); - - /// @brief Toggles anti-flicker activation - /// @param b Desired state. b = true means anti-flicker active, and b = false means anti-flicker inactive. - /// @note When anti-flicker is inactive, all the events generated by the sensor are transmitted. Potential - /// bandwidth limitation might occur. - void enable(bool b); - - /// @brief Gives the anti-flicker filter state - bool is_enabled(); - - /// @brief Sets anti-flicker parameters. - /// - /// Defines the frequency band to be kept or removed in the range [50 - 500] Hz - /// - /// @param min_freq Lower frequency of the band (in Hz) - /// @param max_freq Higher frequency of the band (in Hz) - /// @throw exception if frequencies are outside of the range [min_supported_freq, max_supported_freq] Hz - void set_frequency_band(uint32_t min_freq, uint32_t max_freq); - - /// @brief Sets the anti-flicker filtering mode - /// @param mode Anti-flicker mode - void set_filtering_mode(I_AntiFlickerModule::AntiFlickerMode mode); - - /// @brief Gets corresponding facility in HAL library - I_AntiFlickerModule *get_facility() const; - -private: - I_AntiFlickerModule *pimpl_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_ANTIFLICKER_MODULE_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/biases.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/biases.h deleted file mode 100644 index 9547f642a..000000000 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/biases.h +++ /dev/null @@ -1,49 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_DRIVER_BIASES_H -#define METAVISION_SDK_DRIVER_BIASES_H - -#include -#include - -#include "metavision/hal/facilities/i_ll_biases.h" - -namespace Metavision { - -/// @brief Facility class to handle biases -class Biases { -public: - /// @brief Constructor - Biases(I_LL_Biases *i_ll_biases); - - /// @brief Destructor - ~Biases(); - - /// @brief Sets camera biases from a bias file at biases_filename - /// @throw CameraException in case of failure. This could happen for example if given path does not exists. - /// @param biases_filename Path to the bias file used to configure the camera - void set_from_file(const std::string &biases_filename); - - /// @brief Save the current biases into a file - /// @param dest_file the destination file - void save_to_file(const std::string &dest_file) const; - - /// @brief Get corresponding facility in HAL library - I_LL_Biases *get_facility() const; - -private: - I_LL_Biases *pimpl_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_BIASES_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/erc_module.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/erc_module.h deleted file mode 100644 index 941974df5..000000000 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/erc_module.h +++ /dev/null @@ -1,62 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_DRIVER_ERC_MODULE_H -#define METAVISION_SDK_DRIVER_ERC_MODULE_H - -#include -#include - -#include "metavision/hal/facilities/i_erc_module.h" - -namespace Metavision { - -/// @brief Facility class for Event Rate Controller (ERC) commands -class ErcModule { -public: - /// @brief Constructor - ErcModule(I_ErcModule *erc); - - /// @brief Destructor - ~ErcModule(); - - /// @brief Toggles ERC activation - /// @param b Desired state. b = true means ERC active, and b = false means ERC inactive. - /// @note When ERC is inactive, all the events generated by the sensor are transmitted. Potential - /// bandwidth limitation might occur. - /// @return true on success - bool enable(bool b); - - /// @brief Returns ERC activation state - /// @return The ERC state - bool is_enabled(); - - /// @brief Sets the target CD event rate of the ERC - /// @param events_per_sec Event rate expressed in events per second - /// @note Event rate is computed by ERC block as the number of events generated by the sensor divided by the count - /// period. - void set_cd_event_rate(uint32_t events_per_sec); - - /// @brief Gets the CD event rate set point of the ERC - /// @return The event rate expressed in events per second - /// @note See @ref set_cd_event_rate to define the event rate target. - uint32_t get_cd_event_rate(); - - /// @brief Gets corresponding facility in HAL library - I_ErcModule *get_facility() const; - -private: - I_ErcModule *pimpl_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_ERC_MODULE_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_trail_filter_module.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_trail_filter_module.h deleted file mode 100644 index 7aa9fb74e..000000000 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_trail_filter_module.h +++ /dev/null @@ -1,51 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_DRIVER_EVENT_TRAIL_FILTER_MODULE_H -#define METAVISION_SDK_DRIVER_EVENT_TRAIL_FILTER_MODULE_H - -#include -#include - -#include "metavision/hal/facilities/i_event_trail_filter_module.h" - -namespace Metavision { - -/// @brief Facility class to handle event trail filter module configuration on the hardware side -/// -/// The types of event trail filter are Spatio-Temporal Contrast (STC) and Trail. -class EventTrailFilterModule { -public: - /// @brief Constructor - EventTrailFilterModule(I_EventTrailFilterModule *noise_filter); - - /// @brief Destructor - ~EventTrailFilterModule(); - - /// @brief Returns the set of available types of filters - /// @return set of available types of filters - std::set get_available_types() const; - - /// @brief Enables the EventTrailFilterModule. Filtering type and threshold should be set before hand - /// @param state If true, enables the module. If false, disables it - /// @return true on success - bool enable(bool state); - - /// @brief Gets corresponding facility in HAL library - I_EventTrailFilterModule *get_facility() const; - -private: - I_EventTrailFilterModule *pimpl_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_EVENT_TRAIL_FILTER_MODULE_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/pipeline/camera_stage.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/pipeline/camera_stage.h deleted file mode 100644 index d164197bb..000000000 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/pipeline/camera_stage.h +++ /dev/null @@ -1,158 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_DRIVER_CAMERA_STAGE_H -#define METAVISION_SDK_DRIVER_CAMERA_STAGE_H - -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/algorithms/shared_cd_events_buffer_producer_algorithm.h" - -namespace Metavision { - -/// @brief Producing stage to generate @ref EventCD buffers and/or @ref EventExtTrigger from a @ref Camera. -/// -/// The CD events buffer producing part uses the @ref SharedEventsBufferProducerAlgorithm allowing to tune further the -/// way you want to build the CD events buffers. -/// -/// Default usage: -/// @code {.cpp} -/// int main(void) { -/// // Opens a camera -/// auto cam = Camera::from_first_available(); -/// -/// // Creates a pipeline object -/// Pipeline p; -/// -/// // Add the Camera producing stage to the pipeline -/// auto &cam_stage = p.add_stage(std::make_unique(std::move(cam))); -/// -/// // Runs the pipeline -/// p.run(); -/// -/// return 0; -/// } -/// @endcode -/// -/// Using @ref SharedEventsBufferProducerAlgorithm capabilities: -/// @code {.cpp} -/// int main(void) { -/// auto camera = Camera::from_first_available(); -/// -/// // Creates a pipeline object -/// Pipeline p; -/// -/// SharedEventsBufferProducerParameters parameters; -/// parameters.buffers_time_slice_us_ = 5000; -/// -/// // Will produce buffers containing 5 ms of events for the next consuming stage. -/// auto &cam_stage = p.add_stage(std::make_unique(std::move(cam), parameters)); -/// -/// // Runs the pipeline -/// p.run(); -/// -/// return 0; -/// } -/// @endcode -/// -/// @sa Pipeline -/// @ref BaseStage -class CameraStage : public BaseStage { -public: - using CdBufferProducer = SharedCdEventsBufferProducerAlgorithm; - using EventTriggerBuffer = std::vector; - using EventTriggerBufferPool = SharedObjectPool; - using EventTriggerBufferPtr = EventTriggerBufferPool::ptr_type; - - /// @brief Constructor - /// @param camera Camera producing the input events - /// @param buffer_producer_parameters Buffer to use by the CD events buffer producing part - /// @param enable_cd_events_callback If true, enables the callback of CD events - CameraStage(Camera &&camera, SharedEventsBufferProducerParameters buffer_producer_parameters, - bool enable_cd_events_callback = true) : - camera_(std::move(camera)), ext_trigger_buffer_pool_(EventTriggerBufferPool::make_bounded()) { - if (enable_cd_events_callback) { - init_cd_processing(buffer_producer_parameters); - } - - init(); - } - - /// @brief Constructor - /// @param camera Camera producing the input events - /// @param buffer_duration_ms Time slice (in milliseconds) to use in the @ref SharedEventsBufferProducerParameters - /// used by the CD events buffer producing part - /// @param enable_cd_events_callback If true, enables the callback of CD events - CameraStage(Camera &&camera, timestamp buffer_duration_ms = 1, bool enable_cd_events_callback = true) : - camera_(std::move(camera)), ext_trigger_buffer_pool_(EventTriggerBufferPool::make_bounded()) { - SharedEventsBufferProducerParameters buffer_producer_parameters; - buffer_producer_parameters.buffers_events_count_ = 0; - buffer_producer_parameters.buffers_pool_size_ = 64; - buffer_producer_parameters.buffers_time_slice_us_ = static_cast(buffer_duration_ms * 1000); - buffer_producer_parameters.buffers_preallocation_size_ = 50000; - - if (enable_cd_events_callback) { - init_cd_processing(buffer_producer_parameters); - } - init(); - } - - /// @brief Adds trigger events - /// @param begin @ref EventExtTrigger pointer to the beginning of the buffer - /// @param end @ref EventExtTrigger pointer to the end of the buffer - void add_ext_trigger_events(const EventExtTrigger *begin, const EventExtTrigger *end) { - cur_ext_trigger_buffer_->insert(std::end(*cur_ext_trigger_buffer_), begin, end); - produce(cur_ext_trigger_buffer_); - cur_ext_trigger_buffer_ = ext_trigger_buffer_pool_.acquire(); - cur_ext_trigger_buffer_->clear(); - } - - /// @brief Gets @ref Camera - /// @return Camera used in the stage - Camera &camera() { - return camera_; - } - -private: - void init_cd_processing(const SharedEventsBufferProducerParameters ¶ms) { - cd_buffer_pool_.reset(new CdBufferProducer( - params, - [this](Metavision::timestamp ts, const CdBufferProducer::SharedEventsBuffer buffer) { produce(buffer); })); - camera_.cd().add_callback( - [this](const EventCD *begin, const EventCD *end) { cd_buffer_pool_->process_events(begin, end); }); - } - - void init() { - cur_ext_trigger_buffer_ = ext_trigger_buffer_pool_.acquire(); - cur_ext_trigger_buffer_->clear(); - - camera_.add_status_change_callback([this](const CameraStatus &status) { - if (status == CameraStatus::STOPPED) { - cd_buffer_pool_->flush(); - if (!cur_ext_trigger_buffer_->empty()) - produce(cur_ext_trigger_buffer_); - complete(); - } - }); - - set_starting_callback([this]() { camera_.start(); }); - set_stopping_callback([this]() { camera_.stop(); }); - } - - Camera camera_; - std::unique_ptr cd_buffer_pool_; - EventTriggerBufferPool ext_trigger_buffer_pool_; - EventTriggerBufferPtr cur_ext_trigger_buffer_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_CAMERA_STAGE_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/roi.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/roi.h deleted file mode 100644 index c079e787c..000000000 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/roi.h +++ /dev/null @@ -1,87 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_DRIVER_ROI_H -#define METAVISION_SDK_DRIVER_ROI_H - -#include - -#include "metavision/hal/facilities/i_roi.h" - -namespace Metavision { - -/// @brief Facility class to handle a Region Of Interest (ROI) -class Roi { -public: - /// @brief Basic struct used to set a hardware region of interest (ROI) - a window - on the sensor - /// - /// This struct defines an ROI of with*height pixels going from [x, y] to [x + width -1, y + height -1] - struct Window { - /// ROI top left column coordinate of the ROI - int x = 0; - - /// ROI top left row coordinate of the ROI - int y = 0; - - /// Width of the ROI - int width = 0; - - /// Height of the ROI - int height = 0; - }; - - /// @brief Constructor - Roi(I_ROI *roi); - - /// @brief Destructor - ~Roi(); - - /// @brief Sets an hardware ROI on the sensor - /// - /// When an ROI is set successfully, no events will be output by the sensor outside of this ROI. - /// Since this is a hardware ROI, there is no processing added to filter the events. - /// Setting an ROI will unset any previously set ROI. - /// - /// @param roi The ROI to set on the sensor - void set(Window roi); - - /// @brief Sets multiple ROIs from row and column binary maps - /// - /// The binary maps (std::vector) arguments must have the sensor's dimension - /// - /// @param cols Vector of boolean of size sensor's width representing the binary map of the columns to - /// enable - /// @param rows Vector of boolean of size sensor's height representing the binary map of the rows to - /// enable - /// @throw an exception if the size of either @p cols or @p rows arguments do not match the sensor - /// geometry - /// @warning For a pixel to be enabled, it must be enabled on both its row and column - void set(const std::vector &cols, const std::vector &rows); - - /// @brief Sets multiple hardware ROI from @ref Roi::Window vector - /// @param windows A vector of ROIs to set - /// @throw an exception if the size of the vector is higher than the maximum supported number - /// of windows (see @ref I_ROI::get_max_supported_windows_count) - void set(const std::vector &windows); - - /// @brief Unsets any set ROI on the sensor - void unset(); - - /// @brief Gets corresponding facility in HAL library - I_ROI *get_facility() const; - -private: - I_ROI *pimpl_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_ROI_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/trigger_out.h b/sdk/modules/driver/cpp/include/metavision/sdk/driver/trigger_out.h deleted file mode 100644 index 04789dad8..000000000 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/trigger_out.h +++ /dev/null @@ -1,71 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_DRIVER_TRIGGER_OUT_H -#define METAVISION_SDK_DRIVER_TRIGGER_OUT_H - -#include - -#include "metavision/hal/facilities/i_trigger_out.h" - -namespace Metavision { - -/// @brief Trigger out signal handler class -/// -/// The trigger out is a signal generator. -/// Its purpose is to synchronize two (or more) devices. -/// -/// The configurable signal through this interface is a periodic 1 microsecond pulse. -class TriggerOut { -public: - /// @brief Constructor - TriggerOut(I_TriggerOut *i_trigger_out); - - /// @brief Destructor - virtual ~TriggerOut(); - - /// @brief Sets the trigger out signal pulse period - /// - /// By default, the system has a period of 100 us meaning that, when enabled, a pulse of 1 microsecond will occur - /// every 100us. - /// - /// @param period_us the signal period in microseconds. - void set_pulse_period(uint32_t period_us); - - /// @brief Sets the duty cycle of the trigger out signal i.e. the pulse duration - /// - /// The duty cycle represents the part of the signal during which its value is 1 (0 otherwise). - /// Duty cycle represents the quantity pulse_width_us/period_us and thus must be in the range [0, 1]. - /// The period is set with @ref set_pulse_period. - /// - /// Setting a duty cycle of 0.5 (50%) means that the value of the signal is 1 during the first half of each period, - /// and 0 during the second half. - /// - /// @param period_ratio Ratio representing pulse_width_us/period_us which must be in the range [0, - /// 1] (value is clamped in this range otherwise) - void set_duty_cycle(double period_ratio); - - /// @brief Enables the trigger out signal - void enable(); - - /// @brief Disables the trigger out signal - void disable(); - - /// @brief Get corresponding facility in HAL library - I_TriggerOut *get_facility() const; - -private: - I_TriggerOut *pimpl_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_DRIVER_TRIGGER_OUT_H diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradlew b/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradlew deleted file mode 100755 index 4f906e0c8..000000000 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradlew +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright 2015 the original author or authors. -# -# 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 -# -# https://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. -# - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/settings.gradle b/sdk/modules/driver/cpp/samples/metavision_viewer_android/settings.gradle deleted file mode 100644 index e7b4def49..000000000 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/sdk/modules/driver/cpp/src/biases.cpp b/sdk/modules/driver/cpp/src/biases.cpp deleted file mode 100644 index 13b1dbb90..000000000 --- a/sdk/modules/driver/cpp/src/biases.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/hal/utils/hal_exception.h" -#include "metavision/sdk/driver/biases.h" -#include "metavision/sdk/driver/camera_exception.h" -#include "metavision/sdk/driver/camera_error_code.h" -#include "metavision/sdk/driver/internal/camera_error_code_internal.h" -#include "metavision/sdk/base/utils/generic_header.h" -#include "metavision/sdk/driver/camera_exception.h" - -namespace Metavision { - -Biases::Biases(I_LL_Biases *i_ll_biases) : pimpl_(i_ll_biases) {} - -Biases::~Biases() {} - -void Biases::set_from_file(const std::string &biases_filename) { - // Check extension - const auto extension = boost::filesystem::extension(biases_filename); - if (extension != ".bias") { - throw CameraException(CameraErrorCode::WrongExtension, - "For bias file '" + biases_filename + - "' : expected '.bias' extension to set the bias from this file but got '." + - extension + "'"); - } - - // open file - std::ifstream bias_file(biases_filename); - if (!bias_file.is_open()) { - throw CameraException(CameraErrorCode::CouldNotOpenFile, - "Could not open file '" + biases_filename + "' for reading. Failed to set biases."); - } - - // Skip header if any - GenericHeader header(bias_file); - - // Get available biases : - std::map available_biases = pimpl_->get_all_biases(); - - // Parse the file to get the list of the biases that the user wants to set - std::map biases_to_set; - for (std::string line; std::getline(bias_file, line) && !line.empty();) { - std::stringstream ss(line); - - // Get value and name - std::string value_str, bias_name, separator; - ss >> value_str >> separator >> bias_name; - std::transform(value_str.begin(), value_str.end(), value_str.begin(), ::tolower); - - if (value_str.empty() || bias_name.empty()) { - throw CameraException(BiasesErrors::UnsupportedBiasFile, - "Cannot read bias file '" + biases_filename + "' : wrong line format '" + line + "'"); - } - int value; - if (value_str.find("0x") != std::string::npos) { - value = std::stoi(value_str, 0, 16); - - } else { - value = std::stol(value_str); - } - - // Check if the bias that we want to set is compatible and not read only - LL_Bias_Info bias_info; - bool ret = true; - try { - ret = pimpl_->get_bias_info(bias_name, bias_info); - } catch (Metavision::HalException &) { ret = false; } - if (!ret) { - throw CameraException(BiasesErrors::UnsupportedBias, - "Bias '" + bias_name + "' is not compatible with the device."); - } - if (!bias_info.is_modifiable()) { - continue; - } - - auto it = biases_to_set.find(bias_name); - if (it != biases_to_set.end()) { - if (value != it->second) { - throw CameraException(CameraErrorCode::BiasesError, "Given two different values for bias '" + - bias_name + "' in file '" + biases_filename + - "'"); - } - } - biases_to_set.emplace(bias_name, value); - } - - // If we get here, no error was found, and we can proceed in setting the biases - for (auto it = biases_to_set.begin(), it_end = biases_to_set.end(); it != it_end; ++it) { - pimpl_->set(it->first, it->second); - } -} - -void Biases::save_to_file(const std::string &dest_file) const { - const auto extension = boost::filesystem::extension(dest_file); - if (extension != ".bias") { - throw CameraException(CameraErrorCode::WrongExtension, - "For bias file '" + dest_file + - "' : expected '.bias' extension to set the bias from this file but got '." + - extension + "'"); - } - - std::ofstream output_file(dest_file); - if (!output_file.is_open()) { - throw CameraException(CameraErrorCode::CouldNotOpenFile, - "Could not open file '" + dest_file + "' for writing. Failed to save biases."); - } - - // Get available biases : - std::map available_biases = pimpl_->get_all_biases(); - - for (auto it = available_biases.begin(), it_end = available_biases.end(); it != it_end; ++it) { - output_file << std::left << std::setw(5) << it->second << "% " << it->first << std::endl; - } - output_file.close(); -} - -I_LL_Biases *Biases::get_facility() const { - return pimpl_; -} - -} // namespace Metavision diff --git a/sdk/modules/driver/cpp/src/roi.cpp b/sdk/modules/driver/cpp/src/roi.cpp deleted file mode 100644 index 44d2035ca..000000000 --- a/sdk/modules/driver/cpp/src/roi.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/driver/roi.h" -#include "metavision/sdk/driver/camera_error_code.h" -#include "metavision/sdk/driver/camera_exception.h" - -namespace Metavision { - -Roi::Roi(I_ROI *roi) : pimpl_(roi) {} - -Roi::~Roi() {} - -void Roi::set(Window roi) { - auto roi_to_set = I_ROI::Window(roi.x, roi.y, roi.width, roi.height); - pimpl_->set_window(roi_to_set); - pimpl_->enable(true); -} - -void Roi::set(const std::vector &cols, const std::vector &rows) { - if (!pimpl_->set_lines(cols, rows)) { - throw(CameraException( - CameraErrorCode::RoiError, - "When trying to set advanced ROI: input binary map must be of the same size of the sensor's dimension.")); - } - pimpl_->enable(true); -} - -void Roi::set(const std::vector &rois) { - std::vector windows; - for (auto roi : rois) { - windows.push_back({roi.x, roi.y, roi.width, roi.height}); - } - pimpl_->set_windows(windows); - pimpl_->enable(true); -} - -void Roi::unset() { - pimpl_->enable(false); -} - -I_ROI *Roi::get_facility() const { - return pimpl_; -} - -} // namespace Metavision diff --git a/sdk/modules/driver/cpp/tests/biases_gtest.cpp b/sdk/modules/driver/cpp/tests/biases_gtest.cpp deleted file mode 100644 index 665174678..000000000 --- a/sdk/modules/driver/cpp/tests/biases_gtest.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/driver/biases.h" -#include "metavision/utils/gtest/gtest_with_tmp_dir.h" -#include "metavision/utils/gtest/warning_removal_helper.h" -#include "metavision/sdk/driver/camera_exception.h" -#include "metavision/hal/device/device.h" -#include "metavision/hal/facilities/i_ll_biases.h" - -namespace { - -class Mock_LL_Biases : public Metavision::I_LL_Biases { -public: - Mock_LL_Biases(const Metavision::DeviceConfig &device_config, const std::map &biases_map) : - Metavision::I_LL_Biases(device_config), biases_map_(biases_map) {} - - ~Mock_LL_Biases() override {} - - bool set_impl(const std::string &bias_name, int bias_value) override { - biases_map_[bias_name] = bias_value; - return true; - } - - int get_impl(const std::string &bias_name) const override { - return biases_map_.find(bias_name)->second; - } - - std::map get_all_biases() const override { - return biases_map_; - } - - bool get_bias_info_impl(const std::string &bias_name, Metavision::LL_Bias_Info &bias_info) const override { - auto it = biases_map_.find(bias_name); - if (it == biases_map_.end()) { - return false; - } - bias_info = - Metavision::LL_Bias_Info(std::numeric_limits::min(), std::numeric_limits::max(), "", true, ""); - return true; - } - - void set_biases_map(const std::map &biases_map) { - biases_map_ = biases_map; - } - -private: - std::map biases_map_; -}; - -} // anonymous namespace - -class Biases_GTest : public Metavision::GTestWithTmpDir { -public: - void write_file(const std::string &filename, const std::string &contents) { - std::ofstream file_out(filename); - - ASSERT_TRUE(file_out.is_open()); - file_out << contents; - file_out.close(); - } - - void compare_biases(const std::map &expected_biases, const std::map &biases) { - ASSERT_EQ(expected_biases.size(), biases.size()); - for (auto it_exp = expected_biases.begin(), it_exp_end = expected_biases.end(), it = biases.begin(); - it_exp != it_exp_end; ++it_exp, ++it) { - EXPECT_EQ(it_exp->first, it->first); - EXPECT_EQ(it_exp->second, it->second); - } - } - -protected: - virtual void SetUp() override { - std::map biases_map = {{"bias_diff", -1}, {"bias_diff_off", -1}, {"bias_diff_on", -1}, - {"bias_fo", -1}, {"bias_hpf", -1}, {"bias_pr", -1}, - {"bias_refr", -1}}; - i_ll_biases_ = std::make_unique(Metavision::DeviceConfig(), biases_map); - biases_.reset(new Metavision::Biases(i_ll_biases_.get())); - } - - std::unique_ptr i_ll_biases_; - std::unique_ptr biases_; -}; - -TEST_F(Biases_GTest, set_from_file_compatible_with_legacy_format) { - // GIVEN a bias file with the legacy format - std::string contents = "% gen 3.1 CD standard biases\n" - "% characterization release 1.4\n" - "% subsystem_ID 2418019330\n" - "% gen 3.1 CD standard biases\n" - "% system_ID 28\n" - "300 % bias_diff % v\n" - "222 % bias_diff_off % v\n" - "385 % bias_diff_on % v\n" - "1480 % bias_fo % i\n" - "1450 % bias_hpf % i\n" - "1250 % bias_pr % i\n" - "1500 % bias_refr % i\n"; - std::string filename = tmpdir_handler_->get_full_path("input.bias"); - write_file(filename, contents); - - // WHEN we set the biases from file - ASSERT_NO_THROW(biases_->set_from_file(filename)); - - // THEN the biases set in the HAL facility have the values written in the file - std::map biases_set = i_ll_biases_->get_all_biases(); - std::map expected_biases = {{"bias_diff", 300}, {"bias_diff_off", 222}, {"bias_diff_on", 385}, - {"bias_fo", 1480}, {"bias_hpf", 1450}, {"bias_pr", 1250}, - {"bias_refr", 1500}}; - - compare_biases(expected_biases, biases_set); -} - -TEST_F(Biases_GTest, set_from_file_with_current_format) { - // GIVEN a bias file like the ones we provide at installation - std::string contents = "299 % bias_diff\n" - "228 % bias_diff_off\n" - "370 % bias_diff_on\n" - "1507 % bias_fo\n" - "1499 % bias_hpf\n" - "1250 % bias_pr\n" - "1500 % bias_refr\n"; - std::string filename = tmpdir_handler_->get_full_path("input.bias"); - write_file(filename, contents); - - // WHEN we set the biases from file - ASSERT_NO_THROW(biases_->set_from_file(filename)); - - // THEN the biases set in the HAL facility have the values written in the file - std::map biases_set = i_ll_biases_->get_all_biases(); - std::map expected_biases = {{"bias_diff", 299}, {"bias_diff_off", 228}, {"bias_diff_on", 370}, - {"bias_fo", 1507}, {"bias_hpf", 1499}, {"bias_pr", 1250}, - {"bias_refr", 1500}}; - compare_biases(expected_biases, biases_set); -} - -TEST_F(Biases_GTest, set_from_file_exa) { - // GIVEN a bias file with values in hexadecimal - std::string contents = "0x97 % bias_pr\n" - "0x17 % bias_fo\n" - "0x30 % bias_hpf\n" - "0x70 % bias_diff_on\n" - "0x45 % bias_diff\n" - "0x34 % bias_diff_off\n" - "0x2D % bias_refr\n"; - std::string filename = tmpdir_handler_->get_full_path("input.bias"); - write_file(filename, contents); - - // WHEN we set the biases from file - ASSERT_NO_THROW(biases_->set_from_file(filename)); - - // THEN the biases set in the HAL facility have the values written in the file - std::map biases_set = i_ll_biases_->get_all_biases(); - std::map expected_biases = {{"bias_pr", 151}, {"bias_fo", 23}, {"bias_hpf", 48}, - {"bias_diff_on", 112}, {"bias_diff", 69}, {"bias_diff_off", 52}, - {"bias_refr", 45}}; - compare_biases(expected_biases, biases_set); -} - -TEST_F(Biases_GTest, set_from_file_wrong_extension) { - // GIVEN a bias file with wrong extension - std::string filename = tmpdir_handler_->get_full_path("input.txt"); - write_file(filename, "299 % bias_diff"); - - try { - // WHEN we set the biases from the given file - biases_->set_from_file(filename); - FAIL() << "Expected exception Metavision::CameraErrorCode::WrongExtension"; - } catch (const Metavision::CameraException &err) { - // THEN it throws an exception - EXPECT_EQ(err.code().value(), Metavision::CameraErrorCode::WrongExtension); - } -} - -TEST_F(Biases_GTest, set_from_file_nonexistent_file) { - // GIVEN a bias file that doesn't exist - std::string filename = tmpdir_handler_->get_full_path("nonexistent.bias"); - - try { - // WHEN we set the biases from this nonexistent file - biases_->set_from_file(filename); - FAIL() << "Expected exception Metavision::CameraErrorCode::CouldNotOpenFile"; - } catch (const Metavision::CameraException &err) { - // THEN it throws an exception - EXPECT_EQ(err.code().value(), Metavision::CameraErrorCode::CouldNotOpenFile); - } -} - -TEST_F(Biases_GTest, set_from_file_wrong_format) { - // GIVEN a bias file with the wrong format - std::string contents = "300 bias_diff\n" - "222 bias_diff_off\n" - "385 bias_diff_on\n" - "1480 bias_fo\n" - "1450 bias_hpf\n" - "1250 bias_pr\n" - "1500 bias_refr\n"; - std::string filename = tmpdir_handler_->get_full_path("input.bias"); - write_file(filename, contents); - - try { - // WHEN we set the biases from file - biases_->set_from_file(filename); - FAIL() << "Expected exception Metavision::CameraErrorCode::BiasesError"; - } catch (const Metavision::CameraException &err) { - // THEN it throws an exception - EXPECT_EQ(err.code().value(), Metavision::CameraErrorCode::BiasesError); - } -} - -TEST_F(Biases_GTest, set_from_file_with_incompatible_biases) { - // GIVEN a bias file like the ones we provide at installation - std::string contents = "299 % bias_diff\n" - "228 % bias_diff_off\n" - "370 % bias_diff_on\n" - "1507 % bias_fo_n\n" // this is the incompatible bias - "1499 % bias_hpf\n" - "1250 % bias_pr\n" - "1500 % bias_refr\n"; - std::string filename = tmpdir_handler_->get_full_path("input.bias"); - write_file(filename, contents); - - try { - // WHEN we set the biases from file - biases_->set_from_file(filename); - FAIL() << "Expected exception Metavision::CameraErrorCode::BiasesError"; - } catch (const Metavision::CameraException &err) { - // THEN it throws an exception - EXPECT_EQ(err.code().value(), Metavision::CameraErrorCode::BiasesError); - } -} - -TEST_F(Biases_GTest, set_from_file_with_two_different_values_for_same_bias) { - // GIVEN a bias file containing different values for a same bias - std::string contents = "299 % bias_diff\n" - "228 % bias_diff_off\n" - "370 % bias_diff_on\n" - "1507 % bias_fo\n" - "1499 % bias_hpf\n" - "1250 % bias_pr\n" - "1500 % bias_fo\n" - "1500 % bias_refr\n"; - std::string filename = tmpdir_handler_->get_full_path("input.bias"); - write_file(filename, contents); - - try { - // WHEN we set the biases from file - biases_->set_from_file(filename); - FAIL() << "Expected exception Metavision::CameraErrorCode::BiasesError"; - } catch (const Metavision::CameraException &err) { - // THEN it throws an exception - EXPECT_EQ(err.code().value(), Metavision::CameraErrorCode::BiasesError); - } -} - -TEST_F(Biases_GTest, save_to_file) { - // GIVEN a Biases instance with given biases - std::map biases_map = {{"bias_diff", 299}, {"bias_diff_off", 228}, {"bias_diff_on", 370}, - {"bias_fo", 1507}, {"bias_hpf", 1499}, {"bias_pr", 1250}, - {"bias_refr", 1500}}; - auto mock_biases = std::make_unique(Metavision::DeviceConfig(), biases_map); - Metavision::Biases biases(mock_biases.get()); - - // WHEN saving the biases to a file - std::string filename = tmpdir_handler_->get_full_path("output.bias"); - ASSERT_NO_THROW(biases.save_to_file(filename)); - - // THEN when reading back the file we get the same biases of the original Biases instance - ASSERT_NO_THROW(biases_->set_from_file(filename)); - std::map biases_set = i_ll_biases_->get_all_biases(); - compare_biases(biases_map, biases_set); -} - -TEST_F(Biases_GTest, save_to_file_wrong_extension) { - // GIVEN an output file with wrong extension - std::string filename = tmpdir_handler_->get_full_path("output.txt"); - - try { - // WHEN saving the biases to a file - biases_->save_to_file(filename); - FAIL() << "Expected exception Metavision::CameraErrorCode::WrongExtension"; - } catch (const Metavision::CameraException &err) { - // THEN it throws an exception - EXPECT_EQ(err.code().value(), Metavision::CameraErrorCode::WrongExtension); - } -} - -TEST_F(Biases_GTest, save_to_file_when_passing_invalid_filename) { - // GIVEN an output file that is invalid - std::string invalid_filename = tmpdir_handler_->get_full_path("output.bias"); - // Invalid because it's an existing directory - ASSERT_TRUE(boost::filesystem::create_directory(invalid_filename)); - - try { - // WHEN saving the biases to the provided file - biases_->save_to_file(invalid_filename); - FAIL() << "Expected exception Metavision::CameraErrorCode::CouldNotOpenFile"; - } catch (const Metavision::CameraException &err) { - // THEN it throws an exception - EXPECT_EQ(err.code().value(), Metavision::CameraErrorCode::CouldNotOpenFile); - } -} - -TEST_F(Biases_GTest, get_facility) { - // GIVEN a Biases instance - // Biases instance already built in the ctor of class Biases_GTest - - // WHEN getting the HAL facility - auto facility = biases_->get_facility(); - - // THEN the facility we got is the same used when building the Biases instance - ASSERT_EQ(i_ll_biases_.get(), facility); -} diff --git a/sdk/modules/driver/cpp/tests/camera_stage_gtest.cpp b/sdk/modules/driver/cpp/tests/camera_stage_gtest.cpp deleted file mode 100644 index da1963a1c..000000000 --- a/sdk/modules/driver/cpp/tests/camera_stage_gtest.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/base/events/event_cd.h" -#include "metavision/utils/gtest/gtest_with_tmp_dir.h" -#include "metavision/sdk/driver/camera_exception.h" -#include "metavision/sdk/driver/pipeline/camera_stage.h" -#include "metavision/sdk/driver/internal/camera_internal.h" -#include "metavision/sdk/core/pipeline/pipeline.h" -#include "metavision/hal/facilities/i_events_stream_decoder.h" -#include "metavision/hal/utils/raw_file_header.h" -#include "tencoder_gtest_common.h" - -using namespace Metavision; - -class CameraStage_Gtest : public GTestWithTmpDir { -protected: - virtual void SetUp() override { - // Create and open the RAW file - static int raw_counter = 1; - rawfile_to_log_path_ = tmpdir_handler_->get_full_path("rawfile_" + std::to_string(++raw_counter) + ".raw"); - encoded_bytes_ = 0; - } - - std::vector write_ref_data() { - std::ofstream rawfile_to_log(rawfile_to_log_path_, std::ios::out | std::ios::binary); - EXPECT_TRUE(rawfile_to_log.is_open()); - - RawFileHeader header_to_write; - header_to_write.set_plugin_name(dummy_plugin_name_); - header_to_write.set_camera_integrator_name(dummy_camera_integrator_name_); - header_to_write.set_plugin_integrator_name(dummy_plugin_integrator_name_); - header_to_write.set_field(dummy_custom_key_, dummy_custom_value_); - - // Prophesee header only. Duplicated what PropheseeRawHeader does to be able to encode then read test RAW - // file - header_to_write.set_field("system_ID", std::to_string(gen31_system_id)); - - rawfile_to_log << header_to_write; - - auto events = build_vector_of_events(); - TEncoder encoder; - encoder.set_encode_event_callback([&](const uint8_t *data, const uint8_t *data_end) { - encoded_bytes_ += std::distance(data, data_end); - rawfile_to_log.write(reinterpret_cast(data), std::distance(data, data_end)); - }); - - encoder.encode(events.cbegin(), events.cend()); - encoder.flush(); - return events; - } - -public: - static const std::string dummy_plugin_name_; - static const std::string dummy_camera_integrator_name_; - static const std::string dummy_plugin_integrator_name_; - static const std::string dummy_custom_key_; - static const std::string dummy_custom_value_; - - static constexpr long gen31_system_id = 28; - -protected: - std::string rawfile_to_log_path_; - size_t encoded_bytes_; -}; - -constexpr long CameraStage_Gtest::gen31_system_id; -const std::string CameraStage_Gtest::dummy_plugin_name_ = "hal_plugin_gen31_fx3"; -const std::string CameraStage_Gtest::dummy_camera_integrator_name_ = "Prophesee"; -const std::string CameraStage_Gtest::dummy_plugin_integrator_name_ = "Prophesee"; -const std::string CameraStage_Gtest::dummy_custom_key_ = "custom"; -const std::string CameraStage_Gtest::dummy_custom_value_ = "field"; - -struct MockStage : public BaseStage { -public: - MockStage() { - set_consuming_callback([this](const boost::any &data) { - auto events = boost::any_cast(data); - events_received_.insert(events_received_.end(), events->cbegin(), events->cend()); - }); - } - - std::vector events_received_; -}; - -TEST_F(CameraStage_Gtest, camera_stage_produces_correct_events) { - //////////////////////////////////////////////////////////////////////////////// - // PURPOSE - // Checks that the camera stage produces correct events - - std::vector ref_data = write_ref_data(); - - Camera camera = Camera::from_file(rawfile_to_log_path_); - size_t decoded_bytes = 0; - camera.raw_data().add_callback([&](auto, size_t bytes_count) { decoded_bytes += bytes_count; }); - Pipeline p(true); - auto &cam_stage = p.add_stage(std::make_unique(std::move(camera))); - cam_stage.detach(); - auto &mock_stage = p.add_stage(std::make_unique(), cam_stage); - mock_stage.detach(); - - p.run(); - - ASSERT_EQ(encoded_bytes_, decoded_bytes); - ASSERT_EQ(ref_data.size(), mock_stage.events_received_.size()); - - timestamp tshift; - { - ASSERT_NO_THROW(cam_stage.camera().get_device()); - auto &device = cam_stage.camera().get_device(); - const auto &decoder = device.get_facility(); - - ASSERT_TRUE(decoder); - - EXPECT_TRUE(decoder->get_timestamp_shift(tshift)); - } - - using SizeType = std::vector::size_type; - for (SizeType i = 0; i < ref_data.size(); ++i) { - EXPECT_EQ(ref_data[i].x, mock_stage.events_received_[i].x); - EXPECT_EQ(ref_data[i].y, mock_stage.events_received_[i].y); - EXPECT_EQ(ref_data[i].t, mock_stage.events_received_[i].t + tshift); - EXPECT_EQ(ref_data[i].p, mock_stage.events_received_[i].p); - } -} diff --git a/sdk/modules/stream/CMakeLists.txt b/sdk/modules/stream/CMakeLists.txt new file mode 100644 index 000000000..1c689e434 --- /dev/null +++ b/sdk/modules/stream/CMakeLists.txt @@ -0,0 +1,16 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +# C++ +add_subdirectory(cpp) + +# Python +if(COMPILE_PYTHON3_BINDINGS) + add_subdirectory(python) +endif(COMPILE_PYTHON3_BINDINGS) diff --git a/sdk/modules/stream/cmake/MetavisionSDK_streamCPackConfig.cmake b/sdk/modules/stream/cmake/MetavisionSDK_streamCPackConfig.cmake new file mode 100644 index 000000000..0ef9131ea --- /dev/null +++ b/sdk/modules/stream/cmake/MetavisionSDK_streamCPackConfig.cmake @@ -0,0 +1,59 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +########################################################## +# +# Metavision SDK Stream - debian packages information +# + +# File and package name of the components are automatically set, just need to set the package description +# and potential dependencies + +# Runtime (library) +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-LIB_DESCRIPTION "Metavision SDK stream library.\n${OPEN_PACKAGE_LICENSE}") +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-LIB_DEPENDS metavision-hal-lib metavision-sdk-base-lib metavision-sdk-core-lib) +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-LIB_PACKAGE_DEPENDS "libprotobuf-dev") +if (HDF5_FOUND) + list(APPEND CPACK_DEBIAN_METAVISION-SDK-STREAM-LIB_PACKAGE_DEPENDS "hdf5-ecf-codec-lib") +endif (HDF5_FOUND) +string(REPLACE ";" ", " CPACK_DEBIAN_METAVISION-SDK-STREAM-LIB_PACKAGE_DEPENDS "${CPACK_DEBIAN_METAVISION-SDK-STREAM-LIB_PACKAGE_DEPENDS}") + +# Runtime (apps) +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-BIN_DESCRIPTION "Binaries for the Metavision SDK stream applications.\n${OPEN_PACKAGE_LICENSE}") +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-BIN_DEPENDS metavision-sdk-stream-lib metavision-sdk-core-lib metavision-hal-prophesee-hw-layer-lib) + +# Development package +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-DEV_DESCRIPTION "Development (C++) files for Metavision SDK stream library.\n${OPEN_PACKAGE_LICENSE}") +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-DEV_DEPENDS metavision-sdk-stream-lib metavision-sdk-base-dev metavision-sdk-core-dev metavision-hal-dev) +if (HDF5_FOUND) + list(APPEND CPACK_DEBIAN_METAVISION-SDK-STREAM-DEV_PACKAGE_DEPENDS "hdf5-ecf-codec-dev") +endif (HDF5_FOUND) +string(REPLACE ";" ", " CPACK_DEBIAN_METAVISION-SDK-STREAM-DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_METAVISION-SDK-STREAM-DEV_PACKAGE_DEPENDS}") + +# Samples +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-SAMPLES_DESCRIPTION "Samples for Metavision SDK stream library.\n${OPEN_PACKAGE_LICENSE}") +set(CPACK_COMPONENT_METAVISION-SDK-STREAM-SAMPLES_DEPENDS + metavision-hal-prophesee-hw-layer-dev + metavision-sdk-base-dev + metavision-sdk-core-dev + metavision-sdk-stream-dev + metavision-sdk-ui-dev) + + +if (COMPILE_PYTHON3_BINDINGS) + # Python bindings + foreach (py_suffix ${PYTHON3_ALL_VERSIONS}) + set(CPACK_COMPONENT_METAVISION-SDK-STREAM-PYTHON${py_suffix}_DESCRIPTION "Metavision SDK Core Python 3 libraries.\n${OPEN_PACKAGE_LICENSE}") + set(CPACK_COMPONENT_METAVISION-SDK-STREAM-PYTHON${py_suffix}_DEPENDS metavision-sdk-stream-lib metavision-sdk-base-python${py_suffix} metavision-hal-python${py_suffix}) + endforeach() + + # Python samples of metavision-sdk-stream-python + set(CPACK_COMPONENT_METAVISION-SDK-STREAM-PYTHON-SAMPLES_DESCRIPTION "Samples for Metavision SDK Stream Python 3 library.\n${OPEN_PACKAGE_LICENSE}") + set(CPACK_COMPONENT_METAVISION-SDK-STREAM-PYTHON-SAMPLES_DEPENDS metavision-sdk-core-python${PYTHON3_DEFAULT_VERSION} metavision-sdk-base-python${PYTHON3_DEFAULT_VERSION} metavision-sdk-stream-python${PYTHON3_DEFAULT_VERSION}) +endif (COMPILE_PYTHON3_BINDINGS) diff --git a/sdk/modules/driver/cpp/3rdparty/CMakeLists.txt b/sdk/modules/stream/cpp/3rdparty/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/3rdparty/CMakeLists.txt rename to sdk/modules/stream/cpp/3rdparty/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/3rdparty/hdf5_ecf b/sdk/modules/stream/cpp/3rdparty/hdf5_ecf similarity index 100% rename from sdk/modules/driver/cpp/3rdparty/hdf5_ecf rename to sdk/modules/stream/cpp/3rdparty/hdf5_ecf diff --git a/sdk/modules/driver/cpp/CMakeLists.txt b/sdk/modules/stream/cpp/CMakeLists.txt similarity index 88% rename from sdk/modules/driver/cpp/CMakeLists.txt rename to sdk/modules/stream/cpp/CMakeLists.txt index a9dbcd840..09719c9e4 100644 --- a/sdk/modules/driver/cpp/CMakeLists.txt +++ b/sdk/modules/stream/cpp/CMakeLists.txt @@ -34,6 +34,4 @@ if (BUILD_TESTING) endif (BUILD_TESTING) # Cpack -add_cpack_component(PUBLIC metavision-sdk-driver-lib metavision-sdk-driver-dev metavision-sdk-driver-bin metavision-sdk-driver-samples) - - +add_cpack_component(PUBLIC metavision-sdk-stream-lib metavision-sdk-stream-dev metavision-sdk-stream-bin metavision-sdk-stream-samples) diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera.h similarity index 83% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/camera.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/camera.h index 69dd68cb4..e0ae9c624 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera.h @@ -9,63 +9,63 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_H -#define METAVISION_SDK_DRIVER_CAMERA_H +#ifndef METAVISION_SDK_STREAM_CAMERA_H +#define METAVISION_SDK_STREAM_CAMERA_H #include +#include #include +#include #include #include #include -#include +#include #include +#include #include // Metavision HAL Device class #include "metavision/hal/device/device.h" -// Metavision SDK Driver File Config Hints class -#include "metavision/sdk/driver/file_config_hints.h" - -// Metavision SDK Driver CD handler class -#include "metavision/sdk/driver/cd.h" - -// Metavision SDK Driver ERCCounter handler class -#include "metavision/sdk/driver/erc_counter.h" +// Metavision HAL DeviceConfig class +#include "metavision/hal/utils/device_config.h" -// Metavision SDK Driver External Trigger handler class -#include "metavision/sdk/driver/ext_trigger.h" +// Metavision HAL I_Geometry class +#include "metavision/hal/facilities/i_geometry.h" -// Metavision SDK Driver FrameDiff handler class -#include "metavision/sdk/driver/frame_diff.h" +// Metavision SDK Stream File Config Hints class +#include "metavision/sdk/stream/file_config_hints.h" -// Metavision SDK Driver FrameHisto handler class -#include "metavision/sdk/driver/frame_histo.h" +// Metavision SDK Stream CD handler class +#include "metavision/sdk/stream/cd.h" -// Metavision SDK Driver Trigger Out handler class -#include "metavision/sdk/driver/trigger_out.h" +// Metavision SDK Stream ERCCounter handler class +#include "metavision/sdk/stream/erc_counter.h" -// Metavision SDK Driver RAW data handler class -#include "metavision/sdk/driver/raw_data.h" +// Metavision SDK Stream External Trigger handler class +#include "metavision/sdk/stream/ext_trigger.h" -// Metavision SDK Driver camera ROI handler -#include "metavision/sdk/driver/roi.h" +// Metavision SDK Stream FrameDiff handler class +#include "metavision/sdk/stream/frame_diff.h" -// Metavision SDK driver Biases class -#include "metavision/sdk/driver/biases.h" +// Metavision SDK Stream FrameHisto handler class +#include "metavision/sdk/stream/frame_histo.h" -// Metavision SDK driver OfflineStreamingControl class -#include "metavision/sdk/driver/offline_streaming_control.h" +// Metavision SDK Stream RAW data handler class +#include "metavision/sdk/stream/raw_data.h" -// Metavision SDK Driver Geometry handler class -#include "metavision/sdk/driver/geometry.h" +// Metavision SDK Stream OfflineStreamingControl class +#include "metavision/sdk/stream/offline_streaming_control.h" // Metavision device generation -#include "metavision/sdk/driver/camera_generation.h" +#include "metavision/sdk/stream/camera_generation.h" -// Metavision SDK Driver camera exceptions -#include "metavision/sdk/driver/camera_exception.h" +// Metavision SDK Stream camera exceptions +#include "metavision/sdk/stream/camera_exception.h" + +// Metavision SDK Stream camera error codes +#include "metavision/sdk/stream/camera_error_code.h" // Metavision SDK callback id #include "metavision/sdk/base/utils/callback_id.h" @@ -73,15 +73,6 @@ // Metavision SDK timestamp #include "metavision/sdk/base/utils/timestamp.h" -// Metavision SDK Driver AntiFlickerModule class -#include "metavision/sdk/driver/antiflicker_module.h" - -// Metavision SDK Driver ErcModule class -#include "metavision/sdk/driver/erc_module.h" - -// Metavision SDK Driver EventTrailFilterModule class -#include "metavision/sdk/driver/event_trail_filter_module.h" - namespace Metavision { /// @brief Online camera type input sources: USB, embedded, remote @@ -120,7 +111,6 @@ using StatusChangeCallback = std::function; /// In case of an offline source, the fields correspond to the online source used to record the data. struct CameraConfiguration { std::string serial_number; - std::string system_ID; std::string plugin_name; std::string integrator; std::string data_encoding_format; @@ -251,7 +241,29 @@ class Camera { /// @param file_path Path to the file /// @param hints Hints expressing how the file should be read, for more details see @ref FileConfigHints /// @return @ref Camera instance initialized from the input file - static Camera from_file(const std::string &file_path, const FileConfigHints &hints = FileConfigHints()); + static Camera from_file(const std::filesystem::path &file_path, const FileConfigHints &hints = FileConfigHints()); + + /// @brief Returns facility + template + FacilityType &get_facility() { + auto facility = get_device().get_facility(); + if (!facility) { + throw CameraException(CameraErrorCode::UnsupportedFeature, + std::string("Unavailable facility ") + typeid(FacilityType).name()); + } + return *facility; + } + + /// @brief Returns facility + template + const FacilityType &get_facility() const { + auto facility = get_device().get_facility(); + if (!facility) { + throw CameraException(CameraErrorCode::UnsupportedFeature, + std::string("Unavailable facility ") + typeid(FacilityType).name()); + } + return *facility; + } /// @brief Gets class to handle RAW data from the camera /// @throw CameraException if the camera has not been initialized. @@ -265,11 +277,6 @@ class Camera { /// @throw CameraException if the camera has not been initialized. ExtTrigger &ext_trigger(); - /// @brief Gets class to handle trigger out signal - /// @throw CameraException if the camera has not been initialized. - /// @throw CameraException in case of failure (for example if camera runs from an offline source). - TriggerOut &trigger_out(); - /// @brief Gets class to handle ERCCounter events /// @throw CameraException if the camera has not been initialized. ERCCounter &erc_counter(); @@ -282,26 +289,6 @@ class Camera { /// @throw CameraException if the camera has not been initialized. FrameDiff &frame_diff(); - /// @brief Gets class to handle Roi on the sensor - /// @throw CameraException in case of failure (for instance if the camera is not initialized or the camera is - /// running from an offline source). - Roi &roi(); - - /// @brief Gets class to handle AFK on the hardware side - /// @throw CameraException in case of failure (for instance if the camera is not initialized or the camera is - /// running from an offline source). - AntiFlickerModule &antiflicker_module(); - - /// @brief Gets class to handle Event Rater Controller on the hardware side - /// @throw CameraException in case of failure (for instance if the camera is not initialized or the camera is - /// running from an offline source). - ErcModule &erc_module(); - - /// @brief Gets class to handle STC or TRAIL Event Trail Filter Module on the hardware side - /// @throw CameraException in case of failure (for instance if the camera is not initialized or the camera is - /// running from an offline source). - EventTrailFilterModule &event_trail_filter_module(); - /// @brief Registers a callback that will be called when a runtime error occurs /// /// When a camera runtime error occurs, the camera thread is left and events are no longer sent. @@ -337,17 +324,13 @@ class Camera { /// @return true if the callback has been unregistered correctly, false otherwise. bool remove_status_change_callback(CallbackId callback_id); - /// @brief Gets class to handle camera biases - /// @throw CameraException in case of failure (for example if camera runs from an offline source). - Biases &biases(); - /// @brief Gets class to control offline streaming /// @throw CameraException if the camera has not been initialized or if the feature is not available. OfflineStreamingControl &offline_streaming_control(); /// @brief Gets the device's geometry /// @throw CameraException if the camera has not been initialized. - const Geometry &geometry() const; + const I_Geometry &geometry() const; /// @brief Gets the device's generation /// @throw CameraException if the camera has not been initialized. @@ -388,7 +371,7 @@ class Camera { /// In case of an offline input source, the function can be used to split the file and record only a portion of it. /// @throw CameraException if the camera has not been initialized. /// @warning Calling this function will overwrite the file at the path @p file_path if it already exists. - /// @note This functions is the recommended way to save recording with SDK driver. + /// @note This functions is the recommended way to save recording with SDK Stream. /// It uses a separate thread to write the file for efficiency, so it will not slow down the decoding thread /// as opposed to @ref I_EventsStream::log_raw_data and @ref I_EventsStream::stop_log_raw_data /// It also enables writing to supported formats other than RAW file, although the writing speed will probably @@ -399,7 +382,7 @@ class Camera { /// For more information, refer to the metavision_file_cutter sample /// @param file_path Path to the file containing the recorded data /// @return true if recording could be started, false otherwise - bool start_recording(const std::string &file_path); + bool start_recording(const std::filesystem::path &file_path); /// @brief Stops recording data from camera to the specified path /// @@ -409,7 +392,7 @@ class Camera { /// @param file_path Path to the file containing the recorded data. If empty, all ongoing recordings are stopped. /// @throw CameraException if the camera has not been initialized. /// @return true if recording could be stopped, false otherwise - bool stop_recording(const std::string &file_path = std::string()); + bool stop_recording(const std::filesystem::path &file_path = std::string()); /// @brief Returns @ref CameraConfiguration of the camera that holds the available camera properties (serial, /// systemID, format of events, etc.) @@ -433,12 +416,12 @@ class Camera { /// @brief Saves the camera settings to a given file /// @param path The path of the file to save the camera settings to /// @return true on success - bool save(const std::string &path) const; + bool save(const std::filesystem::path &path) const; /// @brief Loads the camera settings from a given file /// @param path The path of the file to load the camera settings from /// @return true on success - bool load(const std::string &path); + bool load(const std::filesystem::path &path); /// @brief Gets corresponding @ref Device in HAL library /// @@ -473,6 +456,11 @@ class Camera { std::unique_ptr pimpl_; }; +template<> +I_Geometry &Camera::get_facility(); +template<> +const I_Geometry &Camera::get_facility() const; + /// @brief Saves the camera to a given stream /// @param os The output stream in which the camera will be saved /// @param camera The camera to save @@ -487,4 +475,4 @@ std::istream &operator>>(std::istream &is, Camera &camera); } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_H +#endif // METAVISION_SDK_STREAM_CAMERA_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_error_code.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_error_code.h similarity index 88% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_error_code.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_error_code.h index 2bf077f39..77a04e52d 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_error_code.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_error_code.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_ERROR_CODE_H -#define METAVISION_SDK_DRIVER_CAMERA_ERROR_CODE_H +#ifndef METAVISION_SDK_STREAM_CAMERA_ERROR_CODE_H +#define METAVISION_SDK_STREAM_CAMERA_ERROR_CODE_H namespace Metavision { @@ -22,28 +22,24 @@ using CameraErrorCodeType = int; /// @sa @ref CameraException namespace CameraErrorCode { enum Enum : CameraErrorCodeType { - /// Base Metavision SDK Driver camera error + /// Base Metavision SDK Stream camera error CameraError = 0x100000, /// Camera failed initialization FailedInitialization = CameraError | 0x01000, /// Failed initialization due to a camera not found CameraNotFound = FailedInitialization | 0x1, - /// Metavision SDK Driver Internal Initialization problem + /// Metavision SDK Stream Internal Initialization problem InternalInitializationError = FailedInitialization | 0x100, /// Camera runtime errors RuntimeError = CameraError | 0x02000, - /// Fails to set biases. - BiasesError = RuntimeError | 0x200, /// Error due to a non initialized camera CameraNotInitialized = RuntimeError | 0x2, /// Invalid RAW file InvalidRawfile = RuntimeError | 0x3, /// Error while retrieving data from source DataTransferFailed = RuntimeError | 0x4, - /// Fails to set ROI. - RoiError = RuntimeError | 0x6, /// Error while trying to use a feature unsupported by the camera UnsupportedFeature = RuntimeError | 0x100, /// Device firmware is not up to date @@ -69,4 +65,4 @@ enum Enum : CameraErrorCodeType { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_ERROR_CODE_H +#endif // METAVISION_SDK_STREAM_CAMERA_ERROR_CODE_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_exception.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_exception.h similarity index 88% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_exception.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_exception.h index 1bc55b6fb..d0cc9da98 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_exception.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_exception.h @@ -9,18 +9,18 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_EXCEPTION_H -#define METAVISION_SDK_DRIVER_CAMERA_EXCEPTION_H +#ifndef METAVISION_SDK_STREAM_CAMERA_EXCEPTION_H +#define METAVISION_SDK_STREAM_CAMERA_EXCEPTION_H #include #include #include "metavision/sdk/base/utils/error_utils.h" -#include "metavision/sdk/driver/camera_error_code.h" +#include "metavision/sdk/stream/camera_error_code.h" namespace Metavision { -/// @brief Class for all exceptions thrown by Metavision SDK Driver +/// @brief Class for all exceptions thrown by Metavision SDK Stream /// /// @sa http://www.cplusplus.com/reference/system_error/system_error/ /// @sa http://en.cppreference.com/w/cpp/error/error_code @@ -40,4 +40,4 @@ class CameraException : public BaseException { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_EXCEPTION_H +#endif // METAVISION_SDK_STREAM_CAMERA_EXCEPTION_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_generation.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_generation.h similarity index 90% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_generation.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_generation.h index 5b57652c2..5bbb11809 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/camera_generation.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_generation.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_GENERATION_H -#define METAVISION_SDK_DRIVER_CAMERA_GENERATION_H +#ifndef METAVISION_SDK_STREAM_CAMERA_GENERATION_H +#define METAVISION_SDK_STREAM_CAMERA_GENERATION_H #include @@ -30,6 +30,9 @@ class CameraGeneration { /// @brief Returns the minor version of the camera's generation short version_minor() const; + /// @brief Returns the name corresponding to the camera's generation + std::string name() const; + /// @brief overrides "equal to" operator bool operator==(const CameraGeneration &c) const; @@ -60,4 +63,4 @@ class CameraGeneration { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_GENERATION_H +#endif // METAVISION_SDK_STREAM_CAMERA_GENERATION_H diff --git a/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_stream_slicer.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_stream_slicer.h new file mode 100644 index 000000000..9b9ac85a8 --- /dev/null +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/camera_stream_slicer.h @@ -0,0 +1,104 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_STREAM_CAMERA_STREAM_SLICER_H +#define METAVISION_SDK_STREAM_CAMERA_STREAM_SLICER_H + +#include +#include + +#include "metavision/sdk/base/utils/object_pool.h" +#include "metavision/sdk/core/algorithms/event_buffer_reslicer_algorithm.h" +#include "metavision/sdk/core/utils/concurrent_queue.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/slice_iterator.h" + +namespace Metavision { +using EventBuffer = std::vector; +using TriggerBuffer = std::vector; + +/// @brief Structure representing a slice of events and triggers +struct Slice { + using ConditionStatus = EventBufferReslicerAlgorithm::ConditionStatus; + + /// @brief Default constructor + Slice() = default; + + /// @brief Comparison operator + /// @param other Slice to compare with + /// @return True if the two slices are equal, false otherwise + bool operator==(const Slice &other) const; + + ConditionStatus status; ///< Status indicating how the slice was completed + timestamp t; ///< Timestamp of the slice + std::size_t n_events; ///< Number of CD events in the slice + std::shared_ptr events; ///< Events in the slice + std::shared_ptr triggers; ///< Triggers in the slice +}; + +/// @brief Class that slices a stream of events and triggers according to a given condition +/// +/// Internally, a concurrent queue is used to store the slices produced by the background threads of the @ref Camera +/// class (i.e. in the callbacks). The size of this concurrent queue can be limited to prevent the background threads +/// from producing too many slices (i.e. especially in offline mode) and consuming too much memory. +class CameraStreamSlicer { +public: + using SliceCondition = EventBufferReslicerAlgorithm::Condition; + using SliceIterator = SliceIteratorT; + + /// @brief Default constructor + CameraStreamSlicer() = default; + + /// @brief Constructor + /// @param camera Camera instance to slice, the ownership of the camera is transferred to the slicer + /// @param slice_condition Slicing parameters + /// @param max_queue_size Maximum number of slices that can be stored in the internal queue + CameraStreamSlicer(Camera &&camera, const SliceCondition &slice_condition = SliceCondition::make_n_us(1000), + size_t max_queue_size = 5); + + /// @brief Move constructor + /// @param slicer CameraStreamSlicer to move + CameraStreamSlicer(CameraStreamSlicer &&slicer) noexcept; + + /// @brief Move assignment operator + /// @param slicer CameraStreamSlicer to move + CameraStreamSlicer &operator=(CameraStreamSlicer &&slicer) noexcept; + + CameraStreamSlicer(const CameraStreamSlicer &) = delete; + CameraStreamSlicer &operator=(const CameraStreamSlicer &) = delete; + + /// @brief Destructor + ~CameraStreamSlicer(); + + /// @brief Starts the camera stream and returns an iterator to the first slice + SliceIterator begin(); + + /// @brief Returns an iterator to the end of the stream + SliceIterator end(); + + /// @brief Returns the underlying camera instance + [[nodiscard]] const Camera &camera() const; + +private: + void init_slicing(); + + std::shared_ptr> queue_; + SharedObjectPool> event_buffer_pool_; + SharedObjectPool> trigger_buffer_pool_; + std::shared_ptr curt_event_buffer_; + std::shared_ptr curt_trigger_buffer_; + EventBufferReslicerAlgorithm slicer_; + Camera camera_; +}; + +} // namespace Metavision + +#endif // METAVISION_SDK_STREAM_CAMERA_STREAM_SLICER_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/cd.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/cd.h similarity index 96% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/cd.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/cd.h index 4666cfd88..09afb76d5 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/cd.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/cd.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CD_H -#define METAVISION_SDK_DRIVER_CD_H +#ifndef METAVISION_SDK_STREAM_CD_H +#define METAVISION_SDK_STREAM_CD_H #include #include @@ -61,4 +61,4 @@ class CD { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CD_H +#endif // METAVISION_SDK_STREAM_CD_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/dat_event_file_reader.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/dat_event_file_reader.h similarity index 85% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/dat_event_file_reader.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/dat_event_file_reader.h index 7651b8982..2668eb90c 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/dat_event_file_reader.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/dat_event_file_reader.h @@ -9,11 +9,12 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_DAT_EVENT_FILE_READER_H -#define METAVISION_SDK_DRIVER_DAT_EVENT_FILE_READER_H +#ifndef METAVISION_SDK_STREAM_DAT_EVENT_FILE_READER_H +#define METAVISION_SDK_STREAM_DAT_EVENT_FILE_READER_H +#include #include -#include "metavision/sdk/driver/event_file_reader.h" +#include "metavision/sdk/stream/event_file_reader.h" namespace Metavision { @@ -21,7 +22,7 @@ class Device; class DATEventFileReader : public EventFileReader { public: - DATEventFileReader(const std::string &path); + DATEventFileReader(const std::filesystem::path &path); ~DATEventFileReader(); bool seekable() const override; @@ -39,4 +40,4 @@ class DATEventFileReader : public EventFileReader { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_RAW_EVENT_FILE_READER_H +#endif // METAVISION_SDK_STREAM_RAW_EVENT_FILE_READER_H diff --git a/sdk/modules/stream/cpp/include/metavision/sdk/stream/detail/slice_iterator_impl.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/detail/slice_iterator_impl.h new file mode 100644 index 000000000..9f7394c6c --- /dev/null +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/detail/slice_iterator_impl.h @@ -0,0 +1,64 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_STREAM_SLICE_ITERATOR_IMPL_H +#define METAVISION_SDK_STREAM_SLICE_ITERATOR_IMPL_H + +namespace Metavision { + +template +SliceIteratorT::SliceIteratorT(std::shared_ptr> q) : queue_(std::move(q)) { + ++(*this); +} + +template +typename SliceIteratorT::reference SliceIteratorT::operator*() { + return slice_; +} + +template +typename SliceIteratorT::pointer SliceIteratorT::operator->() { + return &slice_; +} + +template +SliceIteratorT &SliceIteratorT::operator++() { + if (queue_) { + if (auto opt_slice = queue_->pop_front(); opt_slice) { + slice_ = std::move(*opt_slice); + } else { + queue_ = nullptr; + slice_ = SliceT{}; + } + } + return *this; +} + +template +SliceIteratorT SliceIteratorT::operator++(int) { + auto it = *this; + ++it; + return it; +} + +template +bool SliceIteratorT::operator==(const SliceIteratorT &other) const { + return queue_ == other.queue_ && slice_ == other.slice_; +} + +template +bool SliceIteratorT::operator!=(const SliceIteratorT &other) const { + return !(*this == other); +} + +} // namespace Metavision + +#endif // METAVISION_SDK_STREAM_SLICE_ITERATOR_IMPL_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/erc_counter.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/erc_counter.h similarity index 95% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/erc_counter.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/erc_counter.h index b7b8acd6b..2ed340638 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/erc_counter.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/erc_counter.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_ERC_COUNTER_H -#define METAVISION_SDK_DRIVER_ERC_COUNTER_H +#ifndef METAVISION_SDK_STREAM_ERC_COUNTER_H +#define METAVISION_SDK_STREAM_ERC_COUNTER_H #include #include @@ -61,4 +61,4 @@ class ERCCounter { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_ERC_COUNTER_H +#endif // METAVISION_SDK_STREAM_ERC_COUNTER_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_reader.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/event_file_reader.h similarity index 96% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_reader.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/event_file_reader.h index 29a978e98..be62a2003 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_reader.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/event_file_reader.h @@ -9,9 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_EVENT_FILE_READER_H -#define METAVISION_SDK_DRIVER_EVENT_FILE_READER_H +#ifndef METAVISION_SDK_STREAM_EVENT_FILE_READER_H +#define METAVISION_SDK_STREAM_EVENT_FILE_READER_H +#include #include #include #include @@ -30,14 +31,14 @@ class EventFileReader { public: /// @brief Builds an EventFileReader /// @param path Path to the event based file to read - EventFileReader(const std::string &path); + EventFileReader(const std::filesystem::path &path); /// @brief Destructs an EventFileReader virtual ~EventFileReader(); /// @brief Gets the path of the event based file /// @return Path of the file - const std::string &get_path() const; + const std::filesystem::path &get_path() const; /// @brief Alias for the "reading callback" used when a buffer of events has been read /// @@ -157,4 +158,4 @@ class EventFileReader { } // namespace Metavision -#endif /* METAVISION_SDK_DRIVER_EVENT_FILE_READER_H */ +#endif /* METAVISION_SDK_STREAM_EVENT_FILE_READER_H */ diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_writer.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/event_file_writer.h similarity index 88% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_writer.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/event_file_writer.h index eae447dac..a244d1e99 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/event_file_writer.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/event_file_writer.h @@ -9,9 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_EVENT_FILE_WRITER_H -#define METAVISION_SDK_DRIVER_EVENT_FILE_WRITER_H +#ifndef METAVISION_SDK_STREAM_EVENT_FILE_WRITER_H +#define METAVISION_SDK_STREAM_EVENT_FILE_WRITER_H +#include #include #include @@ -27,15 +28,15 @@ class Camera; class EventFileWriter { public: /// @brief Builds an EventFileWriter - /// @param path Path to the event based file to read - EventFileWriter(const std::string &path = std::string()); + /// @param path Path to the event based file to write + EventFileWriter(const std::filesystem::path &path = std::filesystem::path()); /// @brief Destructs an EventFileWriter virtual ~EventFileWriter(); /// @brief Open the writer with specified path /// @param path Path to the file to write - void open(const std::string &path); + void open(const std::filesystem::path &path); /// @brief Close the writer void close(); @@ -55,7 +56,7 @@ class EventFileWriter { /// @brief Gets the path of the event based file /// @return Path of the file - const std::string &get_path() const; + const std::filesystem::path &get_path() const; /// @brief Adds metadata to the file /// @param key Metatadata key to be added @@ -94,9 +95,9 @@ class EventFileWriter { Private &get_pimpl(); private: - virtual void open_impl(const std::string &path) = 0; - virtual void close_impl() = 0; - virtual bool is_open_impl() const = 0; + virtual void open_impl(const std::filesystem::path &path) = 0; + virtual void close_impl() = 0; + virtual bool is_open_impl() const = 0; virtual void add_metadata_impl(const std::string &key, const std::string &value) = 0; virtual void add_metadata_map_from_camera_impl(const Camera &camera) = 0; @@ -111,4 +112,4 @@ class EventFileWriter { } // namespace Metavision -#endif /* METAVISION_SDK_DRIVER_EVENT_FILE_WRITER_H */ +#endif /* METAVISION_SDK_STREAM_EVENT_FILE_WRITER_H */ diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/ext_trigger.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/ext_trigger.h similarity index 95% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/ext_trigger.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/ext_trigger.h index 70628aa1e..8c1dca0e1 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/ext_trigger.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/ext_trigger.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_EXT_TRIGGER_H -#define METAVISION_SDK_DRIVER_EXT_TRIGGER_H +#ifndef METAVISION_SDK_STREAM_EXT_TRIGGER_H +#define METAVISION_SDK_STREAM_EXT_TRIGGER_H #include #include @@ -61,4 +61,4 @@ class ExtTrigger { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_EXT_TRIGGER_H +#endif // METAVISION_SDK_STREAM_EXT_TRIGGER_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/file_config_hints.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/file_config_hints.h similarity index 97% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/file_config_hints.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/file_config_hints.h index 9e102aa10..d627624c1 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/file_config_hints.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/file_config_hints.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_FILE_CONFIG_HINTS_H -#define METAVISION_SDK_DRIVER_FILE_CONFIG_HINTS_H +#ifndef METAVISION_SDK_STREAM_FILE_CONFIG_HINTS_H +#define METAVISION_SDK_STREAM_FILE_CONFIG_HINTS_H #include #include @@ -143,4 +143,4 @@ class FileConfigHints { }; } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_FILE_CONFIG_HINTS_H +#endif // METAVISION_SDK_STREAM_FILE_CONFIG_HINTS_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/frame_diff.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/frame_diff.h similarity index 95% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/frame_diff.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/frame_diff.h index c3986397c..f54513a34 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/frame_diff.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/frame_diff.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_FRAME_DIFF_H -#define METAVISION_SDK_DRIVER_FRAME_DIFF_H +#ifndef METAVISION_SDK_STREAM_FRAME_DIFF_H +#define METAVISION_SDK_STREAM_FRAME_DIFF_H #include #include @@ -61,4 +61,4 @@ class FrameDiff { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_FRAME_DIFF_H +#endif // METAVISION_SDK_STREAM_FRAME_DIFF_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/frame_histo.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/frame_histo.h similarity index 95% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/frame_histo.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/frame_histo.h index 9f3118cef..f050903df 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/frame_histo.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/frame_histo.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_FRAME_HISTO_H -#define METAVISION_SDK_DRIVER_FRAME_HISTO_H +#ifndef METAVISION_SDK_STREAM_FRAME_HISTO_H +#define METAVISION_SDK_STREAM_FRAME_HISTO_H #include #include @@ -61,4 +61,4 @@ class FrameHisto { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_FRAME_HISTO_H +#endif // METAVISION_SDK_STREAM_FRAME_HISTO_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/hdf5_event_file_reader.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/hdf5_event_file_reader.h similarity index 84% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/hdf5_event_file_reader.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/hdf5_event_file_reader.h index 92233d9a9..76118d058 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/hdf5_event_file_reader.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/hdf5_event_file_reader.h @@ -9,17 +9,18 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_HDF5_EVENT_FILE_READER_H -#define METAVISION_SDK_DRIVER_HDF5_EVENT_FILE_READER_H +#ifndef METAVISION_SDK_STREAM_HDF5_EVENT_FILE_READER_H +#define METAVISION_SDK_STREAM_HDF5_EVENT_FILE_READER_H +#include #include -#include "metavision/sdk/driver/event_file_reader.h" +#include "metavision/sdk/stream/event_file_reader.h" namespace Metavision { class HDF5EventFileReader : public EventFileReader { public: - HDF5EventFileReader(const std::string &path, bool time_shift = true); + HDF5EventFileReader(const std::filesystem::path &path, bool time_shift = true); ~HDF5EventFileReader() override; bool seekable() const override; @@ -37,4 +38,4 @@ class HDF5EventFileReader : public EventFileReader { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_HDF5_EVENT_FILE_READER_H +#endif // METAVISION_SDK_STREAM_HDF5_EVENT_FILE_READER_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/hdf5_event_file_writer.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/hdf5_event_file_writer.h similarity index 78% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/hdf5_event_file_writer.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/hdf5_event_file_writer.h index 3197deddc..f3b0c9d16 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/hdf5_event_file_writer.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/hdf5_event_file_writer.h @@ -9,25 +9,27 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_HDF5_EVENT_FILE_WRITER_H -#define METAVISION_SDK_DRIVER_HDF5_EVENT_FILE_WRITER_H +#ifndef METAVISION_SDK_STREAM_HDF5_EVENT_FILE_WRITER_H +#define METAVISION_SDK_STREAM_HDF5_EVENT_FILE_WRITER_H +#include #include #include #include -#include "metavision/sdk/driver/event_file_writer.h" +#include "metavision/sdk/stream/event_file_writer.h" namespace Metavision { class HDF5EventFileWriter : public EventFileWriter { public: - HDF5EventFileWriter(const std::string &path = std::string(), - const std::unordered_map &metadata_map = - std::unordered_map()); + HDF5EventFileWriter(const std::filesystem::path &path = std::filesystem::path(), + const std::unordered_map &metadata_map = + std::unordered_map()); + ~HDF5EventFileWriter() override; private: - void open_impl(const std::string &path) override; + void open_impl(const std::filesystem::path &path) override; void close_impl() override; bool is_open_impl() const override; void flush_impl() override; @@ -45,4 +47,4 @@ class HDF5EventFileWriter : public EventFileWriter { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_HDF5_EVENT_FILE_WRITER_H +#endif // METAVISION_SDK_STREAM_HDF5_EVENT_FILE_WRITER_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/offline_streaming_control.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/offline_streaming_control.h similarity index 93% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/offline_streaming_control.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/offline_streaming_control.h index bebb98d19..9a55d651f 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/offline_streaming_control.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/offline_streaming_control.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_OFFLINE_STREAMING_CONTROL_H -#define METAVISION_SDK_DRIVER_OFFLINE_STREAMING_CONTROL_H +#ifndef METAVISION_SDK_STREAM_OFFLINE_STREAMING_CONTROL_H +#define METAVISION_SDK_STREAM_OFFLINE_STREAMING_CONTROL_H #include #include @@ -58,4 +58,4 @@ class OfflineStreamingControl { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_OFFLINE_STREAMING_CONTROL_H +#endif // METAVISION_SDK_STREAM_OFFLINE_STREAMING_CONTROL_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_data.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_data.h similarity index 95% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_data.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_data.h index 4326fd013..31da0623b 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_data.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_data.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_RAW_DATA_H -#define METAVISION_SDK_DRIVER_RAW_DATA_H +#ifndef METAVISION_SDK_STREAM_RAW_DATA_H +#define METAVISION_SDK_STREAM_RAW_DATA_H #include #include @@ -63,4 +63,4 @@ class RawData { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_RAW_DATA_H +#endif // METAVISION_SDK_STREAM_RAW_DATA_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_event_file_writer.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_event_file_logger.h similarity index 75% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_event_file_writer.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_event_file_logger.h index a804f4090..6240eec2b 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_event_file_writer.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_event_file_logger.h @@ -9,27 +9,28 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_RAW_EVENT_FILE_WRITER_H -#define METAVISION_SDK_DRIVER_RAW_EVENT_FILE_WRITER_H +#ifndef METAVISION_SDK_STREAM_RAW_EVENT_FILE_WRITER_H +#define METAVISION_SDK_STREAM_RAW_EVENT_FILE_WRITER_H +#include #include #include #include -#include "metavision/sdk/driver/event_file_writer.h" +#include "metavision/sdk/stream/event_file_writer.h" namespace Metavision { -class RAWEventFileWriter : public EventFileWriter { +class RAWEventFileLogger : public EventFileWriter { public: - RAWEventFileWriter(const std::string &path = std::string(), - const std::unordered_map &metadata_map = - std::unordered_map()); - ~RAWEventFileWriter() override; + RAWEventFileLogger(const std::filesystem::path &path = std::filesystem::path(), + const std::unordered_map &metadata_map = + std::unordered_map()); + ~RAWEventFileLogger() override; bool add_raw_data(const std::uint8_t *ptr, size_t size); private: - void open_impl(const std::string &path) override; + void open_impl(const std::filesystem::path &path) override; void close_impl() override; bool is_open_impl() const override; void flush_impl() override; @@ -47,4 +48,4 @@ class RAWEventFileWriter : public EventFileWriter { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_RAW_EVENT_FILE_WRITER_H +#endif // METAVISION_SDK_STREAM_RAW_EVENT_FILE_WRITER_H diff --git a/sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_event_file_reader.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_event_file_reader.h similarity index 87% rename from sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_event_file_reader.h rename to sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_event_file_reader.h index a0fbd625a..9face0332 100644 --- a/sdk/modules/driver/cpp/include/metavision/sdk/driver/raw_event_file_reader.h +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_event_file_reader.h @@ -9,11 +9,12 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_RAW_EVENT_FILE_READER_H -#define METAVISION_SDK_DRIVER_RAW_EVENT_FILE_READER_H +#ifndef METAVISION_SDK_STREAM_RAW_EVENT_FILE_READER_H +#define METAVISION_SDK_STREAM_RAW_EVENT_FILE_READER_H +#include #include -#include "metavision/sdk/driver/event_file_reader.h" +#include "metavision/sdk/stream/event_file_reader.h" namespace Metavision { @@ -21,7 +22,7 @@ class Device; class RAWEventFileReader : public EventFileReader { public: - RAWEventFileReader(Device &device, const std::string &path); + RAWEventFileReader(Device &device, const std::filesystem::path &path); ~RAWEventFileReader(); using RawDataBufferReadCallback = std::function; @@ -50,4 +51,4 @@ class RAWEventFileReader : public EventFileReader { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_RAW_EVENT_FILE_READER_H +#endif // METAVISION_SDK_STREAM_RAW_EVENT_FILE_READER_H diff --git a/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_evt2_event_file_writer.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_evt2_event_file_writer.h new file mode 100644 index 000000000..45da88b12 --- /dev/null +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/raw_evt2_event_file_writer.h @@ -0,0 +1,86 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_STREAM_RAW_EVT2_EVENT_FILE_WRITER_H +#define METAVISION_SDK_STREAM_RAW_EVT2_EVENT_FILE_WRITER_H + +#include +#include +#include +#include +#include +#include +#include "metavision/hal/utils/raw_file_header.h" +#include "metavision/sdk/stream/event_file_writer.h" + +namespace Metavision { + +class Evt2Encoder; + +/// @brief EventFileWriter specialized class to write events to a RAW EVT2 file +/// @note This class only supports writing CD and Trigger events +class RAWEvt2EventFileWriter : public EventFileWriter { +public: + /// @brief Constructor + /// @param stream_width Width of the stream + /// @param stream_height Height of the stream + /// @param path Path to the file to write to + /// @param enable_trigger_support If true, the writer will merge CD and Trigger event streams before writing them to + /// the file, leading to some encoding latency. If false, CD event will be written as soon as they are added to the + /// writer, and Trigger events will not be supported. + /// @param metadata_map Map of metadata to add in the header of the written file + /// @param max_events_add_latency Maximum latency for the addition of events, in camera time, beyond which the + /// writer will assume it can safely encode early buffered events. By default, there is no limit, meaning the writer + /// will buffer CD events until a least one trigger event is received, which may in certain cases lead to memory + /// issues. Alternatively, a finite positive latency value can be specified, the writer will then assume absence of + /// triggers if CD events have been buffered for a larger time, hence avoiding memory issues but with the risk of + /// EVT2 encoding errors if trigger events are actually received with a higher latency. + RAWEvt2EventFileWriter(int stream_width, int stream_height, + const std::filesystem::path &path = std::filesystem::path(), + bool enable_trigger_support = false, + const std::unordered_map &metadata_map = + std::unordered_map(), + timestamp max_events_add_latency = std::numeric_limits::max()); + + /// @brief Destructor + ~RAWEvt2EventFileWriter() override; + +private: + void open_impl(const std::filesystem::path &path) override; + void close_impl() override; + bool is_open_impl() const override; + void flush_impl() override; + + void add_metadata_impl(const std::string &key, const std::string &value) override; + void add_metadata_map_from_camera_impl(const Camera &camera) override; + void remove_metadata_impl(const std::string &key) override; + + bool add_events_impl(const EventCD *begin, const EventCD *end) override; + bool add_events_impl(const EventExtTrigger *begin, const EventExtTrigger *end) override; + + void encode_buffered_events(bool flush_all_queued_events); + void merge_encode_buffered_events(bool flush_all_queued_events); + + const bool exttrigger_support_enabled_; + const timestamp max_events_add_latency_; + RawFileHeader header_; + bool header_written_ = false; + std::ofstream ofs_; + std::deque events_trigger_; + std::deque events_cd_; + timestamp ts_last_cd_ = std::numeric_limits::min(), + ts_last_trigger_ = std::numeric_limits::min(); + std::unique_ptr encoder_; +}; + +} // namespace Metavision + +#endif // METAVISION_SDK_STREAM_RAW_EVT2_EVENT_FILE_WRITER_H diff --git a/sdk/modules/stream/cpp/include/metavision/sdk/stream/slice_iterator.h b/sdk/modules/stream/cpp/include/metavision/sdk/stream/slice_iterator.h new file mode 100644 index 000000000..c08bf57b7 --- /dev/null +++ b/sdk/modules/stream/cpp/include/metavision/sdk/stream/slice_iterator.h @@ -0,0 +1,72 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifndef METAVISION_SDK_STREAM_SLICE_ITERATOR_H +#define METAVISION_SDK_STREAM_SLICE_ITERATOR_H + +#include +#include "metavision/sdk/core/utils/concurrent_queue.h" + +namespace Metavision { + +/// @brief Iterator over slices +/// @tparam SliceT Type of the slice +template +class SliceIteratorT { +public: + using value_type = SliceT; + using difference_type = std::ptrdiff_t; + using pointer = SliceT *; + using reference = SliceT &; + using iterator_category = std::input_iterator_tag; + + using QueuePtr = std::shared_ptr>; + + /// @brief Default constructor + /// @param q A queue to retrieve slices from, if nullptr, the iterator will be invalid (i.e. end()) + explicit SliceIteratorT(QueuePtr q = nullptr); + + /// @brief Dereference operator + /// @return A reference to the current slice + reference operator*(); + + /// @brief Dereference operator + /// @return A pointer to the current slice + pointer operator->(); + + /// @brief Pre-increment operator + /// @return A reference to this instance + SliceIteratorT &operator++(); + + /// @brief Post-increment operator + /// @return A copy of this instance after the increment + SliceIteratorT operator++(int); + + /// @brief Equality comparison operator + /// @param other The other iterator to compare with + /// @return True if the two iterators are equal, false otherwise + bool operator==(const SliceIteratorT &other) const; + + /// @brief Inequality comparison operator + /// @param other The other iterator to compare with + /// @return True if the two iterators are different, false otherwise + bool operator!=(const SliceIteratorT &other) const; + +private: + QueuePtr queue_; + SliceT slice_; +}; + +} // namespace Metavision + +#include "metavision/sdk/stream/detail/slice_iterator_impl.h" + +#endif // METAVISION_SDK_STREAM_SLICE_ITERATOR_H diff --git a/sdk/modules/driver/cpp/lib/CMakeLists.txt b/sdk/modules/stream/cpp/lib/CMakeLists.txt similarity index 83% rename from sdk/modules/driver/cpp/lib/CMakeLists.txt rename to sdk/modules/stream/cpp/lib/CMakeLists.txt index 1a8558843..0aed12b7b 100644 --- a/sdk/modules/driver/cpp/lib/CMakeLists.txt +++ b/sdk/modules/stream/cpp/lib/CMakeLists.txt @@ -13,7 +13,7 @@ if (HDF5_FOUND) set(extra_required_packages "hdf5_ecf") endif (HDF5_FOUND) -MetavisionSDK_add_module(driver +MetavisionSDK_add_module(stream REQUIRED_METAVISION_SDK_MODULES PUBLIC base @@ -21,26 +21,25 @@ MetavisionSDK_add_module(driver EXTRA_REQUIRED_PACKAGE MetavisionHAL ${extra_required_packages} ) -target_link_libraries(metavision_sdk_driver +target_link_libraries(metavision_sdk_stream PUBLIC metavision_hal metavision_hal_discovery PRIVATE - Boost::filesystem metavision_device_serialization_obj ) if (HDF5_FOUND) - target_compile_definitions(metavision_sdk_driver + target_compile_definitions(metavision_sdk_stream PRIVATE HAS_HDF5 ${HDF5_DEFINITIONS} ${HDF5_CXX_DEFINITIONS} ) - target_include_directories(metavision_sdk_driver + target_include_directories(metavision_sdk_stream PRIVATE ${HDF5_INCLUDE_DIRS} ) - target_link_libraries(metavision_sdk_driver + target_link_libraries(metavision_sdk_stream PRIVATE ${HDF5_LIBRARIES} hdf5_ecf_codec diff --git a/sdk/modules/driver/cpp/samples/CMakeLists.txt b/sdk/modules/stream/cpp/samples/CMakeLists.txt similarity index 92% rename from sdk/modules/driver/cpp/samples/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/CMakeLists.txt index c871d9770..b103fd210 100644 --- a/sdk/modules/driver/cpp/samples/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/CMakeLists.txt @@ -7,10 +7,12 @@ # 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. +add_subdirectory(metavision_camera_stream_slicer) add_subdirectory(metavision_file_cutter) add_subdirectory(metavision_file_to_csv) add_subdirectory(metavision_file_to_dat) add_subdirectory(metavision_file_info) +add_subdirectory(metavision_raw_evt_encoder) add_subdirectory(metavision_viewer) if (HDF5_FOUND) diff --git a/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt similarity index 76% rename from sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt index a85b2e8db..d84c19eef 100644 --- a/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt @@ -8,7 +8,7 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_active_pixel_detection) -set (common_libraries MetavisionSDK::driver MetavisionSDK::core Boost::program_options opencv_highgui) +set (common_libraries MetavisionSDK::stream MetavisionSDK::core Boost::program_options opencv_highgui) add_executable(${sample} ${sample}.cpp $) target_include_directories(${sample} PRIVATE metavision_psee_hw_layer_obj) @@ -16,16 +16,16 @@ target_link_libraries(${sample} PRIVATE ${common_libraries} metavision_psee_hw_l install(TARGETS ${sample} RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples ) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install similarity index 89% rename from sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install rename to sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install index 31efbc559..637929e5d 100644 --- a/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install +++ b/sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/CMakeLists.txt.install @@ -14,10 +14,10 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) find_package(MetavisionPSEEHWLayer REQUIRED) -find_package(MetavisionSDK COMPONENTS core driver REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) find_package(OpenCV COMPONENTS highgui REQUIRED) add_executable(metavision_active_pixel_detection metavision_active_pixel_detection.cpp) -target_link_libraries(metavision_active_pixel_detection PRIVATE Metavision::PSEEHWLayer MetavisionSDK::driver MetavisionSDK::core Boost::program_options ${OpenCV_LIBS}) +target_link_libraries(metavision_active_pixel_detection PRIVATE Metavision::PSEEHWLayer MetavisionSDK::stream MetavisionSDK::core Boost::program_options ${OpenCV_LIBS}) diff --git a/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp b/sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp similarity index 98% rename from sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp rename to sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp index 768423566..fa688629a 100644 --- a/sdk/modules/driver/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_active_pixel_detection/metavision_active_pixel_detection.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -333,7 +333,7 @@ int main(int argc, char *argv[]) { [&avg_rate](Metavision::timestamp ts, double arate, double) { avg_rate = arate; }, 100000, 1000000, true); // Setup CD frame generator - Metavision::CDFrameGenerator cd_frame_generator(geometry.width(), geometry.height()); + Metavision::CDFrameGenerator cd_frame_generator(geometry.get_width(), geometry.get_height()); cd_frame_generator.set_display_accumulation_time_us(10000); std::mutex cd_frame_mutex; @@ -354,7 +354,7 @@ int main(int argc, char *argv[]) { std::string cd_window_name("CD Events"); cv::namedWindow(cd_window_name, cv::WINDOW_NORMAL); cv::setWindowProperty(cd_window_name, cv::WND_PROP_ASPECT_RATIO, cv::WINDOW_KEEPRATIO); - cv::resizeWindow(cd_window_name, geometry.width(), geometry.height()); + cv::resizeWindow(cd_window_name, geometry.get_width(), geometry.get_height()); cv::moveWindow(cd_window_name, 0, 0); #if (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION * 100 + CV_SUBMINOR_VERSION) >= 408) || \ (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION * 100 + CV_SUBMINOR_VERSION) >= 102) @@ -379,7 +379,7 @@ int main(int argc, char *argv[]) { std::vector events; - Data data(geometry.width(), geometry.height()); + Data data(geometry.get_width(), geometry.get_height()); data.camera = &camera; int calib_cb_id = -1; @@ -407,8 +407,8 @@ int main(int argc, char *argv[]) { if (!calib_setup) { cv::namedWindow(calib_window_name, cv::WINDOW_NORMAL); cv::setWindowProperty(calib_window_name, cv::WND_PROP_ASPECT_RATIO, cv::WINDOW_KEEPRATIO); - cv::resizeWindow(calib_window_name, geometry.width(), geometry.height()); - cv::moveWindow(calib_window_name, 0, geometry.height()); + cv::resizeWindow(calib_window_name, geometry.get_width(), geometry.get_height()); + cv::moveWindow(calib_window_name, 0, geometry.get_height()); #if (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION * 100 + CV_SUBMINOR_VERSION) >= 408) || \ (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION * 100 + CV_SUBMINOR_VERSION) >= 102) cv::setWindowProperty(calib_window_name, cv::WND_PROP_TOPMOST, 1); diff --git a/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/CMakeLists.txt new file mode 100644 index 000000000..d6c799fb3 --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) Prophesee S.A. +# +# 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 (sample metavision_camera_stream_slicer) +add_executable(${sample} ${sample}.cpp) +target_link_libraries(${sample} PRIVATE MetavisionSDK::core MetavisionSDK::stream Boost::program_options) + +install(FILES ${sample}.cpp + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples +) + +install(FILES CMakeLists.txt.install + RENAME CMakeLists.txt + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples +) \ No newline at end of file diff --git a/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/CMakeLists.txt.install new file mode 100644 index 000000000..cb4048385 --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/CMakeLists.txt.install @@ -0,0 +1,22 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +project(metavision_camera_stream_slicer) + +cmake_minimum_required(VERSION 3.5) + +set(CMAKE_CXX_STANDARD 17) + +find_package(MetavisionSDK COMPONENTS core stream REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED) +find_package(OpenCV COMPONENTS highgui REQUIRED) + +add_executable(metavision_camera_stream_slicer metavision_camera_stream_slicer.cpp) +target_link_libraries(metavision_camera_stream_slicer PRIVATE MetavisionSDK::stream MetavisionSDK::core Boost::program_options ${OpenCV_LIBS}) + diff --git a/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/metavision_camera_stream_slicer.cpp b/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/metavision_camera_stream_slicer.cpp new file mode 100644 index 000000000..4e92fd535 --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_camera_stream_slicer/metavision_camera_stream_slicer.cpp @@ -0,0 +1,168 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +// This code demonstrates how to use the Metavision CameraStreamSlicer to slice the events from a camera or a file into +// slices of a fixed number of events or a fixed duration. + +#include +#include + +#include +#include + +using SlicingMode = Metavision::EventBufferReslicerAlgorithm::ConditionType; +using SlicingCondition = Metavision::EventBufferReslicerAlgorithm::Condition; + +namespace std { +const std::unordered_map kSlicingModeToStr = {{SlicingMode::IDENTITY, "IDENTITY"}, + {SlicingMode::N_EVENTS, "N_EVENTS"}, + {SlicingMode::N_US, "N_US"}, + {SlicingMode::MIXED, "MIXED"}}; + +const std::unordered_map kStrToSlicingMode = {{"IDENTITY", SlicingMode::IDENTITY}, + {"N_EVENTS", SlicingMode::N_EVENTS}, + {"N_US", SlicingMode::N_US}, + {"MIXED", SlicingMode::MIXED}}; + +std::istream &operator>>(std::istream &is, SlicingMode &mode) { + std::string s; + is >> s; + auto it = kStrToSlicingMode.find(s); + if (it == kStrToSlicingMode.cend()) + throw std::runtime_error("Failed to convert string to slicing mode"); + mode = it->second; + return is; +} + +std::ostream &operator<<(std::ostream &os, const SlicingMode &mode) { + auto it = kSlicingModeToStr.find(mode); + if (it == kSlicingModeToStr.cend()) + throw std::runtime_error("Failed to convert slicing mode to string"); + os << it->second; + return os; +} +} // namespace std + +struct Config { + std::string record_path; + std::string serial_number; + SlicingCondition slicing_condition; +}; + +std::optional parse_command_line(int argc, char *argv[]) { + namespace po = boost::program_options; + + Metavision::timestamp delta_ts; + size_t delta_n_events; + SlicingMode slicing_mode; + + const std::string program_desc("Code sample showing how to use the Metavision Slicer"); + + Config config; + po::options_description options_desc; + po::options_description base_options("Base options"); + // clang-format off + base_options.add_options() + ("help,h", "Produce help message.") + ("input-event-file,i", po::value(&config.record_path), "Path to input event file (RAW or HDF5). If not specified, the camera live stream is used.") + ("camera-serial-number,s", po::value(&config.serial_number), "Serial number of the camera to be used") + ; + // clang-format on + + po::options_description slicing_options("Slicing options"); + // clang-format off + slicing_options.add_options() + ("slicing-mode,m", po::value(&slicing_mode)->default_value(SlicingMode::N_US), "Slicing mode (i.e. N_EVENTS, N_US, MIXED)") + ("delta-ts,t", po::value(&delta_ts)->default_value(1000), "Slice duration in us") + ("delta-n-events,n", po::value(&delta_n_events)->default_value(1000), "Number of events in a slice") + ; + // clang-format on + + options_desc.add(base_options).add(slicing_options); + + po::variables_map vm; + try { + po::store(po::command_line_parser(argc, argv).options(options_desc).run(), vm); + po::notify(vm); + } catch (po::error &e) { + MV_LOG_ERROR() << program_desc; + MV_LOG_ERROR() << options_desc; + MV_LOG_ERROR() << "Parsing error:" << e.what(); + return std::nullopt; + } + + if (vm.count("help")) { + MV_LOG_INFO() << program_desc; + MV_LOG_INFO() << options_desc; + return std::nullopt; + } + + switch (slicing_mode) { + case SlicingMode::IDENTITY: + config.slicing_condition = SlicingCondition::make_identity(); + break; + + case SlicingMode::N_EVENTS: + config.slicing_condition = SlicingCondition::make_n_events(delta_n_events); + break; + + case SlicingMode::N_US: + config.slicing_condition = SlicingCondition::make_n_us(delta_ts); + break; + + case SlicingMode::MIXED: + config.slicing_condition = SlicingCondition::make_mixed(delta_ts, delta_n_events); + break; + } + + return config; +} + +int main(int argc, char *argv[]) { + const auto config = parse_command_line(argc, argv); + if (!config) + return 1; + + Metavision::Camera camera; + + if (!config->record_path.empty()) { + camera = Metavision::Camera::from_file(config->record_path); + } else { + camera = Metavision::Camera::from_serial(config->serial_number); + } + + const auto &geometry = camera.geometry(); + const auto width = geometry.get_width(); + const auto height = geometry.get_height(); + + cv::Mat frame_8uc3(height, width, CV_8UC3); + + Metavision::CameraStreamSlicer slicer(std::move(camera), config->slicing_condition); + + for (const auto &slice : slicer) { + MV_LOG_INFO() << "ts:" << slice.t << "new slice of" << slice.n_events << "events"; + + frame_8uc3.create(height, width, CV_8UC3); + Metavision::BaseFrameGenerationAlgorithm::generate_frame_from_events(slice.events->cbegin(), + slice.events->cend(), frame_8uc3); + + for (const auto &t : *slice.triggers) { + MV_LOG_INFO() << "ts:" << t.t << "new external trigger with polarity" << t.p; + } + + cv::imshow("Camera stream slicer", frame_8uc3); + const auto cmd = cv::waitKey(1); + if (cmd == 'q') + break; + } + + return 0; +} \ No newline at end of file diff --git a/sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_cutter/CMakeLists.txt similarity index 75% rename from sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_cutter/CMakeLists.txt index ee9b9d5c6..448cb0c87 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_file_cutter/CMakeLists.txt @@ -8,22 +8,22 @@ # See the License for the specific language governing permissions and limitations under the License. add_executable(metavision_file_cutter metavision_file_cutter.cpp) -target_link_libraries(metavision_file_cutter PRIVATE MetavisionSDK::driver Boost::program_options Threads::Threads) +target_link_libraries(metavision_file_cutter PRIVATE MetavisionSDK::stream Boost::program_options Threads::Threads) install(TARGETS metavision_file_cutter RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES metavision_file_cutter.cpp - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_cutter - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_cutter + COMPONENT metavision-sdk-stream-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_cutter - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_cutter + COMPONENT metavision-sdk-stream-samples ) # Test application diff --git a/sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_file_cutter/CMakeLists.txt.install similarity index 89% rename from sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt.install rename to sdk/modules/stream/cpp/samples/metavision_file_cutter/CMakeLists.txt.install index cec9455f9..f760def86 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_cutter/CMakeLists.txt.install +++ b/sdk/modules/stream/cpp/samples/metavision_file_cutter/CMakeLists.txt.install @@ -12,9 +12,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS driver REQUIRED) +find_package(MetavisionSDK COMPONENTS stream REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) find_package(Threads REQUIRED) add_executable(metavision_file_cutter metavision_file_cutter.cpp) -target_link_libraries(metavision_file_cutter PRIVATE MetavisionSDK::driver Boost::program_options Threads::Threads) \ No newline at end of file +target_link_libraries(metavision_file_cutter PRIVATE MetavisionSDK::stream Boost::program_options Threads::Threads) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp b/sdk/modules/stream/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp similarity index 96% rename from sdk/modules/driver/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp rename to sdk/modules/stream/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp index 408ee1486..ce1733e27 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_file_cutter/metavision_file_cutter.cpp @@ -14,9 +14,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include namespace po = boost::program_options; @@ -81,7 +81,7 @@ int main(int argc, char *argv[]) { if (out_file_ext == ".raw") { try { camera.raw_data(); - writer = std::make_unique(out_file_path); + writer = std::make_unique(out_file_path); } catch (const Metavision::CameraException &) { MV_LOG_ERROR() << "Unable to cut to RAW from a file that does not contain RAW data"; return 1; @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) { if (done) { return; } - auto *raw_writer = static_cast(writer.get()); + auto *raw_writer = static_cast(writer.get()); auto last_ts = camera.get_last_timestamp(); if (last_ts >= start_ts && last_ts <= end_ts) { raw_writer->add_raw_data(ptr, size); diff --git a/sdk/modules/driver/cpp/samples/metavision_file_cutter/test/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_cutter/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_cutter/test/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_cutter/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py b/sdk/modules/stream/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py similarity index 97% rename from sdk/modules/driver/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py rename to sdk/modules/stream/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py index 28d9fcca5..1229aa977 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py +++ b/sdk/modules/stream/cpp/samples/metavision_file_cutter/test/metavision_file_cutter_pytest.py @@ -186,7 +186,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen31_recording_from_0s_to_6s( Plugin name hal_plugin_gen31_fx3 Data encoding EVT2 Camera generation 3.1 -Camera systemID \d* Camera serial 00001621 ==================================================================================================== @@ -219,7 +218,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen31_recording_from_8s_to_11s Plugin name hal_plugin_gen31_fx3 Data encoding EVT2 Camera generation 3.1 -Camera systemID \d* Camera serial 00001621 ==================================================================================================== @@ -252,8 +250,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen4_evt2_recording_full_cut(d Plugin name hal_plugin_gen41_evk3 Data encoding EVT2 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -286,8 +282,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen4_evt2_recording_from_2s_to Plugin name hal_plugin_gen41_evk3 Data encoding EVT2 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -320,8 +314,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen4_evt2_recording_from_4s_to Plugin name hal_plugin_gen41_evk3 Data encoding EVT2 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -354,8 +346,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen4_evt3_recording_full_cut(d Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -388,8 +378,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen4_evt3_recording_from_3s_to Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -422,8 +410,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen4_evt3_recording_from_8s_to Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -456,8 +442,6 @@ def pytestcase_test_metavision_file_cutter_on_raw_gen4_evt3_recording_from_4s_to Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d*(?: -Camera subsystemID 537921537)? Camera serial 00001495 ==================================================================================================== @@ -505,7 +489,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen31_recording_from_0s_to_6s Integrator Prophesee Data encoding ECF Camera generation 3.1 -Camera systemID 28 Camera serial 00001621 ==================================================================================================== @@ -538,7 +521,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen31_recording_from_8s_to_11 Integrator Prophesee Data encoding ECF Camera generation 3.1 -Camera systemID 28 Camera serial 00001621 ==================================================================================================== @@ -571,7 +553,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen4_evt2_recording_full_cut( Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID 26 Camera serial 00001495 ==================================================================================================== @@ -604,7 +585,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen4_evt2_recording_from_2s_t Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID 26 Camera serial 00001495 ==================================================================================================== @@ -637,7 +617,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen4_evt2_recording_from_4s_t Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID 26 Camera serial 00001495 ==================================================================================================== @@ -670,7 +649,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen4_evt3_recording_full_cut( Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID 26 Camera serial 00001495 ==================================================================================================== @@ -703,7 +681,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen4_evt3_recording_from_3s_t Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID 26 Camera serial 00001495 ==================================================================================================== @@ -736,7 +713,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen4_evt3_recording_from_8s_t Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID 26 Camera serial 00001495 ==================================================================================================== @@ -769,7 +745,6 @@ def pytestcase_test_metavision_file_cutter_on_hdf5_gen4_evt3_recording_from_4s_t Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID 26 Camera serial 00001495 ==================================================================================================== diff --git a/sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_info/CMakeLists.txt similarity index 74% rename from sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_info/CMakeLists.txt index 38a97cd18..d49929a22 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_file_info/CMakeLists.txt @@ -8,22 +8,22 @@ # See the License for the specific language governing permissions and limitations under the License. add_executable(metavision_file_info metavision_file_info.cpp) -target_link_libraries(metavision_file_info PRIVATE MetavisionSDK::driver Boost::program_options Boost::filesystem Threads::Threads) +target_link_libraries(metavision_file_info PRIVATE MetavisionSDK::stream Boost::program_options Threads::Threads) install(TARGETS metavision_file_info RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES metavision_file_info.cpp - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_info - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_info + COMPONENT metavision-sdk-stream-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_info - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_info + COMPONENT metavision-sdk-stream-samples ) # Test application diff --git a/sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_file_info/CMakeLists.txt.install similarity index 81% rename from sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt.install rename to sdk/modules/stream/cpp/samples/metavision_file_info/CMakeLists.txt.install index 0319c4ad8..3633e11fe 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_info/CMakeLists.txt.install +++ b/sdk/modules/stream/cpp/samples/metavision_file_info/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS driver REQUIRED) -find_package(Boost COMPONENTS program_options filesystem REQUIRED) +find_package(MetavisionSDK COMPONENTS stream REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED) find_package(Threads REQUIRED) add_executable(metavision_file_info metavision_file_info.cpp) -target_link_libraries(metavision_file_info PRIVATE MetavisionSDK::driver Boost::program_options Boost::filesystem Threads::Threads) +target_link_libraries(metavision_file_info PRIVATE MetavisionSDK::stream Boost::program_options Threads::Threads) diff --git a/sdk/modules/driver/cpp/samples/metavision_file_info/metavision_file_info.cpp b/sdk/modules/stream/cpp/samples/metavision_file_info/metavision_file_info.cpp similarity index 94% rename from sdk/modules/driver/cpp/samples/metavision_file_info/metavision_file_info.cpp rename to sdk/modules/stream/cpp/samples/metavision_file_info/metavision_file_info.cpp index 42e8bc8de..052d37af3 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_info/metavision_file_info.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_file_info/metavision_file_info.cpp @@ -9,7 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// Example of using Metavision SDK Driver API to get information about an event file. +// Example of using Metavision SDK Stream API to get information about an event file. #include #include @@ -17,12 +17,12 @@ #include #include #include +#include #include -#include #include #include -#include -#include +#include +#include namespace po = boost::program_options; @@ -177,9 +177,9 @@ int main(int argc, char *argv[]) { log << "\r" << line_sep << "\n\n"; const std::string global_format("%-20s%s"); - log << boost::format(global_format) % "Name" % boost::filesystem::path(in_file_path).filename().string() << "\n"; + log << boost::format(global_format) % "Name" % std::filesystem::path(in_file_path).filename().string() << "\n"; log << boost::format(global_format) % "Path" % - boost::filesystem::canonical(boost::filesystem::path(in_file_path)).make_preferred().string() + std::filesystem::canonical(in_file_path).make_preferred().string() << "\n"; log << boost::format(global_format) % "Duration" % human_readable_time(duration) << "\n"; @@ -201,10 +201,6 @@ int main(int argc, char *argv[]) { tmp_oss << gen.version_major() << "." << gen.version_minor(); log << boost::format(global_format) % "Camera generation" % tmp_oss.str() << "\n"; - if (!config.system_ID.empty()) { - log << boost::format(global_format) % "Camera systemID" % config.system_ID << "\n"; - } - if (!config.serial_number.empty()) { log << boost::format(global_format) % "Camera serial" % config.serial_number << "\n"; } diff --git a/sdk/modules/driver/cpp/samples/metavision_file_info/test/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_info/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_info/test/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_info/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py b/sdk/modules/stream/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py similarity index 98% rename from sdk/modules/driver/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py rename to sdk/modules/stream/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py index e8aab287a..599592dd1 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py +++ b/sdk/modules/stream/cpp/samples/metavision_file_info/test/metavision_file_info_pytest.py @@ -103,7 +103,6 @@ def pytestcase_test_metavision_file_info_on_gen31_raw_recording(dataset_dir): Plugin name hal_plugin_gen31_fx3 Data encoding EVT2 Camera generation 3.1 -Camera systemID \d* Camera serial 00001621 ==================================================================================================== @@ -133,7 +132,6 @@ def pytestcase_test_metavision_file_info_on_gen4_evt2_raw_recording(dataset_dir) Plugin name hal_plugin_gen41_evk3 Data encoding EVT2 Camera generation 4.0 -Camera systemID \d* Camera serial 00001495 ==================================================================================================== @@ -163,7 +161,6 @@ def pytestcase_test_metavision_file_info_on_gen4_evt3_raw_recording(dataset_dir) Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d* Camera serial 00001495 ==================================================================================================== @@ -193,7 +190,6 @@ def pytestcase_test_metavision_file_info_on_gen4_evt3_with_triggers_raw_recordin Plugin name hal_plugin_gen41_evk3 Data encoding EVT3 Camera generation 4.0 -Camera systemID \d* Camera serial 00001167 ==================================================================================================== @@ -224,7 +220,6 @@ def pytestcase_test_metavision_file_info_on_gen31_hdf5_recording(dataset_dir): Integrator Prophesee Data encoding ECF Camera generation 3.1 -Camera systemID \d* Camera serial 00001621 ==================================================================================================== @@ -254,7 +249,6 @@ def pytestcase_test_metavision_file_info_on_gen4_evt2_hdf5_recording(dataset_dir Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID \d* Camera serial 00001495 ==================================================================================================== @@ -284,7 +278,6 @@ def pytestcase_test_metavision_file_info_on_gen4_evt3_hdf5_recording(dataset_dir Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID \d* Camera serial 00001495 ==================================================================================================== @@ -314,7 +307,6 @@ def pytestcase_test_metavision_file_info_on_gen4_evt3_with_triggers_hdf5_recordi Integrator Prophesee Data encoding ECF Camera generation 4.0 -Camera systemID \d* Camera serial 00001167 ==================================================================================================== diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/CMakeLists.txt similarity index 74% rename from sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_to_csv/CMakeLists.txt index c0ea7a1ad..61a2d2ad2 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/CMakeLists.txt @@ -8,25 +8,25 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_file_to_csv) -set (common_libraries MetavisionSDK::core MetavisionSDK::driver Boost::program_options) +set (common_libraries MetavisionSDK::core MetavisionSDK::stream Boost::program_options) add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(TARGETS ${sample} RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples ) # Test application diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/CMakeLists.txt.install similarity index 90% rename from sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt.install rename to sdk/modules/stream/cpp/samples/metavision_file_to_csv/CMakeLists.txt.install index 10023a6ae..e37f52b7e 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/CMakeLists.txt.install +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) set (sample metavision_file_to_csv) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver Boost::program_options) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream Boost::program_options) diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/metavision_file_to_csv.cpp b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/metavision_file_to_csv.cpp similarity index 94% rename from sdk/modules/driver/cpp/samples/metavision_file_to_csv/metavision_file_to_csv.cpp rename to sdk/modules/stream/cpp/samples/metavision_file_to_csv/metavision_file_to_csv.cpp index 0e9f46285..850c5da05 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/metavision_file_to_csv.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/metavision_file_to_csv.cpp @@ -9,7 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// This code sample demonstrates how to use Metavision SDK Driver to convert an event file +// This code sample demonstrates how to use Metavision SDK Stream to convert an event file // to a CSV formatted event file. #include @@ -17,8 +17,8 @@ #include #include #include -#include -#include +#include +#include class CSVWriter { public: @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) { std::string out_file_path; const std::string program_desc( - "Code sample demonstrating how to use Metavision SDK Driver to convert a file to a CSV formatted" + "Code sample demonstrating how to use Metavision SDK Stream to convert a file to a CSV formatted" " file.\n"); po::options_description options_desc("Options"); diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/test/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_to_csv/test/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_to_csv/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_csv/test/metavision_file_to_csv_pytest.py b/sdk/modules/stream/cpp/samples/metavision_file_to_csv/test/metavision_file_to_csv_pytest.py similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_to_csv/test/metavision_file_to_csv_pytest.py rename to sdk/modules/stream/cpp/samples/metavision_file_to_csv/test/metavision_file_to_csv_pytest.py diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/CMakeLists.txt similarity index 75% rename from sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_to_dat/CMakeLists.txt index dd7596542..6872ac6bf 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/CMakeLists.txt @@ -8,22 +8,22 @@ # See the License for the specific language governing permissions and limitations under the License. add_executable(metavision_file_to_dat metavision_file_to_dat.cpp) -target_link_libraries(metavision_file_to_dat PRIVATE MetavisionSDK::core MetavisionSDK::driver Boost::program_options) +target_link_libraries(metavision_file_to_dat PRIVATE MetavisionSDK::core MetavisionSDK::stream Boost::program_options) install(TARGETS metavision_file_to_dat RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES metavision_file_to_dat.cpp - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_dat - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_to_dat + COMPONENT metavision-sdk-stream-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_dat - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_to_dat + COMPONENT metavision-sdk-stream-samples ) # Test application diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install similarity index 90% rename from sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install rename to sdk/modules/stream/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install index c1050cfc8..5da97ccf0 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) set (sample metavision_file_to_dat) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver Boost::program_options) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream Boost::program_options) diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp similarity index 94% rename from sdk/modules/driver/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp rename to sdk/modules/stream/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp index d345b4581..e83cc4cd8 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/metavision_file_to_dat.cpp @@ -9,7 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// This application demonstrates how to use Metavision SDK Driver to convert a RAW or HDF5 event file to a DAT file. +// This application demonstrates how to use Metavision SDK Stream to convert a RAW or HDF5 event file to a DAT file. #include #include @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include namespace po = boost::program_options; @@ -63,8 +63,8 @@ int main(int argc, char *argv[]) { MV_LOG_ERROR() << e.what(); return 1; } - const unsigned short width = camera.geometry().width(); - const unsigned short height = camera.geometry().height(); + const unsigned short width = camera.geometry().get_width(); + const unsigned short height = camera.geometry().get_height(); // get the base of the input filename and the path const std::string output_base = std::regex_replace(event_file_path, std::regex("\\.[^.]*$"), ""); diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_to_dat/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py b/sdk/modules/stream/cpp/samples/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py rename to sdk/modules/stream/cpp/samples/metavision_file_to_dat/test/metavision_file_to_dat_pytest.py diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt similarity index 78% rename from sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt index 02559a160..076b2b4a3 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt @@ -10,22 +10,22 @@ add_executable(metavision_file_to_hdf5 metavision_file_to_hdf5.cpp) target_compile_definitions(metavision_file_to_hdf5 PRIVATE ${HDF5_DEFINITIONS} ${HDF5_CXX_DEFINITIONS}) target_include_directories(metavision_file_to_hdf5 PRIVATE ${HDF5_INCLUDE_DIRS}) -target_link_libraries(metavision_file_to_hdf5 PRIVATE MetavisionSDK::core MetavisionSDK::driver Boost::program_options ${HDF5_LIBRARIES}) +target_link_libraries(metavision_file_to_hdf5 PRIVATE MetavisionSDK::core MetavisionSDK::stream Boost::program_options ${HDF5_LIBRARIES}) install(TARGETS metavision_file_to_hdf5 RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES metavision_file_to_hdf5.cpp - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_hdf5 - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_to_hdf5 + COMPONENT metavision-sdk-stream-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/cpp_samples/metavision_file_to_hdf5 - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_file_to_hdf5 + COMPONENT metavision-sdk-stream-samples ) # Test application diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install similarity index 90% rename from sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install rename to sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install index 265bf73e7..9ca5a1619 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/CMakeLists.txt.install @@ -13,9 +13,9 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) set (sample metavision_file_to_hdf5) add_executable(${sample} ${sample}.cpp) -target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::driver Boost::program_options) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream Boost::program_options) diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp similarity index 75% rename from sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp rename to sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp index 5109859c3..bc083738d 100644 --- a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/metavision_file_to_hdf5.cpp @@ -9,7 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// This application demonstrates how to use Metavision SDK Core pipeline utility and SDK Driver to convert +// This application demonstrates how to use Metavision SDK Core and SDK Stream to convert // an event file to an HDF5 file. #include @@ -20,10 +20,8 @@ #include #include #include -#include -#include -#include -#include +#include +#include namespace po = boost::program_options; @@ -38,22 +36,6 @@ int convert_file_to_hdf5(const std::filesystem::path &in_file_path, const std::f std::filesystem::create_directories(out_hdf5_file_path.parent_path()); } - // A pipeline for which all added stages will automatically be run in their own processing threads (if applicable) - Metavision::Pipeline p(true); - - /// Pipeline - // 0 (Camera) - // | - // v - // | - // |----------<--------->-----------| - // | | - // v v - // | | - // 1 (Write CD) 2 (Write Ext Trigger) - // - - // 0) Stage producing events from a camera Metavision::Camera camera; try { camera = Metavision::Camera::from_file(in_file_path.string(), @@ -62,39 +44,25 @@ int convert_file_to_hdf5(const std::filesystem::path &in_file_path, const std::f MV_LOG_ERROR() << e.what(); return 1; } - auto &cam_stage = p.add_stage(std::make_unique(std::move(camera))); - // Gets the wrapped camera from the stage to extract sensor's resolution - Metavision::Camera &cam = cam_stage.camera(); // Build an HDF5 file writer Metavision::HDF5EventFileWriter hdf5_writer(out_hdf5_file_path.string()); - hdf5_writer.add_metadata_map_from_camera(cam); - - // 1) Stage that will write CD events to an HDF5 file - auto cd_stage_ptr = std::make_unique(); - cd_stage_ptr->set_consuming_callback([&hdf5_writer](const boost::any &data) { - try { - auto buffer = boost::any_cast(data); - hdf5_writer.add_events(buffer->data(), buffer->data() + buffer->size()); - } catch (boost::bad_any_cast &) {} - }); - p.add_stage(std::move(cd_stage_ptr), cam_stage); - - // 2) Stage that will write external triggers events to an HDF5 file + hdf5_writer.add_metadata_map_from_camera(camera); + + // Process EventCD into HDF5 data try { - cam.ext_trigger().add_callback( - [&cam_stage](const Metavision::EventExtTrigger *begin, const Metavision::EventExtTrigger *end) { - cam_stage.add_ext_trigger_events(begin, end); + camera.cd().add_callback( + [&hdf5_writer](const Metavision::EventCD *begin, const Metavision::EventCD *end) { + hdf5_writer.add_events(begin, end); }); + } catch (Metavision::CameraException &) {} - auto ext_trigger_stage_ptr = std::make_unique(); - ext_trigger_stage_ptr->set_consuming_callback([&hdf5_writer](const boost::any &data) { - try { - auto buffer = boost::any_cast(data); - hdf5_writer.add_events(buffer->data(), buffer->data() + buffer->size()); - } catch (boost::bad_any_cast &) {} - }); - p.add_stage(std::move(ext_trigger_stage_ptr), cam_stage); + // Process EventExtTrigger into HDF5 data + try { + camera.ext_trigger().add_callback( + [&hdf5_writer](const Metavision::EventExtTrigger *begin, const Metavision::EventExtTrigger *end) { + hdf5_writer.add_events(begin, end); + }); } catch (Metavision::CameraException &) {} // Run the pipeline step by step to give a visual feedback about the progression @@ -104,7 +72,8 @@ int convert_file_to_hdf5(const std::filesystem::path &in_file_path, const std::f int dots = 0; auto last_time = std::chrono::high_resolution_clock::now(); - while (p.step()) { + camera.start(); + while (camera.is_running()) { const auto time = std::chrono::high_resolution_clock::now(); if (std::chrono::duration_cast(time - last_time) > 500ms) { last_time = time; @@ -113,6 +82,7 @@ int convert_file_to_hdf5(const std::filesystem::path &in_file_path, const std::f dots = (dots + 1) % 4; } } + camera.stop(); hdf5_writer.close(); diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/test/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/test/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py b/sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py rename to sdk/modules/stream/cpp/samples/metavision_file_to_hdf5/test/metavision_file_to_hdf5_pytest.py diff --git a/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/CMakeLists.txt new file mode 100644 index 000000000..c393b976b --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +add_executable(metavision_raw_evt_encoder metavision_raw_evt_encoder.cpp) +target_link_libraries(metavision_raw_evt_encoder PRIVATE MetavisionSDK::core MetavisionSDK::stream Boost::program_options) + +install(FILES metavision_raw_evt_encoder.cpp + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_raw_evt_encoder + COMPONENT metavision-sdk-stream-samples +) + +install(FILES CMakeLists.txt.install + RENAME CMakeLists.txt + DESTINATION share/metavision/sdk/stream/cpp_samples/metavision_raw_evt_encoder + COMPONENT metavision-sdk-stream-samples +) diff --git a/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/CMakeLists.txt.install new file mode 100644 index 000000000..11005ed82 --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/CMakeLists.txt.install @@ -0,0 +1,21 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +project(metavision_raw_evt_encoder) + +cmake_minimum_required(VERSION 3.5) + +set(CMAKE_CXX_STANDARD 17) + +find_package(MetavisionSDK COMPONENTS core stream REQUIRED) +find_package(Boost COMPONENTS program_options REQUIRED) + +set (sample metavision_raw_evt_encoder) +add_executable(${sample} ${sample}.cpp) +target_link_libraries(${sample} MetavisionSDK::core MetavisionSDK::stream Boost::program_options) diff --git a/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/metavision_raw_evt_encoder.cpp b/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/metavision_raw_evt_encoder.cpp new file mode 100644 index 000000000..194c90dfa --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_raw_evt_encoder/metavision_raw_evt_encoder.cpp @@ -0,0 +1,122 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +// This application demonstrates how to use Metavision SDK Stream module to decode an event recording, process it and +// encode it back to RAW EVT2 format. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace po = boost::program_options; + +int main(int argc, char *argv[]) { + std::filesystem::path in_path; + std::filesystem::path out_path; + bool encode_triggers = false; + Metavision::timestamp max_event_latency = -1; + + const std::string program_desc("Sample application to process a decoded event stream and encode it to RAW EVT2.\n"); + + po::options_description options_desc("Options"); + // clang-format off + options_desc.add_options() + ("help,h", "Produce help message.") + ("input-path,i", po::value(&in_path)->required(), "Path to input event file.") + ("output-path,o", po::value(&out_path)->default_value(""), "Path to output file. If not specified, will use a modified version of the input path.") + ("encode-triggers", po::bool_switch(&encode_triggers), "Flag to activate encoding of external trigger events.") + ("max-event-latency", po::value(&max_event_latency)->default_value(-1), "Maximum latency in camera time for the reception of events, infinite by default.") + ; + // clang-format on + + po::variables_map vm; + po::store(po::command_line_parser(argc, argv).options(options_desc).run(), vm); + if (vm.count("help")) { + MV_LOG_INFO() << program_desc; + MV_LOG_INFO() << options_desc; + return 0; + } + + try { + po::notify(vm); + } catch (po::error &e) { + MV_LOG_ERROR() << program_desc; + MV_LOG_ERROR() << options_desc; + MV_LOG_ERROR() << "Parsing error:" << e.what(); + return 1; + } + + // Get the output filename + if (out_path.empty()) { + out_path = in_path.parent_path() / in_path.stem(); + out_path.concat("_evt_encoded.raw"); + } + + // Create the camera + Metavision::Camera camera = Metavision::Camera::from_file(in_path.string()); + const auto width = camera.geometry().get_width(); + const auto height = camera.geometry().get_height(); + + // Instantiate the pipeline for processing decoded events, here a simple flip y algorithm + Metavision::FlipYAlgorithm yflipper(height - 1); + + // Instantiate the RAW encoder + Metavision::RAWEvt2EventFileWriter writer(width, height, out_path.string(), encode_triggers, {}, max_event_latency); + + // Setup console feedback to be provided on processing progression + using namespace std::chrono_literals; + auto log = MV_LOG_INFO() << Metavision::Log::no_space << Metavision::Log::no_endline; + log << "Writing to " << out_path << "\n"; + const std::string message("Encoding RAW file..."); + log << message << std::flush; + int dots = 0; + auto last_time = std::chrono::high_resolution_clock::now(); + auto progress_feedback_fct = [&]() { + const auto time = std::chrono::high_resolution_clock::now(); + if (std::chrono::duration_cast(time - last_time) > 500ms) { + last_time = time; + log << "\r" << message.substr(0, message.size() - 3 + dots) + std::string(" ").substr(0, 3 - dots) + << std::flush; + dots = (dots + 1) % 4; + } + }; + + // Define the callback to process the events + std::vector events; + camera.cd().add_callback([&](const Metavision::EventCD *begin, const Metavision::EventCD *end) { + events.clear(); + yflipper.process_events(begin, end, std::back_inserter(events)); + writer.add_events(events.data(), events.data() + events.size()); + progress_feedback_fct(); + }); + if (encode_triggers) { + camera.ext_trigger().add_callback( + [&](const Metavision::EventExtTrigger *begin, const Metavision::EventExtTrigger *end) { + writer.add_events(begin, end); + }); + } + + // Start the camera and the processing/encoding + camera.start(); + while (camera.is_running()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + }; + log << "\rDone! " << std::endl; + camera.stop(); + + return 0; +} diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_viewer/CMakeLists.txt similarity index 73% rename from sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_viewer/CMakeLists.txt index 32a4ee6b6..3423db1df 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_viewer/CMakeLists.txt @@ -8,23 +8,23 @@ # See the License for the specific language governing permissions and limitations under the License. set (sample metavision_viewer) -set (common_libraries MetavisionSDK::driver MetavisionSDK::core Boost::program_options opencv_highgui) +set (common_libraries MetavisionSDK::stream MetavisionSDK::core Boost::program_options opencv_highgui) add_executable(${sample} ${sample}.cpp) target_link_libraries(${sample} PRIVATE ${common_libraries}) install(TARGETS ${sample} RUNTIME DESTINATION bin - COMPONENT metavision-sdk-driver-bin + COMPONENT metavision-sdk-stream-bin ) install(FILES ${sample}.cpp - DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples ) install(FILES CMakeLists.txt.install RENAME CMakeLists.txt - DESTINATION share/metavision/sdk/driver/cpp_samples/${sample} - COMPONENT metavision-sdk-driver-samples + DESTINATION share/metavision/sdk/stream/cpp_samples/${sample} + COMPONENT metavision-sdk-stream-samples ) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt.install b/sdk/modules/stream/cpp/samples/metavision_viewer/CMakeLists.txt.install similarity index 81% rename from sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt.install rename to sdk/modules/stream/cpp/samples/metavision_viewer/CMakeLists.txt.install index e61089f8b..8e55e8a6a 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer/CMakeLists.txt.install +++ b/sdk/modules/stream/cpp/samples/metavision_viewer/CMakeLists.txt.install @@ -13,10 +13,10 @@ cmake_minimum_required(VERSION 3.5) set(CMAKE_CXX_STANDARD 17) -find_package(MetavisionSDK COMPONENTS core driver REQUIRED) +find_package(MetavisionSDK COMPONENTS core stream REQUIRED) find_package(Boost COMPONENTS program_options REQUIRED) find_package(OpenCV COMPONENTS highgui REQUIRED) add_executable(metavision_viewer metavision_viewer.cpp) -target_link_libraries(metavision_viewer PRIVATE MetavisionSDK::driver MetavisionSDK::core Boost::program_options ${OpenCV_LIBS}) +target_link_libraries(metavision_viewer PRIVATE MetavisionSDK::stream MetavisionSDK::core Boost::program_options ${OpenCV_LIBS}) diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer/metavision_viewer.cpp b/sdk/modules/stream/cpp/samples/metavision_viewer/metavision_viewer.cpp similarity index 89% rename from sdk/modules/driver/cpp/samples/metavision_viewer/metavision_viewer.cpp rename to sdk/modules/stream/cpp/samples/metavision_viewer/metavision_viewer.cpp index 7588e09eb..f6dd9fad7 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer/metavision_viewer.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_viewer/metavision_viewer.cpp @@ -9,7 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -// Example of using Metavision SDK Driver API for visualizing events stream, setting ROI and ERC as well as +// Example of using Metavision SDK Stream API for visualizing events stream, setting ROI and ERC as well as // saving and loading the camera settings to and from camera settings files #include @@ -23,12 +23,15 @@ #include #endif #include +#include +#include +#include #include #include #include #include -#include -#include +#include +#include #include static const int ESCAPE = 27; @@ -51,7 +54,7 @@ struct RoiControl { bool use_windows; // Whether to set ROIs through windows or lines std::vector cols; std::vector rows; - std::vector windows; + std::vector windows; Metavision::I_ROI::Mode mode; cv::Point mouse_down_coord; // Coordinates of initial pixel while left mouse button is held down bool need_refresh; // Whether ROIs need to be updated on the device @@ -145,7 +148,7 @@ int main(int argc, char *argv[]) { std::atomic do_retry = false; const std::string short_program_desc( - "Simple viewer to stream events from an event file or a device, using the SDK driver API.\n"); + "Simple viewer to stream events from an event file or a device, using the SDK Stream API.\n"); std::string long_program_desc(short_program_desc + "Define a region using the cursor (click and drag) to set a Region of Interest (ROI)\n" "Press SPACE key while running to record or stop recording raw data\n" @@ -242,7 +245,7 @@ int main(int argc, char *argv[]) { } if (biases_file != "") { - camera.biases().set_from_file(biases_file); + camera.get_facility().load_from_file(biases_file); } camera_is_opened = true; @@ -257,7 +260,7 @@ int main(int argc, char *argv[]) { } // With the HAL device corresponding to the camera object (file or live camera), we can try to get a facility - // This gives us access to extra HAL features not covered by the SDK Driver camera API + // This gives us access to extra HAL features not covered by the SDK Stream camera API try { auto *plugin_sw_info = camera.get_device().get_facility(); if (plugin_sw_info) { @@ -303,7 +306,7 @@ int main(int argc, char *argv[]) { // Setup CD frame generator std::mutex cd_frame_generator_mutex; - Metavision::CDFrameGenerator cd_frame_generator(geometry.width(), geometry.height()); + Metavision::CDFrameGenerator cd_frame_generator(geometry.get_width(), geometry.get_height()); cd_frame_generator.set_display_accumulation_time_us(10000); std::mutex cd_frame_mutex; @@ -318,9 +321,9 @@ int main(int argc, char *argv[]) { unsigned int max_roi_windows = 0; try { - max_roi_windows = camera.roi().get_facility()->get_max_supported_windows_count(); + max_roi_windows = camera.get_facility().get_max_supported_windows_count(); } catch (...) {} - RoiControl roi_ctrl(geometry.width(), geometry.height(), max_roi_windows); + RoiControl roi_ctrl(geometry.get_width(), geometry.get_height(), max_roi_windows); roi_ctrl.use_windows = true; if (roi.size() != 0) { roi_ctrl.need_refresh = true; @@ -331,8 +334,8 @@ int main(int argc, char *argv[]) { // Setup CD frame display std::string cd_window_name("CD Events"); - cv::namedWindow(cd_window_name, CV_GUI_EXPANDED); - cv::resizeWindow(cd_window_name, geometry.width(), geometry.height()); + cv::namedWindow(cd_window_name, CV_GUI_NORMAL); + cv::resizeWindow(cd_window_name, geometry.get_width(), geometry.get_height()); cv::moveWindow(cd_window_name, 0, 0); #if (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION * 100 + CV_SUBMINOR_VERSION) >= 408) || \ (CV_MAJOR_VERSION == 4 && (CV_MINOR_VERSION * 100 + CV_SUBMINOR_VERSION) >= 102) @@ -402,11 +405,13 @@ int main(int argc, char *argv[]) { if (roi_ctrl.need_refresh) { try { + auto &roi_facility = camera.get_facility(); if (roi_ctrl.use_windows) { - camera.roi().set(roi_ctrl.windows); + roi_facility.set_windows(roi_ctrl.windows); } else { - camera.roi().set(roi_ctrl.cols, roi_ctrl.rows); + roi_facility.set_lines(roi_ctrl.cols, roi_ctrl.rows); } + roi_facility.enable(true); } catch (...) {} roi_ctrl.need_refresh = false; } @@ -484,8 +489,8 @@ int main(int argc, char *argv[]) { } roi_ctrl.reset(); try { - if (camera.roi().get_facility()->is_enabled()) { - camera.roi().unset(); + if (camera.get_facility().is_enabled()) { + camera.get_facility().enable(false); } } catch (...) { MV_LOG_INFO() << "No ROI facility available"; @@ -501,32 +506,40 @@ int main(int argc, char *argv[]) { roi_ctrl.mode = Metavision::I_ROI::Mode::ROI; } - if (camera.roi().get_facility()->is_enabled()) { - camera.roi().unset(); + try { + auto &roi_facility = camera.get_facility(); + if (roi_facility.is_enabled()) { + roi_facility.enable(false); + } + roi_facility.set_mode(roi_ctrl.mode); + roi_ctrl.need_refresh = true; + } catch (...) { + MV_LOG_INFO() << "No ROI facility available"; } - camera.roi().get_facility()->set_mode(roi_ctrl.mode); - roi_ctrl.need_refresh = true; break; } case 'e': { try { - camera.erc_module().enable(!camera.erc_module().is_enabled()); - MV_LOG_INFO() << "ERC:" << (camera.erc_module().is_enabled() ? "enabled" : "disabled"); + auto &erc_module = camera.get_facility(); + erc_module.enable(!erc_module.is_enabled()); + MV_LOG_INFO() << "ERC:" << (erc_module.is_enabled() ? "enabled" : "disabled"); } catch (Metavision::CameraException &) {} break; } case '+': { try { - camera.erc_module().set_cd_event_rate(camera.erc_module().get_cd_event_rate() + 10000000); - MV_LOG_INFO() << "ERC:" << (camera.erc_module().get_cd_event_rate() / 1000000) << "Mev/s"; + auto &erc_module = camera.get_facility(); + erc_module.set_cd_event_rate(erc_module.get_cd_event_rate() + 10000000); + MV_LOG_INFO() << "ERC:" << (erc_module.get_cd_event_rate() / 1000000) << "Mev/s"; } catch (Metavision::CameraException &) {} break; } case '-': { try { - camera.erc_module().set_cd_event_rate(camera.erc_module().get_cd_event_rate() - 10000000); - MV_LOG_INFO() << "ERC:" << (camera.erc_module().get_cd_event_rate() / 1000000) << "Mev/s"; + auto &erc_module = camera.get_facility(); + erc_module.set_cd_event_rate(erc_module.get_cd_event_rate() - 10000000); + MV_LOG_INFO() << "ERC:" << (erc_module.get_cd_event_rate() / 1000000) << "Mev/s"; } catch (Metavision::CameraException &) {} break; } diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/.gitignore b/sdk/modules/stream/cpp/samples/metavision_viewer_android/.gitignore similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/.gitignore rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/.gitignore diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_viewer_android/CMakeLists.txt similarity index 94% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/CMakeLists.txt index 205a8bf50..b1dd00532 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/CMakeLists.txt @@ -16,5 +16,5 @@ execute_process( ${CMAKE_CURRENT_BINARY_DIR}/app/assets/gen4_evt3_hand.raw ) add_android_app(metavision_viewer_android - DEPENDS MetavisionSDK::driver hal_plugins + DEPENDS MetavisionSDK::stream hal_plugins ) \ No newline at end of file diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/build.gradle b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/build.gradle similarity index 90% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/build.gradle rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/build.gradle index 2fa8426b4..26ece5d13 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/build.gradle +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/build.gradle @@ -23,14 +23,20 @@ android { lintOptions { abortOnError false } - compileSdkVersion 30 + + compileSdk 33 + buildToolsVersion "32.0.0" + ndkVersion ndk_version + + namespace 'prophesee.metavision.viewer' + defaultConfig { applicationId "prophesee.metavision.viewer" - minSdkVersion 23 - targetSdkVersion 30 - ndkVersion ndk_version + minSdk 31 + targetSdk 33 versionCode 1 versionName "1.0" + testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' ndk.abiFilters ndk_abi externalNativeBuild { @@ -79,11 +85,10 @@ android { } dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.google.android.gms:play-services-gcm:15.0.1' testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } \ No newline at end of file diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/proguard-rules.pro b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/proguard-rules.pro similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/proguard-rules.pro rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/proguard-rules.pro diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/androidTest/java/com/prophesee/viewer/ExampleInstrumentedTest.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/androidTest/java/com/prophesee/viewer/ExampleInstrumentedTest.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/androidTest/java/com/prophesee/viewer/ExampleInstrumentedTest.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/androidTest/java/com/prophesee/viewer/ExampleInstrumentedTest.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/AndroidManifest.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/AndroidManifest.xml similarity index 91% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/AndroidManifest.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/AndroidManifest.xml index 4cf598618..70d23253d 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/AndroidManifest.xml +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + xmlns:tools="http://schemas.android.com/tools"> + @@ -11,12 +12,12 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> - + - - diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraFrameView.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraFrameView.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraFrameView.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraFrameView.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraThread.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraThread.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraThread.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/CameraThread.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/MainActivity.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/MainActivity.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/MainActivity.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/MainActivity.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/NativeHelper.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/NativeHelper.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/NativeHelper.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/NativeHelper.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/PreferenceActivity.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/PreferenceActivity.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/PreferenceActivity.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/PreferenceActivity.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/SettingsFragment.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/SettingsFragment.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/SettingsFragment.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/java/prophesee/metavision/viewer/SettingsFragment.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/layout-land/activity_main.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/layout-land/activity_main.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/layout-land/activity_main.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/layout-land/activity_main.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/layout-port/activity_main.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/layout-port/activity_main.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/layout-port/activity_main.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/layout-port/activity_main.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/layout/activity_main.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/layout/activity_main.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/layout/activity_main.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/layout/activity_main.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/menu/menu.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/menu/menu.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/menu/menu.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/menu/menu.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ico.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ico.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ico.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-hdpi/ico.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ico.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ico.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ico.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-mdpi/ico.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ico.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ico.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ico.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xhdpi/ico.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ico.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ico.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ico.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxhdpi/ico.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ico.png b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ico.png similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ico.png rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/mipmap-xxxhdpi/ico.png diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values-w820dp/dimens.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values-w820dp/dimens.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values-w820dp/dimens.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values-w820dp/dimens.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/attrs.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/attrs.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/attrs.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/attrs.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/colors.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/colors.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/colors.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/colors.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/dimens.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/dimens.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/dimens.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/dimens.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/strings.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/strings.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/strings.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/strings.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/styles.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/styles.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/values/styles.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/values/styles.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/xml/device_filter.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/xml/device_filter.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/xml/device_filter.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/xml/device_filter.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/xml/preferences.xml b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/xml/preferences.xml similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/main/res/xml/preferences.xml rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/main/res/xml/preferences.xml diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/test/java/com/prophesee/viewer/ExampleUnitTest.java b/sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/test/java/com/prophesee/viewer/ExampleUnitTest.java similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/app/src/test/java/com/prophesee/viewer/ExampleUnitTest.java rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/app/src/test/java/com/prophesee/viewer/ExampleUnitTest.java diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/build.gradle b/sdk/modules/stream/cpp/samples/metavision_viewer_android/build.gradle similarity index 72% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/build.gradle rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/build.gradle index dae28ab60..8f3890716 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/build.gradle +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/build.gradle @@ -1,30 +1,15 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id 'com.android.application' version '7.4.0' apply false + id 'com.android.library' version '7.4.0' apply false +} + ext.ndk_abi = local_props("ndk.abi") ext.ndk_version = local_props("ndk.version") ext.metavision_plugin_dir = local_props("metavision.plugin.dir") ext.build_dir = local_props("build.dir") project.buildDir = build_dir -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - google() - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - task clean(type: Delete) { delete rootProject.buildDir } diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/CMakeLists.txt similarity index 77% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/CMakeLists.txt index 24cdc769c..c0856589b 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/CMakeLists.txt +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/CMakeLists.txt @@ -15,16 +15,15 @@ set(ANDROID_PREBUILT_3RDPARTY_DIR ${METAVISION_BUILD_DIR}/generated/android/3rdp set(MetavisionHAL_DIR ${METAVISION_BUILD_DIR}/generated/share/cmake/MetavisionHALCMakePackagesFilesDir) set(MetavisionSDK_DIR ${METAVISION_BUILD_DIR}/generated/share/cmake/MetavisionSDKCMakePackagesFilesDir) -find_package(MetavisionSDK COMPONENTS driver REQUIRED) +find_package(MetavisionSDK COMPONENTS stream REQUIRED) -set (boost_components_to_find program_options filesystem timer chrono thread) +set (boost_components_to_find program_options timer chrono thread) find_package(Boost COMPONENTS ${boost_components_to_find} REQUIRED) -find_package(OpenCV COMPONENTS core highgui imgproc videoio imgcodecs calib3d objdetect REQUIRED) +find_package(OpenCV COMPONENTS core imgproc REQUIRED) set(metavision_viewer_src) add_subdirectory(src) add_library(metavision_viewer SHARED ${metavision_viewer_src}) -target_link_libraries(metavision_viewer MetavisionSDK::driver OpenCV::java Boost::program_options log android jnigraphics) - +target_link_libraries(metavision_viewer MetavisionSDK::stream opencv_core opencv_imgproc Boost::program_options log android jnigraphics) diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/src/CMakeLists.txt b/sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/src/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/src/CMakeLists.txt rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/src/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/src/native_helper.cpp b/sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/src/native_helper.cpp similarity index 96% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/src/native_helper.cpp rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/src/native_helper.cpp index 21cf849e1..2935df8cb 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/cpp/src/native_helper.cpp +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/cpp/src/native_helper.cpp @@ -23,7 +23,7 @@ #if CV_MAJOR_VERSION >= 4 #include #endif -#include +#include #include #include @@ -133,8 +133,8 @@ JNIEXPORT jintArray JNICALL Java_prophesee_metavision_viewer_NativeHelper_getCam jint *narr = env->GetIntArrayElements(newArray, NULL); if (camera_initialized) { auto &geometry = camera.geometry(); - narr[0] = geometry.width(); - narr[1] = geometry.height(); + narr[0] = geometry.get_width(); + narr[1] = geometry.get_height(); } env->ReleaseIntArrayElements(newArray, narr, 0); @@ -149,7 +149,7 @@ JNIEXPORT jboolean JNICALL Java_prophesee_metavision_viewer_NativeHelper_createC camera = Metavision::Camera::from_first_available(); cd_frame_generator.reset( - new Metavision::CDFrameGenerator(camera.geometry().width(), camera.geometry().height())); + new Metavision::CDFrameGenerator(camera.geometry().get_width(), camera.geometry().get_height())); camera.cd().add_callback([](const Metavision::EventCD *ev_begin, const Metavision::EventCD *ev_end) { cd_counter += std::distance(ev_begin, ev_end); @@ -175,7 +175,7 @@ JNIEXPORT jboolean JNICALL Java_prophesee_metavision_viewer_NativeHelper_createC camera = Metavision::Camera::from_file(std::string(raw_path_cstr)); cd_frame_generator.reset( - new Metavision::CDFrameGenerator(camera.geometry().width(), camera.geometry().height())); + new Metavision::CDFrameGenerator(camera.geometry().get_width(), camera.geometry().get_height())); camera.cd().add_callback([](const Metavision::EventCD *ev_begin, const Metavision::EventCD *ev_end) { cd_counter += std::distance(ev_begin, ev_end); diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle.properties b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle.properties similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle.properties rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle.properties diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.jar b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.jar similarity index 59% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.jar rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.jar index e708b1c02..249e5832f 100644 Binary files a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.jar and b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.properties b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.properties similarity index 92% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.properties rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.properties index 4d9ca1649..8049c684f 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.properties +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradlew b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradlew new file mode 100755 index 000000000..a69d9cb6c --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradlew @@ -0,0 +1,240 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradlew.bat b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradlew.bat similarity index 87% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/gradlew.bat rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/gradlew.bat index ac1b06f93..53a6b238d 100644 --- a/sdk/modules/driver/cpp/samples/metavision_viewer_android/gradlew.bat +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/local.properties.in b/sdk/modules/stream/cpp/samples/metavision_viewer_android/local.properties.in similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/local.properties.in rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/local.properties.in diff --git a/sdk/modules/driver/cpp/samples/metavision_viewer_android/prophesee.jks b/sdk/modules/stream/cpp/samples/metavision_viewer_android/prophesee.jks similarity index 100% rename from sdk/modules/driver/cpp/samples/metavision_viewer_android/prophesee.jks rename to sdk/modules/stream/cpp/samples/metavision_viewer_android/prophesee.jks diff --git a/sdk/modules/stream/cpp/samples/metavision_viewer_android/settings.gradle b/sdk/modules/stream/cpp/samples/metavision_viewer_android/settings.gradle new file mode 100644 index 000000000..b87d5ffaf --- /dev/null +++ b/sdk/modules/stream/cpp/samples/metavision_viewer_android/settings.gradle @@ -0,0 +1,15 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} +include ':app' diff --git a/sdk/modules/driver/cpp/src/CMakeLists.txt b/sdk/modules/stream/cpp/src/CMakeLists.txt similarity index 80% rename from sdk/modules/driver/cpp/src/CMakeLists.txt rename to sdk/modules/stream/cpp/src/CMakeLists.txt index 3bb6a6c79..b9101a77b 100644 --- a/sdk/modules/driver/cpp/src/CMakeLists.txt +++ b/sdk/modules/stream/cpp/src/CMakeLists.txt @@ -7,34 +7,29 @@ # 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. -target_sources(metavision_sdk_driver PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/antiflicker_module.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/biases.cpp +target_sources(metavision_sdk_stream PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/camera_exception.cpp ${CMAKE_CURRENT_SOURCE_DIR}/camera_generation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/camera.cpp ${CMAKE_CURRENT_SOURCE_DIR}/camera_live.cpp ${CMAKE_CURRENT_SOURCE_DIR}/camera_offline_raw.cpp ${CMAKE_CURRENT_SOURCE_DIR}/camera_offline_generic.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/camera_stream_slicer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cd.cpp ${CMAKE_CURRENT_SOURCE_DIR}/dat_event_file_reader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/erc_counter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/erc_module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/event_file_reader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/event_file_writer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ext_trigger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/frame_diff.cpp ${CMAKE_CURRENT_SOURCE_DIR}/frame_histo.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/geometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hdf5_event_file_reader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hdf5_event_file_writer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/offline_streaming_control.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/event_trail_filter_module.cpp ${CMAKE_CURRENT_SOURCE_DIR}/raw_data.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/raw_event_file_logger.cpp ${CMAKE_CURRENT_SOURCE_DIR}/raw_event_file_reader.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/raw_event_file_writer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/roi.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/trigger_out.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/raw_evt2_event_file_writer.cpp ) add_subdirectory(protobuf) diff --git a/sdk/modules/driver/cpp/src/camera.cpp b/sdk/modules/stream/cpp/src/camera.cpp similarity index 85% rename from sdk/modules/driver/cpp/src/camera.cpp rename to sdk/modules/stream/cpp/src/camera.cpp index 871be915f..f13be739b 100644 --- a/sdk/modules/driver/cpp/src/camera.cpp +++ b/sdk/modules/stream/cpp/src/camera.cpp @@ -9,18 +9,17 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include - #include "metavision/hal/device/device_discovery.h" +#include "metavision/hal/facilities/i_geometry.h" #include "metavision/hal/utils/hal_connection_exception.h" -#include "metavision/sdk/driver/internal/camera_internal.h" -#include "metavision/sdk/driver/internal/camera_live_internal.h" -#include "metavision/sdk/driver/internal/camera_offline_generic_internal.h" -#include "metavision/sdk/driver/internal/camera_offline_raw_internal.h" -#include "metavision/sdk/driver/internal/camera_error_code_internal.h" -#include "metavision/sdk/driver/camera_exception.h" -#include "metavision/sdk/driver/raw_event_file_writer.h" -#include "metavision/sdk/driver/hdf5_event_file_writer.h" +#include "metavision/sdk/stream/internal/camera_internal.h" +#include "metavision/sdk/stream/internal/camera_live_internal.h" +#include "metavision/sdk/stream/internal/camera_offline_generic_internal.h" +#include "metavision/sdk/stream/internal/camera_offline_raw_internal.h" +#include "metavision/sdk/stream/internal/camera_error_code_internal.h" +#include "metavision/sdk/stream/camera_exception.h" +#include "metavision/sdk/stream/raw_event_file_logger.h" +#include "metavision/sdk/stream/hdf5_event_file_writer.h" namespace Metavision { @@ -152,7 +151,7 @@ bool Camera::Private::stop() { return true; } -bool Camera::Private::start_recording(const std::string &file_path) { +bool Camera::Private::start_recording(const std::filesystem::path &file_path) { check_initialization(); stop_recording(file_path); @@ -161,11 +160,11 @@ bool Camera::Private::start_recording(const std::string &file_path) { bool ret = false; try { ret = start_recording_impl(file_path); - } catch (CameraException &e) { + } catch (const CameraException &) { throw; } catch (...) { throw CameraException(CameraErrorCode::CouldNotOpenFile, - "Could not open file '" + file_path + + "Could not open file '" + file_path.string() + "' to record. Make sure it is a valid filename and that you have " "permissions to write it."); } @@ -174,7 +173,7 @@ bool Camera::Private::start_recording(const std::string &file_path) { return ret; } -bool Camera::Private::stop_recording(const std::string &file_path) { +bool Camera::Private::stop_recording(const std::filesystem::path &file_path) { check_initialization(); bool ret = true; @@ -188,12 +187,20 @@ bool Camera::Private::stop_recording(const std::string &file_path) { return ret; } -const Geometry &Camera::Private::geometry() const { - check_initialization(); - if (!geometry_) { - throw CameraException(InternalInitializationErrors::IGeometryNotFound); - }; - return *geometry_; +I_Geometry &Camera::Private::get_geometry() { + try { + auto geom = device().get_facility(); + if (geom) { + return *geom; + } + } catch (const CameraException &e) { + if (e.code().value() != UnsupportedFeatureErrors::DeviceUnavailable) { + throw; + } + } + // Shouldn't reach here + throw CameraException(CameraErrorCode::UnsupportedFeature, + std::string("Unavailable facility ") + typeid(I_Geometry).name()); } const CameraGeneration &Camera::Private::generation() const { @@ -257,30 +264,6 @@ OfflineStreamingControl &Camera::Private::offline_streaming_control() { throw CameraException(CameraErrorCode::CameraNotInitialized); } -Roi &Camera::Private::roi() { - throw CameraException(CameraErrorCode::CameraNotInitialized); -} - -Biases &Camera::Private::biases() { - throw CameraException(CameraErrorCode::CameraNotInitialized); -} - -AntiFlickerModule &Camera::Private::antiflicker_module() { - throw CameraException(CameraErrorCode::CameraNotInitialized); -} - -ErcModule &Camera::Private::erc_module() { - throw CameraException(CameraErrorCode::CameraNotInitialized); -} - -EventTrailFilterModule &Camera::Private::event_trail_filter_module() { - throw CameraException(CameraErrorCode::CameraNotInitialized); -} - -TriggerOut &Camera::Private::trigger_out() { - throw CameraException(CameraErrorCode::CameraNotInitialized); -} - timestamp Camera::Private::get_last_timestamp() const { throw CameraException(CameraErrorCode::CameraNotInitialized); } @@ -297,16 +280,16 @@ bool Camera::Private::process_impl() { throw CameraException(CameraErrorCode::CameraNotInitialized); } -bool Camera::Private::start_recording_impl(const std::string &file_path) { - std::string ext = boost::filesystem::extension(file_path); +bool Camera::Private::start_recording_impl(const std::filesystem::path &file_path) { + std::string ext = file_path.extension().string(); std::shared_ptr writer; if (ext == ".raw") { - writer = std::make_shared(file_path); + writer = std::make_shared(file_path); } else if (ext == ".hdf5") { writer = std::make_shared(file_path); } else { throw CameraException(CameraErrorCode::WrongExtension, - "Unsupported extension for the recording destination " + file_path + "."); + "Unsupported extension for the recording destination " + file_path.string() + "."); } writer->add_metadata_map_from_camera(*pub_ptr_); if (ext == ".raw") { @@ -314,14 +297,15 @@ bool Camera::Private::start_recording_impl(const std::string &file_path) { throw CameraException(UnsupportedFeatureErrors::RawRecordingUnavailable, "Cannot record to a RAW file from this type of camera."); } - recording_cb_ids_.emplace(file_path, raw_data_->add_callback([writer](const std::uint8_t *ptr, size_t size) { - auto *raw_writer = static_cast(writer.get()); + recording_cb_ids_.emplace(file_path.string(), + raw_data_->add_callback([writer](const std::uint8_t *ptr, size_t size) { + auto *raw_writer = static_cast(writer.get()); raw_writer->add_raw_data(ptr, size); })); } else { auto timeshift_added = std::make_shared(false); recording_cb_ids_.emplace( - file_path, cd_->add_callback([timeshift_added, writer](const EventCD *begin, const EventCD *end) { + file_path.string(), cd_->add_callback([timeshift_added, writer](const EventCD *begin, const EventCD *end) { if (!*timeshift_added) { writer->add_metadata("time_shift", std::to_string(begin->t)); *timeshift_added = true; @@ -329,7 +313,7 @@ bool Camera::Private::start_recording_impl(const std::string &file_path) { writer->add_events(begin, end); })); if (ext_trigger_) { - recording_cb_ids_.emplace(file_path, ext_trigger_->add_callback([writer](auto begin, auto end) { + recording_cb_ids_.emplace(file_path.string(), ext_trigger_->add_callback([writer](auto begin, auto end) { writer->add_events(begin, end); })); } @@ -346,8 +330,8 @@ bool Camera::Private::start_recording_impl(const std::string &file_path) { return true; } -bool Camera::Private::stop_recording_impl(const std::string &file_path) { - auto range = recording_cb_ids_.equal_range(file_path); +bool Camera::Private::stop_recording_impl(const std::filesystem::path &file_path) { + auto range = recording_cb_ids_.equal_range(file_path.string()); if (range.first != range.second) { for (auto it = range.first; it != range.second; ++it) { // only one of those calls will succeed, we don't care which one @@ -569,30 +553,30 @@ Camera Camera::from_serial(const std::string &serial, const DeviceConfig &config } } -Camera Camera::from_file(const std::string &file_path, const FileConfigHints &hints) { - if (boost::filesystem::extension(file_path) != "") { - if (!boost::filesystem::exists(file_path)) { +Camera Camera::from_file(const std::filesystem::path &file_path, const FileConfigHints &hints) { + if (file_path.has_extension()) { + if (!std::filesystem::exists(file_path)) { throw CameraException(CameraErrorCode::FileDoesNotExist, - "Opening file at " + file_path + ": not an existing file."); + "Opening file at " + file_path.string() + ": not an existing file."); } - if (!boost::filesystem::is_regular_file(file_path)) { + if (!std::filesystem::is_regular_file(file_path)) { throw CameraException(CameraErrorCode::NotARegularFile); } } - if (boost::filesystem::extension(file_path) == ".raw") { + if (file_path.extension().string() == ".raw") { return Camera(new detail::OfflineRawPrivate(file_path, hints)); - } else if (boost::filesystem::extension(file_path) == ".hdf5") { + } else if (file_path.extension().string() == ".hdf5" || file_path.extension().string() == ".h5") { #if defined HAS_HDF5 return Camera(new detail::OfflineGenericPrivate(file_path, hints)); #endif - } else if (boost::filesystem::extension(file_path) == ".dat" || boost::filesystem::extension(file_path) == "") { + } else if (file_path.extension().string() == ".dat" || !file_path.has_extension()) { return Camera(new detail::OfflineGenericPrivate(file_path, hints)); } throw CameraException(CameraErrorCode::WrongExtension, - "Unsupported extension for the provided input file " + file_path + "."); + "Unsupported extension for the provided input file " + file_path.string() + "."); } RawData &Camera::raw_data() { @@ -611,14 +595,6 @@ ERCCounter &Camera::erc_counter() { return pimpl_->erc_counter(); } -AntiFlickerModule &Camera::antiflicker_module() { - return pimpl_->antiflicker_module(); -} - -ErcModule &Camera::erc_module() { - return pimpl_->erc_module(); -} - FrameHisto &Camera::frame_histo() { return pimpl_->frame_histo(); } @@ -627,18 +603,6 @@ FrameDiff &Camera::frame_diff() { return pimpl_->frame_diff(); } -EventTrailFilterModule &Camera::event_trail_filter_module() { - return pimpl_->event_trail_filter_module(); -} - -TriggerOut &Camera::trigger_out() { - return pimpl_->trigger_out(); -} - -Roi &Camera::roi() { - return pimpl_->roi(); -} - CallbackId Camera::add_runtime_error_callback(RuntimeErrorCallback error_callback) { return pimpl_->add_runtime_error_callback(error_callback); } @@ -655,16 +619,22 @@ bool Camera::remove_status_change_callback(CallbackId callback_id) { return pimpl_->remove_status_change_callback(callback_id); } -Biases &Camera::biases() { - return pimpl_->biases(); -} - OfflineStreamingControl &Camera::offline_streaming_control() { return pimpl_->offline_streaming_control(); } -const Geometry &Camera::geometry() const { - return pimpl_->geometry(); +template<> +I_Geometry &Camera::get_facility() { + return pimpl_->get_geometry(); +} + +template<> +const I_Geometry &Camera::get_facility() const { + return pimpl_->get_geometry(); +} + +const I_Geometry &Camera::geometry() const { + return get_facility(); } const CameraGeneration &Camera::generation() const { @@ -691,11 +661,11 @@ bool Camera::stop() { } } -bool Camera::start_recording(const std::string &file_path) { +bool Camera::start_recording(const std::filesystem::path &file_path) { return pimpl_->start_recording(file_path); } -bool Camera::stop_recording(const std::string &file_path) { +bool Camera::stop_recording(const std::filesystem::path &file_path) { return pimpl_->stop_recording(file_path); } @@ -711,11 +681,11 @@ Metavision::timestamp Camera::get_last_timestamp() const { return pimpl_->get_last_timestamp(); } -bool Camera::save(const std::string &path) const { +bool Camera::save(const std::filesystem::path &path) const { std::ofstream ofs(path); if (!ofs.is_open()) { throw CameraException(CameraErrorCode::CouldNotOpenFile, - "Could not open file '" + path + + "Could not open file '" + path.string() + "' to save camera settings to. Make sure it is a valid filename and that you have " "permissions to write it."); } @@ -724,11 +694,11 @@ bool Camera::save(const std::string &path) const { return ofs.good(); } -bool Camera::load(const std::string &path) { +bool Camera::load(const std::filesystem::path &path) { std::ifstream ifs(path); if (!ifs.is_open()) { throw CameraException(CameraErrorCode::CouldNotOpenFile, - "Could not open file '" + path + + "Could not open file '" + path.string() + "' to load camera settings from. Make sure it is a valid filename and that you have " "permissions to read it."); } diff --git a/sdk/modules/driver/cpp/src/camera_exception.cpp b/sdk/modules/stream/cpp/src/camera_exception.cpp similarity index 81% rename from sdk/modules/driver/cpp/src/camera_exception.cpp rename to sdk/modules/stream/cpp/src/camera_exception.cpp index c4b709edb..a3eb72bab 100644 --- a/sdk/modules/driver/cpp/src/camera_exception.cpp +++ b/sdk/modules/stream/cpp/src/camera_exception.cpp @@ -13,9 +13,9 @@ #include #include "metavision/sdk/base/utils/error_code.h" -#include "metavision/sdk/driver/camera_error_code.h" -#include "metavision/sdk/driver/internal/camera_error_code_internal.h" -#include "metavision/sdk/driver/camera_exception.h" +#include "metavision/sdk/stream/camera_error_code.h" +#include "metavision/sdk/stream/internal/camera_error_code_internal.h" +#include "metavision/sdk/stream/camera_exception.h" namespace Metavision { @@ -39,22 +39,6 @@ std::string get_error_message(CameraErrorCodeType error_code) { msg_to_ret = "Camera runtime error."; break; - case CameraErrorCode::BiasesError: - msg_to_ret = "Could not set given biases."; - break; - - case BiasesErrors::UnsupportedBias: - msg_to_ret = "Could not set bias."; - break; - - case BiasesErrors::UnsupportedBiasFile: - msg_to_ret = "Could not set biases from file."; - break; - - case CameraErrorCode::RoiError: - msg_to_ret = "Could not set given ROI on the sensor."; - break; - case CameraErrorCode::FirmwareIsNotUpToDate: msg_to_ret = "Device's firmware do not support the requested feature. Update it to solve this issue."; break; @@ -97,27 +81,19 @@ std::string get_error_message(CameraErrorCodeType error_code) { // internal errors case CameraErrorCode::InternalInitializationError: - case InternalInitializationErrors::ILLBiasesNotFound: case InternalInitializationErrors::IEventsStreamNotFound: case InternalInitializationErrors::IDeviceControlNotFound: case InternalInitializationErrors::IDecoderNotFound: case InternalInitializationErrors::ICDDecoderNotFound: case InternalInitializationErrors::IGeometryNotFound: case InternalInitializationErrors::IBoardIdentificationNotFound: - case InternalInitializationErrors::IRoiNotFound: case InternalInitializationErrors::UnknownSystemId: case InternalInitializationErrors::InvalidFPGAState: msg_to_ret = "Error while initializing the camera."; break; case CameraErrorCode::UnsupportedFeature: - case UnsupportedFeatureErrors::RoiUnavailable: - case UnsupportedFeatureErrors::BiasesUnavailable: - case UnsupportedFeatureErrors::TriggerOutUnavailable: case UnsupportedFeatureErrors::ExtTriggerUnavailable: - case UnsupportedFeatureErrors::AntiFlickerModuleUnavailable: - case UnsupportedFeatureErrors::ErcModuleUnavailable: - case UnsupportedFeatureErrors::EventTrailFilterModuleUnavailable: msg_to_ret = "Unsupported feature of the camera."; break; @@ -140,7 +116,7 @@ class CameraErrorCategory : public std::error_category { CameraErrorCategory(const CameraErrorCategory &) = delete; virtual const char *name() const noexcept override { - return "Metavision SDK Driver exception"; + return "Metavision SDK Stream exception"; } virtual std::string message(int err) const override { diff --git a/sdk/modules/driver/cpp/src/camera_generation.cpp b/sdk/modules/stream/cpp/src/camera_generation.cpp similarity index 83% rename from sdk/modules/driver/cpp/src/camera_generation.cpp rename to sdk/modules/stream/cpp/src/camera_generation.cpp index b621cdccd..5fed4f586 100644 --- a/sdk/modules/driver/cpp/src/camera_generation.cpp +++ b/sdk/modules/stream/cpp/src/camera_generation.cpp @@ -11,26 +11,32 @@ #include "metavision/hal/device/device.h" #include "metavision/hal/facilities/i_hw_identification.h" -#include "metavision/sdk/driver/camera_generation.h" -#include "metavision/sdk/driver/camera_error_code.h" -#include "metavision/sdk/driver/camera_exception.h" -#include "metavision/sdk/driver/internal/camera_generation_internal.h" +#include "metavision/sdk/stream/camera_generation.h" +#include "metavision/sdk/stream/camera_error_code.h" +#include "metavision/sdk/stream/camera_exception.h" +#include "metavision/sdk/stream/internal/camera_generation_internal.h" namespace Metavision { -CameraGeneration::Private::Private(short version_major, short version_minor) : - major_(version_major), minor_(version_minor) {} +CameraGeneration::Private::Private(const std::string &name) : name_(name) {} + +CameraGeneration::Private::Private(short version_major, short version_minor, const std::string &name) : + major_(version_major), minor_(version_minor), name_(name) {} CameraGeneration::Private::~Private() {} -CameraGeneration *CameraGeneration::Private::build(short version_major, short version_minor) { - return new CameraGeneration(new Private(version_major, version_minor)); +CameraGeneration *CameraGeneration::Private::build(const std::string &name) { + return new CameraGeneration(new Private(name)); +} + +CameraGeneration *CameraGeneration::Private::build(short version_major, short version_minor, const std::string &name) { + return new CameraGeneration(new Private(version_major, version_minor, name)); } CameraGeneration *CameraGeneration::Private::build(Device &device) { auto *hw_id = device.get_facility(); const auto &sensor_info = hw_id->get_sensor_info(); - return CameraGeneration::Private::build(sensor_info.major_version_, sensor_info.minor_version_); + return CameraGeneration::Private::build(sensor_info.major_version_, sensor_info.minor_version_, sensor_info.name_); } CameraGeneration::~CameraGeneration() {} @@ -45,6 +51,10 @@ short CameraGeneration::version_minor() const { return pimpl_->minor_; } +std::string CameraGeneration::name() const { + return pimpl_->name_; +} + CameraGeneration::Private &CameraGeneration::get_pimpl() { return *pimpl_; } diff --git a/sdk/modules/driver/cpp/src/camera_live.cpp b/sdk/modules/stream/cpp/src/camera_live.cpp similarity index 75% rename from sdk/modules/driver/cpp/src/camera_live.cpp rename to sdk/modules/stream/cpp/src/camera_live.cpp index ad81a75a1..b7895692e 100644 --- a/sdk/modules/driver/cpp/src/camera_live.cpp +++ b/sdk/modules/stream/cpp/src/camera_live.cpp @@ -9,8 +9,6 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include - #include "metavision/hal/device/device_discovery.h" #include "metavision/hal/facilities/i_camera_synchronization.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" @@ -18,19 +16,20 @@ #include "metavision/hal/facilities/i_event_decoder.h" #include "metavision/hal/facilities/i_event_frame_decoder.h" #include "metavision/hal/facilities/i_hw_identification.h" +#include "metavision/hal/facilities/i_ll_biases.h" #include "metavision/hal/facilities/i_plugin_software_info.h" #include "metavision/sdk/base/events/event_pointcloud.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" -#include "metavision/sdk/driver/internal/camera_error_code_internal.h" -#include "metavision/sdk/driver/internal/camera_generation_internal.h" -#include "metavision/sdk/driver/internal/camera_live_internal.h" -#include "metavision/sdk/driver/internal/camera_serialization.h" -#include "metavision/sdk/driver/internal/cd_internal.h" -#include "metavision/sdk/driver/internal/ext_trigger_internal.h" -#include "metavision/sdk/driver/internal/erc_counter_internal.h" -#include "metavision/sdk/driver/internal/frame_diff_internal.h" -#include "metavision/sdk/driver/internal/frame_histo_internal.h" -#include "metavision/sdk/driver/internal/raw_data_internal.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/camera_error_code_internal.h" +#include "metavision/sdk/stream/internal/camera_generation_internal.h" +#include "metavision/sdk/stream/internal/camera_live_internal.h" +#include "metavision/sdk/stream/internal/camera_serialization.h" +#include "metavision/sdk/stream/internal/cd_internal.h" +#include "metavision/sdk/stream/internal/ext_trigger_internal.h" +#include "metavision/sdk/stream/internal/erc_counter_internal.h" +#include "metavision/sdk/stream/internal/frame_diff_internal.h" +#include "metavision/sdk/stream/internal/frame_histo_internal.h" +#include "metavision/sdk/stream/internal/raw_data_internal.h" namespace Metavision { namespace detail { @@ -95,49 +94,6 @@ OfflineStreamingControl &LivePrivate::offline_streaming_control() { "Cannot get offline streaming control from a live camera."); } -TriggerOut &LivePrivate::trigger_out() { - if (!trigger_out_) { - throw CameraException(UnsupportedFeatureErrors::TriggerOutUnavailable); - } - return *trigger_out_; -} - -Biases &LivePrivate::biases() { - if (!biases_) { - throw CameraException(InternalInitializationErrors::ILLBiasesNotFound); - } - - return *biases_; -} - -Roi &LivePrivate::roi() { - if (!roi_) { - throw CameraException(InternalInitializationErrors::IRoiNotFound); - } - return *roi_; -} - -AntiFlickerModule &LivePrivate::antiflicker_module() { - if (!afk_) { - throw CameraException(UnsupportedFeatureErrors::AntiFlickerModuleUnavailable); - } - return *afk_; -} - -ErcModule &LivePrivate::erc_module() { - if (!ercm_) { - throw CameraException(UnsupportedFeatureErrors::ErcModuleUnavailable); - } - return *ercm_; -} - -EventTrailFilterModule &LivePrivate::event_trail_filter_module() { - if (!event_trail_filter_) { - throw CameraException(UnsupportedFeatureErrors::EventTrailFilterModuleUnavailable); - } - return *event_trail_filter_; -} - timestamp LivePrivate::get_last_timestamp() const { if (index_manager_.counter_map_.tag_count(CallbackTagIds::DECODE_CALLBACK_TAG_ID) > 0) { if (i_events_stream_decoder_) { @@ -191,24 +147,25 @@ bool LivePrivate::process_impl(TimingProfilerType *profiler) { const bool has_decode_callbacks = index_manager_.counter_map_.tag_count(CallbackTagIds::DECODE_CALLBACK_TAG_ID); // Pointcloud is not handled by Camera object. Always do decoding for pointclouds. if (has_decode_callbacks || device_->get_facility>()) { - i_decoder_->decode(ev_buffer->data(), ev_buffer->data() + ev_buffer->size()); - t.setNumProcessedElements(ev_buffer->size() / i_decoder_->get_raw_event_size_bytes()); + i_decoder_->decode(ev_buffer.data(), ev_buffer.end()); + t.setNumProcessedElements(ev_buffer.size() / i_decoder_->get_raw_event_size_bytes()); } // ... then we call the raw buffer callback so that a user has access to some info (e.g last // decoded timestamp) when the raw callback is called for (auto &cb : raw_data_->get_pimpl().get_cbs()) { - cb(ev_buffer->data(), ev_buffer->size()); + cb(ev_buffer.data(), ev_buffer.size()); } } return true; } -bool LivePrivate::start_recording_impl(const std::string &file_path) { - std::string base_path = boost::filesystem::change_extension(file_path, "").string(); - if (biases_) { - biases_->save_to_file(base_path + ".bias"); +bool LivePrivate::start_recording_impl(const std::filesystem::path &file_path) { + auto *biases = device_->get_facility(); + if (biases) { + std::filesystem::path base_path = file_path; + biases->save_to_file(base_path.replace_extension(".bias")); } return Camera::Private::start_recording_impl(file_path); } @@ -232,7 +189,6 @@ void LivePrivate::init() { throw(CameraException(InternalInitializationErrors::IBoardIdentificationNotFound)); } camera_configuration_.data_encoding_format = hw_identification->get_current_data_encoding_format(); - camera_configuration_.system_ID = std::to_string(hw_identification->get_system_id()); camera_configuration_.serial_number = hw_identification->get_serial(); camera_configuration_.integrator = hw_identification->get_integrator(); camera_configuration_.firmware_version = hw_identification->get_system_info()["System Version"]; @@ -247,12 +203,6 @@ void LivePrivate::init() { throw CameraException(InternalInitializationErrors::IEventsStreamNotFound); } - I_Geometry *i_geometry = device_->get_facility(); - if (!i_geometry) { - throw CameraException(InternalInitializationErrors::IGeometryNotFound); - } - geometry_.reset(new Geometry(i_geometry)); - i_decoder_ = device_->get_facility(); i_events_stream_decoder_ = device_->get_facility(); @@ -324,38 +274,6 @@ void LivePrivate::init() { if (!i_camera_synchronization_) { throw CameraException(InternalInitializationErrors::IDeviceControlNotFound); } - - I_ROI *i_roi = device_->get_facility(); - if (i_roi) { - roi_.reset(new Roi(i_roi)); - } - - I_TriggerOut *i_trigger_out = device_->get_facility(); - if (i_trigger_out) { - trigger_out_.reset(new TriggerOut(i_trigger_out)); - } - - // all ext trigger enabled by default - - I_LL_Biases *i_ll_biases = device_->get_facility(); - if (i_ll_biases) { - biases_.reset(new Biases(i_ll_biases)); - } - - I_AntiFlickerModule *i_afk = device_->get_facility(); - if (i_afk) { - afk_.reset(new AntiFlickerModule(i_afk)); - } - - I_ErcModule *i_ercm = device_->get_facility(); - if (i_ercm) { - ercm_.reset(new ErcModule(i_ercm)); - } - - I_EventTrailFilterModule *i_event_trail_filter = device_->get_facility(); - if (i_event_trail_filter) { - event_trail_filter_.reset(new EventTrailFilterModule(i_event_trail_filter)); - } } } // namespace detail diff --git a/sdk/modules/driver/cpp/src/camera_offline_generic.cpp b/sdk/modules/stream/cpp/src/camera_offline_generic.cpp similarity index 73% rename from sdk/modules/driver/cpp/src/camera_offline_generic.cpp rename to sdk/modules/stream/cpp/src/camera_offline_generic.cpp index b69f52bf5..e61b1b523 100644 --- a/sdk/modules/driver/cpp/src/camera_offline_generic.cpp +++ b/sdk/modules/stream/cpp/src/camera_offline_generic.cpp @@ -11,19 +11,18 @@ #include -#include - #include "metavision/sdk/base/utils/get_time.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" -#include "metavision/sdk/driver/internal/camera_error_code_internal.h" -#include "metavision/sdk/driver/internal/camera_generation_internal.h" -#include "metavision/sdk/driver/internal/camera_offline_generic_internal.h" -#include "metavision/sdk/driver/internal/cd_internal.h" -#include "metavision/sdk/driver/internal/erc_counter_internal.h" -#include "metavision/sdk/driver/internal/ext_trigger_internal.h" -#include "metavision/sdk/driver/internal/offline_streaming_control_internal.h" -#include "metavision/sdk/driver/dat_event_file_reader.h" -#include "metavision/sdk/driver/hdf5_event_file_reader.h" +#include "metavision/hal/facilities/i_geometry.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/camera_error_code_internal.h" +#include "metavision/sdk/stream/internal/camera_generation_internal.h" +#include "metavision/sdk/stream/internal/camera_offline_generic_internal.h" +#include "metavision/sdk/stream/internal/cd_internal.h" +#include "metavision/sdk/stream/internal/erc_counter_internal.h" +#include "metavision/sdk/stream/internal/ext_trigger_internal.h" +#include "metavision/sdk/stream/internal/offline_streaming_control_internal.h" +#include "metavision/sdk/stream/dat_event_file_reader.h" +#include "metavision/sdk/stream/hdf5_event_file_reader.h" namespace Metavision { namespace detail { @@ -39,11 +38,11 @@ struct GenericGeometry : public I_Geometry { int width_, height_; }; -OfflineGenericPrivate::OfflineGenericPrivate(const std::string &file_path, const FileConfigHints &hints) : +OfflineGenericPrivate::OfflineGenericPrivate(const std::filesystem::path &file_path, const FileConfigHints &hints) : Private(detail::Config()) { // clang-format off try { - if (boost::filesystem::extension(file_path) == ".hdf5") { + if (file_path.extension().string() == ".hdf5" || file_path.extension().string() == ".h5") { file_reader_ = std::make_unique(file_path, hints.time_shift()); } else { file_reader_ = std::make_unique(file_path); @@ -74,39 +73,14 @@ OfflineStreamingControl &OfflineGenericPrivate::offline_streaming_control() { return *osc_; } -TriggerOut &OfflineGenericPrivate::trigger_out() { - throw CameraException(UnsupportedFeatureErrors::TriggerOutUnavailable, - "Cannot get trigger out instance when running from a file."); -} - -Biases &OfflineGenericPrivate::biases() { - throw CameraException(UnsupportedFeatureErrors::BiasesUnavailable, "Cannot get biases from a file."); -} - -Roi &OfflineGenericPrivate::roi() { - throw CameraException(UnsupportedFeatureErrors::RoiUnavailable, - "Cannot get roi instance when running from a file."); -} - -AntiFlickerModule &OfflineGenericPrivate::antiflicker_module() { - throw CameraException(UnsupportedFeatureErrors::AntiFlickerModuleUnavailable, - "Cannot get anti-flicker instance when running from a file."); -} - -ErcModule &OfflineGenericPrivate::erc_module() { - throw CameraException(UnsupportedFeatureErrors::ErcModuleUnavailable, - "Cannot get erc instance when running from a file."); -} - -EventTrailFilterModule &OfflineGenericPrivate::event_trail_filter_module() { - throw CameraException(UnsupportedFeatureErrors::EventTrailFilterModuleUnavailable, - "Cannot get event trail filter instance when running from a file."); -} - timestamp OfflineGenericPrivate::get_last_timestamp() const { return last_ts_; } +I_Geometry &OfflineGenericPrivate::get_geometry() { + return *gen_geom_; +} + void OfflineGenericPrivate::start_impl() { first_ts_ = last_ts_ = -1; first_ts_clock_ = 0; @@ -153,6 +127,17 @@ bool OfflineGenericPrivate::process_impl(TimingProfilerType *profiler) { return true; } +std::string versions_to_name(int version_major, int version_minor) { + static const std::map, std::string> m{ + {{3, 0}, "Gen3.0"}, {{3, 1}, "Gen3.1"}, {{4, 0}, "Gen4.0"}, {{4, 1}, "Gen4.1"}, {{4, 2}, "IMX636"}, + }; + auto it = m.find(std::make_pair(version_major, version_minor)); + if (it != m.end()) { + return it->second; + } + return std::string(); +} + void OfflineGenericPrivate::save(std::ostream &) const { throw CameraException(UnsupportedFeatureErrors::SerializationUnsupported, "Cannot serialize when running from a file."); @@ -172,10 +157,6 @@ void OfflineGenericPrivate::init() { if (it != metadata_map_.end()) { camera_configuration_.serial_number = it->second; } - it = metadata_map_.find("system_ID"); - if (it != metadata_map_.end()) { - camera_configuration_.system_ID = it->second; - } it = metadata_map_.find("integrator_name"); if (it != metadata_map_.end()) { camera_configuration_.integrator = it->second; @@ -193,7 +174,6 @@ void OfflineGenericPrivate::init() { std::smatch match; if (std::regex_search(g.begin(), g.end(), match, rgx)) { gen_geom_.reset(new GenericGeometry(std::stoi(match.str(1)), std::stoi(match.str(2)))); - geometry_.reset(new Geometry(gen_geom_.get())); } } @@ -230,7 +210,10 @@ void OfflineGenericPrivate::init() { std::regex rgx("(\\d+).(\\d+)"); std::smatch match; if (std::regex_search(g.begin(), g.end(), match, rgx)) { - generation_.reset(CameraGeneration::Private::build(std::stoi(match.str(1)), std::stoi(match.str(2)))); + auto version_major = std::stoi(match.str(1)); + auto version_minor = std::stoi(match.str(2)); + generation_.reset(CameraGeneration::Private::build(version_major, version_minor, + versions_to_name(version_major, version_minor))); } } diff --git a/sdk/modules/driver/cpp/src/camera_offline_raw.cpp b/sdk/modules/stream/cpp/src/camera_offline_raw.cpp similarity index 79% rename from sdk/modules/driver/cpp/src/camera_offline_raw.cpp rename to sdk/modules/stream/cpp/src/camera_offline_raw.cpp index 610bdd694..7124a01ec 100644 --- a/sdk/modules/driver/cpp/src/camera_offline_raw.cpp +++ b/sdk/modules/stream/cpp/src/camera_offline_raw.cpp @@ -9,8 +9,6 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include - #include "metavision/hal/device/device_discovery.h" #include "metavision/hal/device/device_discovery.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" @@ -20,23 +18,23 @@ #include "metavision/hal/facilities/i_hw_identification.h" #include "metavision/hal/facilities/i_plugin_software_info.h" #include "metavision/sdk/base/utils/get_time.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" -#include "metavision/sdk/driver/internal/camera_error_code_internal.h" -#include "metavision/sdk/driver/internal/camera_generation_internal.h" -#include "metavision/sdk/driver/internal/camera_offline_raw_internal.h" -#include "metavision/sdk/driver/internal/cd_internal.h" -#include "metavision/sdk/driver/internal/ext_trigger_internal.h" -#include "metavision/sdk/driver/internal/erc_counter_internal.h" -#include "metavision/sdk/driver/internal/frame_diff_internal.h" -#include "metavision/sdk/driver/internal/frame_histo_internal.h" -#include "metavision/sdk/driver/internal/offline_streaming_control_internal.h" -#include "metavision/sdk/driver/internal/raw_data_internal.h" -#include "metavision/sdk/driver/raw_event_file_reader.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/camera_error_code_internal.h" +#include "metavision/sdk/stream/internal/camera_generation_internal.h" +#include "metavision/sdk/stream/internal/camera_offline_raw_internal.h" +#include "metavision/sdk/stream/internal/cd_internal.h" +#include "metavision/sdk/stream/internal/ext_trigger_internal.h" +#include "metavision/sdk/stream/internal/erc_counter_internal.h" +#include "metavision/sdk/stream/internal/frame_diff_internal.h" +#include "metavision/sdk/stream/internal/frame_histo_internal.h" +#include "metavision/sdk/stream/internal/offline_streaming_control_internal.h" +#include "metavision/sdk/stream/internal/raw_data_internal.h" +#include "metavision/sdk/stream/raw_event_file_reader.h" namespace Metavision { namespace detail { -OfflineRawPrivate::OfflineRawPrivate(const std::string &rawfile, const FileConfigHints &hints) : +OfflineRawPrivate::OfflineRawPrivate(const std::filesystem::path &rawfile, const FileConfigHints &hints) : Private(detail::Config()) { RawFileConfig raw_file_stream_config; raw_file_stream_config.n_events_to_read_ = hints.max_read_per_op() / 4; @@ -48,7 +46,7 @@ OfflineRawPrivate::OfflineRawPrivate(const std::string &rawfile, const FileConfi if (!device_) { // We should never get here as open_raw_file should throw an exception if the system is unknown throw CameraException(CameraErrorCode::InvalidRawfile, - "The RAW file at " + rawfile + + "The RAW file at " + rawfile.string() + " could not be read. Please check that the file has " "been recorded with an event-based device or contact " "the support."); @@ -80,35 +78,6 @@ OfflineStreamingControl &OfflineRawPrivate::offline_streaming_control() { return *osc_; } -TriggerOut &OfflineRawPrivate::trigger_out() { - throw CameraException(UnsupportedFeatureErrors::TriggerOutUnavailable, - "Cannot get trigger out instance when running from a file."); -} - -Biases &OfflineRawPrivate::biases() { - throw CameraException(UnsupportedFeatureErrors::BiasesUnavailable, "Cannot get biases from a file."); -} - -Roi &OfflineRawPrivate::roi() { - throw CameraException(UnsupportedFeatureErrors::RoiUnavailable, - "Cannot get roi instance when running from a file."); -} - -AntiFlickerModule &OfflineRawPrivate::antiflicker_module() { - throw CameraException(UnsupportedFeatureErrors::AntiFlickerModuleUnavailable, - "Cannot get anti-flicker instance when running from a file."); -} - -ErcModule &OfflineRawPrivate::erc_module() { - throw CameraException(UnsupportedFeatureErrors::ErcModuleUnavailable, - "Cannot get erc instance when running from a file."); -} - -EventTrailFilterModule &OfflineRawPrivate::event_trail_filter_module() { - throw CameraException(UnsupportedFeatureErrors::EventTrailFilterModuleUnavailable, - "Cannot get event trail filter instance when running from a file."); -} - timestamp OfflineRawPrivate::get_last_timestamp() const { return last_ts_; } @@ -184,7 +153,6 @@ void OfflineRawPrivate::init() { } camera_configuration_.data_encoding_format = hw_identification->get_current_data_encoding_format(); - camera_configuration_.system_ID = std::to_string(hw_identification->get_system_id()); camera_configuration_.serial_number = hw_identification->get_serial(); camera_configuration_.integrator = hw_identification->get_integrator(); camera_configuration_.firmware_version = hw_identification->get_system_info()["System Version"]; @@ -201,12 +169,6 @@ void OfflineRawPrivate::init() { throw CameraException(InternalInitializationErrors::IEventsStreamNotFound); } - I_Geometry *i_geometry = device_->get_facility(); - if (!i_geometry) { - throw CameraException(InternalInitializationErrors::IGeometryNotFound); - } - geometry_.reset(new Geometry(i_geometry)); - i_decoder_ = device_->get_facility(); generation_.reset(CameraGeneration::Private::build(*device_)); diff --git a/sdk/modules/driver/cpp/src/camera_serialization.cpp b/sdk/modules/stream/cpp/src/camera_serialization.cpp similarity index 97% rename from sdk/modules/driver/cpp/src/camera_serialization.cpp rename to sdk/modules/stream/cpp/src/camera_serialization.cpp index b62e3560c..72f5193f6 100644 --- a/sdk/modules/driver/cpp/src/camera_serialization.cpp +++ b/sdk/modules/stream/cpp/src/camera_serialization.cpp @@ -28,9 +28,9 @@ #include "metavision/hal/facilities/i_trigger_out.h" #include "metavision/hal/utils/hal_exception.h" #include "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/driver/camera_exception.h" -#include "metavision/sdk/driver/camera_error_code.h" -#include "metavision/sdk/driver/internal/camera_serialization.h" +#include "metavision/sdk/stream/camera_exception.h" +#include "metavision/sdk/stream/camera_error_code.h" +#include "metavision/sdk/stream/internal/camera_serialization.h" #include "device_state.pb.h" #endif // HAS_PROTOBUF @@ -214,7 +214,11 @@ class FacilitySerializer { etf_state->set_threshold(module->get_threshold()); } - void operator()(const I_HW_Register *) {} + void operator()(const I_HW_Register *module) { + if (!module) { + return; + } + } void operator()(const I_LL_Biases *module) { if (!module) { @@ -305,6 +309,10 @@ class FacilityDeserializer { FacilityDeserializer(const DeviceSerialization::DeviceState &state) : state_(state) {} void operator()(I_AntiFlickerModule *module) { + if (!module) { + return; + } + if (!state_.has_afk_state()) { return; } @@ -336,6 +344,10 @@ class FacilityDeserializer { } void operator()(I_CameraSynchronization *module) { + if (!module) { + return; + } + if (!state_.has_cam_sync_state()) { return; } @@ -359,6 +371,10 @@ class FacilityDeserializer { } void operator()(I_DigitalCrop *module) { + if (!module) { + return; + } + if (!state_.has_digital_crop_state()) { return; } @@ -375,6 +391,10 @@ class FacilityDeserializer { } void operator()(I_DigitalEventMask *module) { + if (!module) { + return; + } + if (!state_.has_digital_event_mask_state()) { return; } @@ -393,6 +413,10 @@ class FacilityDeserializer { } void operator()(I_ErcModule *module) { + if (!module) { + return; + } + if (!state_.has_event_rate_control_state()) { return; } @@ -475,6 +499,10 @@ class FacilityDeserializer { } void operator()(I_EventTrailFilterModule *module) { + if (!module) { + return; + } + if (!state_.has_event_trail_filter_state()) { return; } @@ -504,6 +532,10 @@ class FacilityDeserializer { } void operator()(I_HW_Register *module) { + if (!module) { + return; + } + if (!state_.has_hw_register_state()) { return; } @@ -524,6 +556,10 @@ class FacilityDeserializer { } void operator()(I_LL_Biases *module) { + if (!module) { + return; + } + if (!state_.has_ll_biases_state()) { return; } @@ -553,6 +589,10 @@ class FacilityDeserializer { } void operator()(I_ROI *module) { + if (!module) { + return; + } + if (!state_.has_roi_state()) { return; } @@ -591,6 +631,10 @@ class FacilityDeserializer { } void operator()(I_TriggerIn *module) { + if (!module) { + return; + } + if (!state_.has_trigger_in_state()) { return; } @@ -621,6 +665,10 @@ class FacilityDeserializer { } void operator()(I_TriggerOut *module) { + if (!module) { + return; + } + if (!state_.has_trigger_out_state()) { return; } diff --git a/sdk/modules/stream/cpp/src/camera_stream_slicer.cpp b/sdk/modules/stream/cpp/src/camera_stream_slicer.cpp new file mode 100644 index 000000000..b17b91f82 --- /dev/null +++ b/sdk/modules/stream/cpp/src/camera_stream_slicer.cpp @@ -0,0 +1,118 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/hal/facilities/i_events_stream_decoder.h" +#include "metavision/sdk/stream/camera_stream_slicer.h" +#include "metavision/hal/facilities/i_camera_synchronization.h" + +namespace Metavision { +bool Slice::operator==(const Slice &other) const { + return events == other.events && triggers == other.triggers; +} + +CameraStreamSlicer::CameraStreamSlicer(Camera &&camera, const SliceCondition &slice_condition, size_t max_queue_size) : + queue_(std::make_unique>(max_queue_size)), camera_(std::move(camera)) { + if (camera_.is_running()) { + throw std::runtime_error( + "Camera is already running. Cannot create a CameraStreamSlicer from a running camera."); + } + + event_buffer_pool_ = SharedObjectPool>::make_unbounded(); + trigger_buffer_pool_ = SharedObjectPool>::make_unbounded(); + curt_event_buffer_ = event_buffer_pool_.acquire(); + curt_trigger_buffer_ = trigger_buffer_pool_.acquire(); + + slicer_.set_slicing_condition(slice_condition); +} + +CameraStreamSlicer::CameraStreamSlicer(CameraStreamSlicer &&slicer) noexcept : + queue_(std::move(slicer.queue_)), + event_buffer_pool_(std::move(slicer.event_buffer_pool_)), + trigger_buffer_pool_(std::move(slicer.trigger_buffer_pool_)), + curt_event_buffer_(std::move(slicer.curt_event_buffer_)), + curt_trigger_buffer_(std::move(slicer.curt_trigger_buffer_)), + slicer_(std::move(slicer.slicer_)), + camera_(std::move(slicer.camera_)) {} + +CameraStreamSlicer &CameraStreamSlicer::operator=(CameraStreamSlicer &&slicer) noexcept { + queue_ = std::move(slicer.queue_); + event_buffer_pool_ = std::move(slicer.event_buffer_pool_); + trigger_buffer_pool_ = std::move(slicer.trigger_buffer_pool_); + curt_event_buffer_ = std::move(slicer.curt_event_buffer_); + curt_trigger_buffer_ = std::move(slicer.curt_trigger_buffer_); + slicer_ = std::move(slicer.slicer_); + camera_ = std::move(slicer.camera_); + + return *this; +} + +CameraStreamSlicer::~CameraStreamSlicer() { + if (queue_) { + queue_->close(); + camera_.stop(); + } +} + +CameraStreamSlicer::SliceIterator CameraStreamSlicer::begin() { + init_slicing(); + + return SliceIterator(queue_); +} + +CameraStreamSlicer::SliceIterator CameraStreamSlicer::end() { + return SliceIterator(); +} + +const Camera &CameraStreamSlicer::camera() const { + return camera_; +} + +void CameraStreamSlicer::init_slicing() { + camera_.cd().add_callback([this](const auto &begin, const auto &end) { + slicer_.process_events(begin, end, [this](const auto &slice_begin, const auto &slice_end) { + curt_event_buffer_->insert(curt_event_buffer_->end(), slice_begin, slice_end); + }); + }); + + camera_.ext_trigger().add_callback([this](const auto &begin, const auto &end) { + curt_trigger_buffer_->insert(curt_trigger_buffer_->end(), begin, end); + }); + + camera_.add_status_change_callback([this](const CameraStatus &status) { + if (status == CameraStatus::STOPPED) { + slicer_.flush(); + queue_->close(); + } + }); + + try { + auto decoder = camera_.get_device().get_facility(); + + decoder->add_time_callback([this](timestamp t) { slicer_.notify_elapsed_time(t); }); + } catch (const CameraException &e) { MV_LOG_TRACE() << e.what(); } + + slicer_.set_on_new_slice_callback([this](auto status, auto t, auto nevents) { + const bool new_slice_added = queue_->emplace({status, t, nevents, curt_event_buffer_, curt_trigger_buffer_}); + if (new_slice_added) { + curt_event_buffer_ = event_buffer_pool_.acquire(); + curt_trigger_buffer_ = trigger_buffer_pool_.acquire(); + + curt_event_buffer_->clear(); + curt_trigger_buffer_->clear(); + } + }); + + camera_.start(); +} + +} // namespace Metavision \ No newline at end of file diff --git a/sdk/modules/driver/cpp/src/cd.cpp b/sdk/modules/stream/cpp/src/cd.cpp similarity index 92% rename from sdk/modules/driver/cpp/src/cd.cpp rename to sdk/modules/stream/cpp/src/cd.cpp index c427d29b7..764f0b43c 100644 --- a/sdk/modules/driver/cpp/src/cd.cpp +++ b/sdk/modules/stream/cpp/src/cd.cpp @@ -9,11 +9,11 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/cd.h" +#include "metavision/sdk/stream/cd.h" -#include "metavision/sdk/driver/internal/cd_internal.h" +#include "metavision/sdk/stream/internal/cd_internal.h" #include "metavision/sdk/core/utils/index_manager.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" namespace Metavision { diff --git a/sdk/modules/driver/cpp/src/dat_event_file_reader.cpp b/sdk/modules/stream/cpp/src/dat_event_file_reader.cpp similarity index 89% rename from sdk/modules/driver/cpp/src/dat_event_file_reader.cpp rename to sdk/modules/stream/cpp/src/dat_event_file_reader.cpp index dccfc7aab..ae5a549be 100644 --- a/sdk/modules/driver/cpp/src/dat_event_file_reader.cpp +++ b/sdk/modules/stream/cpp/src/dat_event_file_reader.cpp @@ -12,15 +12,13 @@ #include #include -#include - #include "metavision/sdk/base/events/event_cd.h" #include "metavision/sdk/base/events/event_ext_trigger.h" #include "metavision/sdk/base/utils/log.h" #include "metavision/sdk/base/utils/generic_header.h" -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/internal/event_file_reader_internal.h" -#include "metavision/sdk/driver/dat_event_file_reader.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/event_file_reader_internal.h" +#include "metavision/sdk/stream/dat_event_file_reader.h" namespace Metavision { @@ -28,28 +26,27 @@ class DATEventFileReader::Private { public: Private(DATEventFileReader &reader) : reader_(reader), data_stream_(reader.get_path()) { metadata_["generation"] = "3.0"; - metadata_["system_ID"] = "0"; - if (boost::filesystem::exists(reader.get_path())) { + if (std::filesystem::exists(reader.get_path())) { setup_dat_stream(reader.get_path()); } else { bool found_target_files = false; - if (boost::filesystem::exists(reader.get_path() + "_cd.dat")) { - setup_dat_stream(reader.get_path() + "_cd.dat"); + if (std::filesystem::exists(reader.get_path().string() + "_cd.dat")) { + setup_dat_stream(reader.get_path().string() + "_cd.dat"); found_target_files = true; } - if (boost::filesystem::exists(reader.get_path() + "_td.dat")) { - setup_dat_stream(reader.get_path() + "_td.dat"); + if (std::filesystem::exists(reader.get_path().string() + "_td.dat")) { + setup_dat_stream(reader.get_path().string() + "_td.dat"); found_target_files = true; } - if (boost::filesystem::exists(reader.get_path() + "_trigger.dat")) { - setup_dat_stream(reader.get_path() + "_trigger.dat"); + if (std::filesystem::exists(reader.get_path().string() + "_trigger.dat")) { + setup_dat_stream(reader.get_path().string() + "_trigger.dat"); found_target_files = true; } if (!found_target_files) { - throw std::runtime_error("Could not find dat files for \"" + reader.get_path() + "\""); + throw std::runtime_error("Could not find dat files for \"" + reader.get_path().string() + "\""); } } } @@ -109,7 +106,7 @@ class DATEventFileReader::Private { template class DATStream { public: - DATStream(DATEventFileReader &reader, std::ifstream &&ifs, const std::string &path) : + DATStream(DATEventFileReader &reader, std::ifstream &&ifs, const std::filesystem::path &path) : reader_(reader), data_stream_(std::move(ifs)), path_(path) {} bool read_events() { @@ -172,10 +169,10 @@ class DATEventFileReader::Private { uint64_t raw_events_[kEvtChunk]; uint64_t *pos_ptr_ = nullptr; uint64_t *end_ptr_ = nullptr; - const std::string path_; + const std::filesystem::path path_; }; - void setup_dat_stream(const std::string &path) { + void setup_dat_stream(const std::filesystem::path &path) { std::ifstream data(path, std::ios::binary); if (!data.is_open()) { @@ -220,7 +217,7 @@ class DATEventFileReader::Private { std::unique_ptr> ext_trig_stream_; }; -DATEventFileReader::DATEventFileReader(const std::string &path) : +DATEventFileReader::DATEventFileReader(const std::filesystem::path &path) : EventFileReader(path), pimpl_(new Private(*this)) {} DATEventFileReader::~DATEventFileReader() {} diff --git a/sdk/modules/driver/cpp/src/erc_counter.cpp b/sdk/modules/stream/cpp/src/erc_counter.cpp similarity index 92% rename from sdk/modules/driver/cpp/src/erc_counter.cpp rename to sdk/modules/stream/cpp/src/erc_counter.cpp index 82427fd35..2a5b3e68a 100644 --- a/sdk/modules/driver/cpp/src/erc_counter.cpp +++ b/sdk/modules/stream/cpp/src/erc_counter.cpp @@ -9,11 +9,11 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/erc_counter.h" +#include "metavision/sdk/stream/erc_counter.h" -#include "metavision/sdk/driver/internal/erc_counter_internal.h" +#include "metavision/sdk/stream/internal/erc_counter_internal.h" #include "metavision/sdk/core/utils/index_manager.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" namespace Metavision { diff --git a/sdk/modules/driver/cpp/src/event_file_reader.cpp b/sdk/modules/stream/cpp/src/event_file_reader.cpp similarity index 95% rename from sdk/modules/driver/cpp/src/event_file_reader.cpp rename to sdk/modules/stream/cpp/src/event_file_reader.cpp index b5bdee8fb..acc8c0f6b 100644 --- a/sdk/modules/driver/cpp/src/event_file_reader.cpp +++ b/sdk/modules/stream/cpp/src/event_file_reader.cpp @@ -9,12 +9,12 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/internal/callback_tag_ids.h" -#include "metavision/sdk/driver/internal/event_file_reader_internal.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/event_file_reader_internal.h" namespace Metavision { -EventFileReader::Private::Private(EventFileReader &reader, const std::string &path) : +EventFileReader::Private::Private(EventFileReader &reader, const std::filesystem::path &path) : reader_(reader), seeking_(false), cd_buffer_cb_mgr_(cb_id_mgr_, CallbackTagIds::READ_CALLBACK_TAG_ID), @@ -29,7 +29,7 @@ EventFileReader::Private::Private(EventFileReader &reader, const std::string &pa max_t_(-1), duration_(-1) {} -const std::string &EventFileReader::Private::get_path() const { +const std::filesystem::path &EventFileReader::Private::get_path() const { return path_; } @@ -178,11 +178,11 @@ std::unordered_map EventFileReader::Private::get_metad return metadata_map_; } -EventFileReader::EventFileReader(const std::string &path) : pimpl_(new Private(*this, path)) {} +EventFileReader::EventFileReader(const std::filesystem::path &path) : pimpl_(new Private(*this, path)) {} EventFileReader::~EventFileReader() {} -const std::string &EventFileReader::get_path() const { +const std::filesystem::path &EventFileReader::get_path() const { return pimpl_->get_path(); } diff --git a/sdk/modules/driver/cpp/src/event_file_writer.cpp b/sdk/modules/stream/cpp/src/event_file_writer.cpp similarity index 86% rename from sdk/modules/driver/cpp/src/event_file_writer.cpp rename to sdk/modules/stream/cpp/src/event_file_writer.cpp index 9ccad7be5..6f6876b27 100644 --- a/sdk/modules/driver/cpp/src/event_file_writer.cpp +++ b/sdk/modules/stream/cpp/src/event_file_writer.cpp @@ -13,25 +13,32 @@ #include #include -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/internal/event_file_writer_internal.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/event_file_writer_internal.h" namespace Metavision { -EventFileWriter::Private::Private(EventFileWriter &writer, const std::string &path) : +EventFileWriter::Private::Private(EventFileWriter &writer, const std::filesystem::path &path) : writer_(writer), last_cd_ts_(-1), last_ext_trigger_ts_(-1), path_(path) { writer_thread_.start(); - if (!path.empty()) { - cd_buffer_ptr_ = cd_buffer_pool_.acquire(); - ext_trigger_buffer_ptr_ = ext_trigger_buffer_pool_.acquire(); - } + cd_buffer_ptr_ = cd_buffer_pool_.acquire(); + ext_trigger_buffer_ptr_ = ext_trigger_buffer_pool_.acquire(); +} + +void EventFileWriter::Private::set_max_event_cd_buffer_size(size_t size) { + max_event_cd_buffer_size_ = size; +} + +void EventFileWriter::Private::set_max_event_trigger_buffer_size(size_t size) { + max_event_trigger_buffer_size_ = size; } -void EventFileWriter::Private::open(const std::string &path) { +void EventFileWriter::Private::open(const std::filesystem::path &path) { std::unique_lock lock(mutex_); if (writer_.is_open_impl()) { return; } + path_ = path; writer_thread_.start(); writer_.open_impl(path); } @@ -77,7 +84,7 @@ void EventFileWriter::Private::flush() { writer_.flush_impl(); } -const std::string &EventFileWriter::Private::get_path() const { +const std::filesystem::path &EventFileWriter::Private::get_path() const { return path_; } @@ -98,7 +105,7 @@ bool EventFileWriter::Private::add_events(const EventCD *begin, const EventCD *e last_cd_ts_ = std::prev(end)->t; cd_buffer_ptr_->insert(cd_buffer_ptr_->end(), begin, end); - if (cd_buffer_ptr_->size() > kMaxEventCDBufferSize) { + if (cd_buffer_ptr_->size() > max_event_cd_buffer_size_) { writer_thread_.add_task( [this, buf = cd_buffer_ptr_]() { writer_.add_events_impl(buf->data(), buf->data() + buf->size()); }); cd_buffer_ptr_ = cd_buffer_pool_.acquire(); @@ -125,7 +132,7 @@ bool EventFileWriter::Private::add_events(const EventExtTrigger *begin, const Ev last_ext_trigger_ts_ = std::prev(end)->t; ext_trigger_buffer_ptr_->insert(ext_trigger_buffer_ptr_->end(), begin, end); - if (ext_trigger_buffer_ptr_->size() > kMaxEventTriggerBufferSize) { + if (ext_trigger_buffer_ptr_->size() > max_event_trigger_buffer_size_) { writer_thread_.add_task([this, buf = ext_trigger_buffer_ptr_]() { writer_.add_events_impl(buf->data(), buf->data() + buf->size()); }); @@ -150,13 +157,14 @@ void EventFileWriter::Private::add_metadata_map_from_camera(const Camera &camera return; } - const unsigned short width = camera.geometry().width(); - const unsigned short height = camera.geometry().height(); + const unsigned short width = camera.geometry().get_width(); + const unsigned short height = camera.geometry().get_height(); auto &config = camera.get_camera_configuration(); std::unordered_map metadata_map = { - {"integrator_name", config.integrator}, + {"plugin_integrator_name", config.integrator}, + {"camera_integrator_name", config.integrator}, + {"format", config.data_encoding_format}, {"serial_number", config.serial_number}, - {"system_ID", config.system_ID}, {"generation", std::to_string(camera.generation().version_major()) + "." + std::to_string(camera.generation().version_minor())}, {"geometry", std::to_string(width) + "x" + std::to_string(height)}}; @@ -185,11 +193,11 @@ void EventFileWriter::Private::remove_metadata(const std::string &key) { writer_thread_.add_task([this, key] { writer_.remove_metadata_impl(key); }); } -EventFileWriter::EventFileWriter(const std::string &path) : pimpl_(new Private(*this, path)) {} +EventFileWriter::EventFileWriter(const std::filesystem::path &path) : pimpl_(new Private(*this, path)) {} EventFileWriter::~EventFileWriter() {} -void EventFileWriter::open(const std::string &path) { +void EventFileWriter::open(const std::filesystem::path &path) { pimpl_->open(path); } @@ -205,7 +213,7 @@ void EventFileWriter::flush() { pimpl_->flush(); } -const std::string &EventFileWriter::get_path() const { +const std::filesystem::path &EventFileWriter::get_path() const { return pimpl_->get_path(); } diff --git a/sdk/modules/driver/cpp/src/ext_trigger.cpp b/sdk/modules/stream/cpp/src/ext_trigger.cpp similarity index 92% rename from sdk/modules/driver/cpp/src/ext_trigger.cpp rename to sdk/modules/stream/cpp/src/ext_trigger.cpp index f333ad69b..87f7cd551 100644 --- a/sdk/modules/driver/cpp/src/ext_trigger.cpp +++ b/sdk/modules/stream/cpp/src/ext_trigger.cpp @@ -9,11 +9,11 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/ext_trigger.h" +#include "metavision/sdk/stream/ext_trigger.h" -#include "metavision/sdk/driver/internal/ext_trigger_internal.h" +#include "metavision/sdk/stream/internal/ext_trigger_internal.h" #include "metavision/sdk/core/utils/index_manager.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" namespace Metavision { diff --git a/sdk/modules/driver/cpp/src/frame_diff.cpp b/sdk/modules/stream/cpp/src/frame_diff.cpp similarity index 92% rename from sdk/modules/driver/cpp/src/frame_diff.cpp rename to sdk/modules/stream/cpp/src/frame_diff.cpp index 4b1b9aaaf..fc45a073b 100644 --- a/sdk/modules/driver/cpp/src/frame_diff.cpp +++ b/sdk/modules/stream/cpp/src/frame_diff.cpp @@ -9,11 +9,11 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/frame_diff.h" +#include "metavision/sdk/stream/frame_diff.h" -#include "metavision/sdk/driver/internal/frame_diff_internal.h" +#include "metavision/sdk/stream/internal/frame_diff_internal.h" #include "metavision/sdk/core/utils/index_manager.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" namespace Metavision { diff --git a/sdk/modules/driver/cpp/src/frame_histo.cpp b/sdk/modules/stream/cpp/src/frame_histo.cpp similarity index 92% rename from sdk/modules/driver/cpp/src/frame_histo.cpp rename to sdk/modules/stream/cpp/src/frame_histo.cpp index bbccc716f..fa890a8e3 100644 --- a/sdk/modules/driver/cpp/src/frame_histo.cpp +++ b/sdk/modules/stream/cpp/src/frame_histo.cpp @@ -9,11 +9,11 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/frame_histo.h" +#include "metavision/sdk/stream/frame_histo.h" -#include "metavision/sdk/driver/internal/frame_histo_internal.h" +#include "metavision/sdk/stream/internal/frame_histo_internal.h" #include "metavision/sdk/core/utils/index_manager.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" namespace Metavision { diff --git a/sdk/modules/driver/cpp/src/hdf5_event_file_reader.cpp b/sdk/modules/stream/cpp/src/hdf5_event_file_reader.cpp similarity index 97% rename from sdk/modules/driver/cpp/src/hdf5_event_file_reader.cpp rename to sdk/modules/stream/cpp/src/hdf5_event_file_reader.cpp index 511d6800d..c2c7a0e1f 100644 --- a/sdk/modules/driver/cpp/src/hdf5_event_file_reader.cpp +++ b/sdk/modules/stream/cpp/src/hdf5_event_file_reader.cpp @@ -16,7 +16,7 @@ #include #include #endif -#include "metavision/sdk/driver/hdf5_event_file_reader.h" +#include "metavision/sdk/stream/hdf5_event_file_reader.h" namespace Metavision { #ifdef HAS_HDF5 @@ -308,9 +308,10 @@ class IndexesReader { class HDF5EventFileReader::Private { public: - Private(HDF5EventFileReader &reader, const std::string &path, bool time_shift) : timeshift_(0), reader_(reader) { + Private(HDF5EventFileReader &reader, const std::filesystem::path &path, bool time_shift) : + timeshift_(0), reader_(reader) { #ifdef HAS_HDF5 - file_ = H5::H5File(path, H5F_ACC_RDONLY); + file_ = H5::H5File(path.string(), H5F_ACC_RDONLY); auto root = file_.openGroup("/"); if (time_shift) { @@ -492,7 +493,7 @@ class HDF5EventFileReader::Private { HDF5EventFileReader &reader_; }; -HDF5EventFileReader::HDF5EventFileReader(const std::string &path, bool time_shift) : +HDF5EventFileReader::HDF5EventFileReader(const std::filesystem::path &path, bool time_shift) : EventFileReader(path), pimpl_(new Private(*this, path, time_shift)) {} HDF5EventFileReader::~HDF5EventFileReader() {} diff --git a/sdk/modules/driver/cpp/src/hdf5_event_file_writer.cpp b/sdk/modules/stream/cpp/src/hdf5_event_file_writer.cpp similarity index 96% rename from sdk/modules/driver/cpp/src/hdf5_event_file_writer.cpp rename to sdk/modules/stream/cpp/src/hdf5_event_file_writer.cpp index 263219d8a..e8099ca74 100644 --- a/sdk/modules/driver/cpp/src/hdf5_event_file_writer.cpp +++ b/sdk/modules/stream/cpp/src/hdf5_event_file_writer.cpp @@ -20,8 +20,8 @@ #include #include -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/hdf5_event_file_writer.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/hdf5_event_file_writer.h" namespace Metavision { #ifdef HAS_HDF5 @@ -235,7 +235,7 @@ class IndexesWriter { class HDF5EventFileWriter::Private { public: - Private(HDF5EventFileWriter &writer, const std::string &path, + Private(HDF5EventFileWriter &writer, const std::filesystem::path &path, const std::unordered_map &metadata_map) : writer_(writer) { if (!path.empty()) { @@ -246,7 +246,7 @@ class HDF5EventFileWriter::Private { } } - void open_impl(const std::string &path) { + void open_impl(const std::filesystem::path &path) { #ifdef HAS_HDF5 hsize_t dims[1] = {0}, maxdims[1] = {H5S_UNLIMITED}; hsize_t chunk_dims[1] = {kChunkSize}; @@ -268,7 +268,7 @@ class HDF5EventFileWriter::Private { H5::DSetCreatPropList cd_index_ds_prop; cd_index_ds_prop.setChunk(1, chunk_dims); - file_ = H5::H5File(path, H5F_ACC_TRUNC); + file_ = H5::H5File(path.string(), H5F_ACC_TRUNC); file_.createGroup("/CD"); H5::DataSet cd_events_dset = file_.createDataSet("/CD/events", cd_event_dt, cd_event_ds, cd_event_ds_prop); H5::DataSet cd_indexes_dset = file_.createDataSet("/CD/indexes", cd_index_dt, cd_index_ds, cd_index_ds_prop); @@ -403,7 +403,7 @@ class HDF5EventFileWriter::Private { HDF5EventFileWriter &writer_; }; -HDF5EventFileWriter::HDF5EventFileWriter(const std::string &path, +HDF5EventFileWriter::HDF5EventFileWriter(const std::filesystem::path &path, const std::unordered_map &metadata_map) : EventFileWriter(path), pimpl_(new Private(*this, path, metadata_map)) {} @@ -411,16 +411,18 @@ HDF5EventFileWriter::~HDF5EventFileWriter() { close(); } -void HDF5EventFileWriter::open_impl(const std::string &path) { +void HDF5EventFileWriter::open_impl(const std::filesystem::path &path) { return pimpl_->open_impl(path); } void HDF5EventFileWriter::close_impl() { - pimpl_->close_impl(); + if (pimpl_) { + pimpl_->close_impl(); + } } bool HDF5EventFileWriter::is_open_impl() const { - return pimpl_->is_open_impl(); + return pimpl_ && pimpl_->is_open_impl(); } void HDF5EventFileWriter::flush_impl() { diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/callback_tag_ids.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/callback_tag_ids.h similarity index 91% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/callback_tag_ids.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/callback_tag_ids.h index 02b0d686e..c49f748c4 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/callback_tag_ids.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/callback_tag_ids.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CALLBACK_TAG_IDS_H -#define METAVISION_SDK_DRIVER_CALLBACK_TAG_IDS_H +#ifndef METAVISION_SDK_STREAM_CALLBACK_TAG_IDS_H +#define METAVISION_SDK_STREAM_CALLBACK_TAG_IDS_H #include @@ -25,4 +25,4 @@ static constexpr std::uint8_t SEEK_CALLBACK_TAG_ID = DECODE_CALLBACK_TAG_ID + } // namespace CallbackTagIds } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CALLBACK_TAG_IDS_H +#endif // METAVISION_SDK_STREAM_CALLBACK_TAG_IDS_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_error_code_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_error_code_internal.h similarity index 73% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_error_code_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_error_code_internal.h index cdd9194a0..f147a10f8 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_error_code_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_error_code_internal.h @@ -9,10 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_ERROR_CODE_INTERNAL_H -#define METAVISION_SDK_DRIVER_CAMERA_ERROR_CODE_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_CAMERA_ERROR_CODE_INTERNAL_H +#define METAVISION_SDK_STREAM_CAMERA_ERROR_CODE_INTERNAL_H -#include "metavision/sdk/driver/camera_error_code.h" +#include "metavision/sdk/stream/camera_error_code.h" namespace Metavision { @@ -21,13 +21,11 @@ namespace InternalInitializationErrors { enum : CameraErrorCodeType { // Failed initialization errors IBoardIdentificationNotFound = CameraErrorCode::InternalInitializationError | 0x1, - ILLBiasesNotFound = CameraErrorCode::InternalInitializationError | 0x2, IEventsStreamNotFound = CameraErrorCode::InternalInitializationError | 0x3, IDeviceControlNotFound = CameraErrorCode::InternalInitializationError | 0x4, IDecoderNotFound = CameraErrorCode::InternalInitializationError | 0x5, ICDDecoderNotFound = CameraErrorCode::InternalInitializationError | 0x6, IGeometryNotFound = CameraErrorCode::InternalInitializationError | 0x9, - IRoiNotFound = CameraErrorCode::InternalInitializationError | 0xA, UnknownSystemId = CameraErrorCode::InternalInitializationError | 0xB, InvalidFPGAState = CameraErrorCode::InternalInitializationError | 0xE, }; @@ -36,13 +34,7 @@ enum : CameraErrorCodeType { /// Runtime Error specific code namespace UnsupportedFeatureErrors { enum : CameraErrorCodeType { - RoiUnavailable = CameraErrorCode::UnsupportedFeature | 0x2, - BiasesUnavailable = CameraErrorCode::UnsupportedFeature | 0x3, - TriggerOutUnavailable = CameraErrorCode::UnsupportedFeature | 0x4, ExtTriggerUnavailable = CameraErrorCode::UnsupportedFeature | 0x5, - AntiFlickerModuleUnavailable = CameraErrorCode::UnsupportedFeature | 0xD, - EventTrailFilterModuleUnavailable = CameraErrorCode::UnsupportedFeature | 0xF, - ErcModuleUnavailable = CameraErrorCode::UnsupportedFeature | 0x10, OfflineStreamingControlUnavailable = CameraErrorCode::UnsupportedFeature | 0x11, RawRecordingUnavailable = CameraErrorCode::UnsupportedFeature | 0x12, DeviceUnavailable = CameraErrorCode::UnsupportedFeature | 0x13, @@ -55,13 +47,6 @@ enum : CameraErrorCodeType { }; } -namespace BiasesErrors { -enum : CameraErrorCodeType { - UnsupportedBiasFile = CameraErrorCode::BiasesError | 0x1, - UnsupportedBias = CameraErrorCode::BiasesError | 0x2, -}; -} - } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_ERROR_CODE_INTERNAL_H +#endif // METAVISION_SDK_STREAM_CAMERA_ERROR_CODE_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_generation_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_generation_internal.h similarity index 79% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_generation_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_generation_internal.h index 1e6a9f71f..ba8d34804 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_generation_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_generation_internal.h @@ -9,16 +9,18 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_DRIVER_CAMERA_GENERATION_INTERNAL_H -#define METAVISION_DRIVER_CAMERA_GENERATION_INTERNAL_H +#ifndef METAVISION_STREAM_CAMERA_GENERATION_INTERNAL_H +#define METAVISION_STREAM_CAMERA_GENERATION_INTERNAL_H -#include "metavision/sdk/driver/camera_generation.h" +#include +#include "metavision/sdk/stream/camera_generation.h" namespace Metavision { class Device; struct CameraGeneration::Private { - Private(short version_major, short version_minor); + Private(const std::string &name); + Private(short version_major, short version_minor, const std::string &name); virtual ~Private(); @@ -35,13 +37,15 @@ struct CameraGeneration::Private { bool operator>=(const CameraGeneration::Private &c) const; - static CameraGeneration *build(short version_major, short version_minor); + static CameraGeneration *build(const std::string &name); + static CameraGeneration *build(short version_major, short version_minor, const std::string &name = std::string()); static CameraGeneration *build(Device &device); const short major_{-1}; const short minor_{-1}; + const std::string name_; }; } // namespace Metavision -#endif // METAVISION_DRIVER_CAMERA_GENERATION_INTERNAL_H +#endif // METAVISION_STREAM_CAMERA_GENERATION_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_internal.h similarity index 83% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_internal.h index 781aefe6b..8ac5234c9 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_internal.h @@ -9,9 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_INTERNAL_H -#define METAVISION_SDK_DRIVER_CAMERA_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_CAMERA_INTERNAL_H +#define METAVISION_SDK_STREAM_CAMERA_INTERNAL_H +#include #include #include #include @@ -19,7 +20,7 @@ #include #include -#include "metavision/sdk/driver/camera.h" +#include "metavision/sdk/stream/camera.h" #include "metavision/sdk/core/utils/index_manager.h" #include "metavision/sdk/core/utils/timing_profiler.h" @@ -32,6 +33,8 @@ struct Config { } // namespace detail +class I_Geometry; + class Camera::Private { public: Private(); @@ -47,8 +50,8 @@ class Camera::Private { bool start(); bool stop(); - bool start_recording(const std::string &file_path); - bool stop_recording(const std::string &file_path = std::string()); + bool start_recording(const std::filesystem::path &file_path); + bool stop_recording(const std::filesystem::path &file_path = std::filesystem::path()); CD &cd(); ExtTrigger &ext_trigger(); @@ -57,24 +60,18 @@ class Camera::Private { FrameHisto &frame_histo(); FrameDiff &frame_diff(); - const Geometry &geometry() const; const CameraGeneration &generation() const; virtual Device &device(); virtual OfflineStreamingControl &offline_streaming_control(); - virtual TriggerOut &trigger_out(); - virtual Biases &biases(); - virtual Roi &roi(); - virtual AntiFlickerModule &antiflicker_module(); - virtual ErcModule &erc_module(); - virtual EventTrailFilterModule &event_trail_filter_module(); virtual timestamp get_last_timestamp() const; virtual void start_impl(); virtual void stop_impl(); virtual bool process_impl(); - virtual bool start_recording_impl(const std::string &file_path); - virtual bool stop_recording_impl(const std::string &file_path); + virtual bool start_recording_impl(const std::filesystem::path &file_path); + virtual bool stop_recording_impl(const std::filesystem::path &file_path); + virtual I_Geometry &get_geometry(); virtual void save(std::ostream &os) const; virtual void load(std::istream &is); @@ -111,7 +108,6 @@ class Camera::Private { std::unique_ptr frame_diff_; std::unique_ptr raw_data_; - std::unique_ptr geometry_; std::unique_ptr generation_; std::unordered_multimap recording_cb_ids_; @@ -122,4 +118,4 @@ class Camera::Private { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_INTERNAL_H +#endif // METAVISION_SDK_STREAM_CAMERA_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_live_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_live_internal.h similarity index 76% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_live_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_live_internal.h index 79847ec69..d2a80184b 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_live_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_live_internal.h @@ -9,10 +9,12 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_LIVE_INTERNAL_H -#define METAVISION_SDK_DRIVER_CAMERA_LIVE_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_CAMERA_LIVE_INTERNAL_H +#define METAVISION_SDK_STREAM_CAMERA_LIVE_INTERNAL_H -#include "metavision/sdk/driver/internal/camera_internal.h" +#include + +#include "metavision/sdk/stream/internal/camera_internal.h" namespace Metavision { @@ -37,12 +39,6 @@ class LivePrivate : public Camera::Private { Device &device() override; OfflineStreamingControl &offline_streaming_control() override; - TriggerOut &trigger_out() override; - Biases &biases() override; - Roi &roi() override; - AntiFlickerModule &antiflicker_module() override; - ErcModule &erc_module() override; - EventTrailFilterModule &event_trail_filter_module() override; timestamp get_last_timestamp() const override; void start_impl() override; @@ -52,7 +48,7 @@ class LivePrivate : public Camera::Private { template bool process_impl(TimingProfilerType *); - bool start_recording_impl(const std::string &file_path) override; + bool start_recording_impl(const std::filesystem::path &file_path) override; void save(std::ostream &) const override; void load(std::istream &) override; @@ -62,16 +58,9 @@ class LivePrivate : public Camera::Private { I_EventsStreamDecoder *i_events_stream_decoder_ = nullptr; I_Decoder *i_decoder_ = nullptr; I_CameraSynchronization *i_camera_synchronization_ = nullptr; - - std::unique_ptr roi_; - std::unique_ptr trigger_out_; - std::unique_ptr biases_; - std::unique_ptr afk_; - std::unique_ptr ercm_; - std::unique_ptr event_trail_filter_; }; } // namespace detail } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_LIVE_INTERNAL_H +#endif // METAVISION_SDK_STREAM_CAMERA_LIVE_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_offline_generic_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_offline_generic_internal.h similarity index 78% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_offline_generic_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_offline_generic_internal.h index 5376e6e93..e197988b4 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_offline_generic_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_offline_generic_internal.h @@ -9,20 +9,22 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_OFFLINE_GENERIC_INTERNAL_H -#define METAVISION_SDK_DRIVER_CAMERA_OFFLINE_GENERIC_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_CAMERA_OFFLINE_GENERIC_INTERNAL_H +#define METAVISION_SDK_STREAM_CAMERA_OFFLINE_GENERIC_INTERNAL_H -#include "metavision/sdk/driver/internal/camera_internal.h" +#include +#include "metavision/sdk/stream/internal/camera_internal.h" namespace Metavision { class EventFileReader; +class I_Geometry; namespace detail { struct GenericGeometry; class OfflineGenericPrivate : public Camera::Private { public: - OfflineGenericPrivate(const std::string &file_path, const FileConfigHints &hints); + OfflineGenericPrivate(const std::filesystem::path &file_path, const FileConfigHints &hints); ~OfflineGenericPrivate() override; private: @@ -30,14 +32,9 @@ class OfflineGenericPrivate : public Camera::Private { Device &device() override; OfflineStreamingControl &offline_streaming_control() override; - TriggerOut &trigger_out() override; - Biases &biases() override; - Roi &roi() override; - AntiFlickerModule &antiflicker_module() override; - ErcModule &erc_module() override; - EventTrailFilterModule &event_trail_filter_module() override; timestamp get_last_timestamp() const override; + I_Geometry &get_geometry() override; void start_impl() override; void stop_impl() override; bool process_impl() override; @@ -59,4 +56,4 @@ class OfflineGenericPrivate : public Camera::Private { } // namespace detail } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_OFFLINE_GENERIC_INTERNAL_H +#endif // METAVISION_SDK_STREAM_CAMERA_OFFLINE_GENERIC_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_offline_raw_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_offline_raw_internal.h similarity index 80% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_offline_raw_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_offline_raw_internal.h index 86bbf45d7..ee6cd2c3f 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_offline_raw_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_offline_raw_internal.h @@ -9,12 +9,13 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_OFFLINE_RAW_INTERNAL_H -#define METAVISION_SDK_DRIVER_CAMERA_OFFLINE_RAW_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_CAMERA_OFFLINE_RAW_INTERNAL_H +#define METAVISION_SDK_STREAM_CAMERA_OFFLINE_RAW_INTERNAL_H +#include #include "metavision/hal/facilities/i_events_stream.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" -#include "metavision/sdk/driver/internal/camera_internal.h" +#include "metavision/sdk/stream/internal/camera_internal.h" namespace Metavision { @@ -26,7 +27,7 @@ namespace detail { class OfflineRawPrivate : public Camera::Private { public: - OfflineRawPrivate(const std::string &rawfile, const FileConfigHints &hints); + OfflineRawPrivate(const std::filesystem::path &rawfile, const FileConfigHints &hints); ~OfflineRawPrivate() override; private: @@ -34,12 +35,6 @@ class OfflineRawPrivate : public Camera::Private { Device &device() override; OfflineStreamingControl &offline_streaming_control() override; - TriggerOut &trigger_out() override; - Biases &biases() override; - Roi &roi() override; - AntiFlickerModule &antiflicker_module() override; - ErcModule &erc_module() override; - EventTrailFilterModule &event_trail_filter_module() override; timestamp get_last_timestamp() const override; void start_impl() override; @@ -66,4 +61,4 @@ class OfflineRawPrivate : public Camera::Private { } // namespace detail } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_OFFLINE_RAW_INTERNAL_H +#endif // METAVISION_SDK_STREAM_CAMERA_OFFLINE_RAW_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_serialization.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_serialization.h similarity index 89% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_serialization.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_serialization.h index d9694c2d3..62e9890a0 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/camera_serialization.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/camera_serialization.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CAMERA_SERIALIZATION_H -#define METAVISION_SDK_DRIVER_CAMERA_SERIALIZATION_H +#ifndef METAVISION_SDK_STREAM_CAMERA_SERIALIZATION_H +#define METAVISION_SDK_STREAM_CAMERA_SERIALIZATION_H #include #include @@ -24,4 +24,4 @@ std::istream &load_device(Device &d, std::istream &is); } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CAMERA_SERIALIZATION_H +#endif // METAVISION_SDK_STREAM_CAMERA_SERIALIZATION_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/cd_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/cd_internal.h similarity index 92% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/cd_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/cd_internal.h index 58f1b1112..ba1384bfb 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/cd_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/cd_internal.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_CD_INTERNAL_H -#define METAVISION_SDK_DRIVER_CD_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_CD_INTERNAL_H +#define METAVISION_SDK_STREAM_CD_INTERNAL_H #include #include @@ -33,4 +33,4 @@ class CD::Private : public CallbackManager { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_CD_INTERNAL_H +#endif // METAVISION_SDK_STREAM_CD_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/erc_counter_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/erc_counter_internal.h similarity index 90% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/erc_counter_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/erc_counter_internal.h index 80c2b0c30..eccfdec41 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/erc_counter_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/erc_counter_internal.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_ERC_COUNTER_INTERNAL_H -#define METAVISION_SDK_DRIVER_ERC_COUNTER_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_ERC_COUNTER_INTERNAL_H +#define METAVISION_SDK_STREAM_ERC_COUNTER_INTERNAL_H #include #include @@ -33,4 +33,4 @@ class ERCCounter::Private : public CallbackManager { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_ERC_COUNTER_INTERNAL_H +#endif // METAVISION_SDK_STREAM_ERC_COUNTER_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_reader_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/event_file_reader_internal.h similarity index 90% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_reader_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/event_file_reader_internal.h index 5a64ab590..8f451a835 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_reader_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/event_file_reader_internal.h @@ -9,9 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_EVENT_FILE_READER_INTERNAL_H -#define METAVISION_SDK_DRIVER_EVENT_FILE_READER_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_EVENT_FILE_READER_INTERNAL_H +#define METAVISION_SDK_STREAM_EVENT_FILE_READER_INTERNAL_H +#include #include #include #include @@ -19,15 +20,15 @@ #include #include "metavision/sdk/core/utils/callback_manager.h" #include "metavision/sdk/core/utils/index_manager.h" -#include "metavision/sdk/driver/event_file_reader.h" +#include "metavision/sdk/stream/event_file_reader.h" namespace Metavision { class EventFileReader::Private { public: - Private(EventFileReader &reader, const std::string &path); + Private(EventFileReader &reader, const std::filesystem::path &path); - const std::string &get_path() const; + const std::filesystem::path &get_path() const; size_t add_read_callback(const EventsBufferReadCallback &cb); size_t add_read_callback(const EventsBufferReadCallback &cb); @@ -69,11 +70,11 @@ class EventFileReader::Private { CallbackManager, size_t> diff_cb_mgr_; CallbackManager, size_t> pointcloud_cb_mgr_; CallbackManager seek_cb_mgr_; - std::string path_; + std::filesystem::path path_; mutable timestamp min_t_, max_t_, duration_; // cached mutable std::unordered_map metadata_map_; // cached }; } // namespace Metavision -#endif /* METAVISION_SDK_DRIVER_EVENT_FILE_READER_INTERNAL_H */ +#endif /* METAVISION_SDK_STREAM_EVENT_FILE_READER_INTERNAL_H */ diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_writer_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/event_file_writer_internal.h similarity index 68% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_writer_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/event_file_writer_internal.h index ae5920466..c92411743 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/event_file_writer_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/event_file_writer_internal.h @@ -9,23 +9,27 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_EVENT_FILE_WRITER_INTERNAL_H -#define METAVISION_SDK_DRIVER_EVENT_FILE_WRITER_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_EVENT_FILE_WRITER_INTERNAL_H +#define METAVISION_SDK_STREAM_EVENT_FILE_WRITER_INTERNAL_H +#include #include #include "metavision/sdk/base/utils/object_pool.h" #include "metavision/sdk/core/utils/threaded_process.h" -#include "metavision/sdk/driver/event_file_writer.h" +#include "metavision/sdk/stream/event_file_writer.h" namespace Metavision { class EventFileWriter::Private { public: - Private(EventFileWriter &writer, const std::string &path); + Private(EventFileWriter &writer, const std::filesystem::path &path); - const std::string &get_path() const; + const std::filesystem::path &get_path() const; - void open(const std::string &path); + void set_max_event_cd_buffer_size(size_t size); + void set_max_event_trigger_buffer_size(size_t size); + + void open(const std::filesystem::path &path); void close(); bool is_open() const; void flush(); @@ -40,14 +44,14 @@ class EventFileWriter::Private { mutable std::mutex mutex_; EventFileWriter &writer_; timestamp last_cd_ts_, last_ext_trigger_ts_; - std::string path_; - - static constexpr size_t kMaxEventCDBufferSize = 64384; - static constexpr size_t kMaxEventTriggerBufferSize = 1028; - using EventCDBufferPool = SharedObjectPool>; - using EventCDBufferPtr = EventCDBufferPool::ptr_type; - using EventExtTriggerBufferPool = SharedObjectPool>; - using EventExtTriggerBufferPtr = EventExtTriggerBufferPool::ptr_type; + std::filesystem::path path_; + + size_t max_event_cd_buffer_size_ = 64384; + size_t max_event_trigger_buffer_size_ = 1028; + using EventCDBufferPool = SharedObjectPool>; + using EventCDBufferPtr = EventCDBufferPool::ptr_type; + using EventExtTriggerBufferPool = SharedObjectPool>; + using EventExtTriggerBufferPtr = EventExtTriggerBufferPool::ptr_type; EventCDBufferPool cd_buffer_pool_; EventCDBufferPtr cd_buffer_ptr_; EventExtTriggerBufferPool ext_trigger_buffer_pool_; @@ -57,4 +61,4 @@ class EventFileWriter::Private { } // namespace Metavision -#endif /* METAVISION_SDK_DRIVER_EVENT_FILE_WRITER_INTERNAL_H */ \ No newline at end of file +#endif /* METAVISION_SDK_STREAM_EVENT_FILE_WRITER_INTERNAL_H */ diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/ext_trigger_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/ext_trigger_internal.h similarity index 90% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/ext_trigger_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/ext_trigger_internal.h index d5fcc9237..b9472e9c8 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/ext_trigger_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/ext_trigger_internal.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_EXT_TRIGGER_INTERNAL_H -#define METAVISION_SDK_DRIVER_EXT_TRIGGER_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_EXT_TRIGGER_INTERNAL_H +#define METAVISION_SDK_STREAM_EXT_TRIGGER_INTERNAL_H #include #include @@ -31,4 +31,4 @@ class ExtTrigger::Private : public CallbackManager { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_EXT_TRIGGER_INTERNAL_H +#endif // METAVISION_SDK_STREAM_EXT_TRIGGER_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/frame_diff_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/frame_diff_internal.h similarity index 90% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/frame_diff_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/frame_diff_internal.h index c346ecf65..ebb9236b1 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/frame_diff_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/frame_diff_internal.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_FRAME_DIFF_INTERNAL_H -#define METAVISION_SDK_DRIVER_FRAME_DIFF_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_FRAME_DIFF_INTERNAL_H +#define METAVISION_SDK_STREAM_FRAME_DIFF_INTERNAL_H #include "metavision/sdk/core/utils/callback_manager.h" @@ -29,4 +29,4 @@ class FrameDiff::Private : public CallbackManager { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_FRAME_DIFF_INTERNAL_H +#endif // METAVISION_SDK_STREAM_FRAME_DIFF_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/frame_histo_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/frame_histo_internal.h similarity index 90% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/frame_histo_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/frame_histo_internal.h index 3f80cbbe3..ad28421c1 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/frame_histo_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/frame_histo_internal.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_FRAME_HISTO_INTERNAL_H -#define METAVISION_SDK_DRIVER_FRAME_HISTO_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_FRAME_HISTO_INTERNAL_H +#define METAVISION_SDK_STREAM_FRAME_HISTO_INTERNAL_H #include "metavision/sdk/core/utils/callback_manager.h" @@ -29,4 +29,4 @@ class FrameHisto::Private : public CallbackManager { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_FRAME_HISTO_INTERNAL_H +#endif // METAVISION_SDK_STREAM_FRAME_HISTO_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/offline_streaming_control_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/offline_streaming_control_internal.h similarity index 87% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/offline_streaming_control_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/offline_streaming_control_internal.h index f3281ce2b..acd3dcd70 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/offline_streaming_control_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/offline_streaming_control_internal.h @@ -9,10 +9,10 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_OFFLINE_STREAMING_CONTROL_INTERNAL_H -#define METAVISION_SDK_DRIVER_OFFLINE_STREAMING_CONTROL_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_OFFLINE_STREAMING_CONTROL_INTERNAL_H +#define METAVISION_SDK_STREAM_OFFLINE_STREAMING_CONTROL_INTERNAL_H -#include "metavision/sdk/driver/camera.h" +#include "metavision/sdk/stream/camera.h" namespace Metavision { @@ -36,4 +36,4 @@ class OfflineStreamingControl::Private { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_OFFLINE_STREAMING_CONTROL_INTERNAL_H +#endif // METAVISION_SDK_STREAM_OFFLINE_STREAMING_CONTROL_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/raw_data_internal.h b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/raw_data_internal.h similarity index 91% rename from sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/raw_data_internal.h rename to sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/raw_data_internal.h index 741f8a10d..3560720d7 100644 --- a/sdk/modules/driver/cpp/src/include/metavision/sdk/driver/internal/raw_data_internal.h +++ b/sdk/modules/stream/cpp/src/include/metavision/sdk/stream/internal/raw_data_internal.h @@ -9,8 +9,8 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#ifndef METAVISION_SDK_DRIVER_RAW_DATA_INTERNAL_H -#define METAVISION_SDK_DRIVER_RAW_DATA_INTERNAL_H +#ifndef METAVISION_SDK_STREAM_RAW_DATA_INTERNAL_H +#define METAVISION_SDK_STREAM_RAW_DATA_INTERNAL_H #include #include @@ -31,4 +31,4 @@ class RawData::Private : public CallbackManager { } // namespace Metavision -#endif // METAVISION_SDK_DRIVER_RAW_DATA_INTERNAL_H +#endif // METAVISION_SDK_STREAM_RAW_DATA_INTERNAL_H diff --git a/sdk/modules/driver/cpp/src/offline_streaming_control.cpp b/sdk/modules/stream/cpp/src/offline_streaming_control.cpp similarity index 91% rename from sdk/modules/driver/cpp/src/offline_streaming_control.cpp rename to sdk/modules/stream/cpp/src/offline_streaming_control.cpp index c340bacd6..09d625129 100644 --- a/sdk/modules/driver/cpp/src/offline_streaming_control.cpp +++ b/sdk/modules/stream/cpp/src/offline_streaming_control.cpp @@ -11,11 +11,11 @@ #include "metavision/hal/facilities/i_events_stream.h" #include "metavision/hal/utils/raw_file_config.h" -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/internal/camera_internal.h" -#include "metavision/sdk/driver/event_file_reader.h" -#include "metavision/sdk/driver/offline_streaming_control.h" -#include "metavision/sdk/driver/internal/offline_streaming_control_internal.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/camera_internal.h" +#include "metavision/sdk/stream/event_file_reader.h" +#include "metavision/sdk/stream/offline_streaming_control.h" +#include "metavision/sdk/stream/internal/offline_streaming_control_internal.h" #include namespace Metavision { diff --git a/sdk/modules/driver/cpp/src/protobuf/CMakeLists.txt b/sdk/modules/stream/cpp/src/protobuf/CMakeLists.txt similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/CMakeLists.txt rename to sdk/modules/stream/cpp/src/protobuf/CMakeLists.txt diff --git a/sdk/modules/driver/cpp/src/protobuf/antiflicker_state.proto b/sdk/modules/stream/cpp/src/protobuf/antiflicker_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/antiflicker_state.proto rename to sdk/modules/stream/cpp/src/protobuf/antiflicker_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/camera_synchronization_state.proto b/sdk/modules/stream/cpp/src/protobuf/camera_synchronization_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/camera_synchronization_state.proto rename to sdk/modules/stream/cpp/src/protobuf/camera_synchronization_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/device_state.proto b/sdk/modules/stream/cpp/src/protobuf/device_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/device_state.proto rename to sdk/modules/stream/cpp/src/protobuf/device_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/digital_crop_state.proto b/sdk/modules/stream/cpp/src/protobuf/digital_crop_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/digital_crop_state.proto rename to sdk/modules/stream/cpp/src/protobuf/digital_crop_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/digital_event_mask_state.proto b/sdk/modules/stream/cpp/src/protobuf/digital_event_mask_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/digital_event_mask_state.proto rename to sdk/modules/stream/cpp/src/protobuf/digital_event_mask_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/event_rate_activity_filter_state.proto b/sdk/modules/stream/cpp/src/protobuf/event_rate_activity_filter_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/event_rate_activity_filter_state.proto rename to sdk/modules/stream/cpp/src/protobuf/event_rate_activity_filter_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/event_rate_control_state.proto b/sdk/modules/stream/cpp/src/protobuf/event_rate_control_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/event_rate_control_state.proto rename to sdk/modules/stream/cpp/src/protobuf/event_rate_control_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/event_trail_filter_state.proto b/sdk/modules/stream/cpp/src/protobuf/event_trail_filter_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/event_trail_filter_state.proto rename to sdk/modules/stream/cpp/src/protobuf/event_trail_filter_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/hw_register_state.proto b/sdk/modules/stream/cpp/src/protobuf/hw_register_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/hw_register_state.proto rename to sdk/modules/stream/cpp/src/protobuf/hw_register_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/ll_biases_state.proto b/sdk/modules/stream/cpp/src/protobuf/ll_biases_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/ll_biases_state.proto rename to sdk/modules/stream/cpp/src/protobuf/ll_biases_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/region_of_interest_state.proto b/sdk/modules/stream/cpp/src/protobuf/region_of_interest_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/region_of_interest_state.proto rename to sdk/modules/stream/cpp/src/protobuf/region_of_interest_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/trigger_in_state.proto b/sdk/modules/stream/cpp/src/protobuf/trigger_in_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/trigger_in_state.proto rename to sdk/modules/stream/cpp/src/protobuf/trigger_in_state.proto diff --git a/sdk/modules/driver/cpp/src/protobuf/trigger_out_state.proto b/sdk/modules/stream/cpp/src/protobuf/trigger_out_state.proto similarity index 100% rename from sdk/modules/driver/cpp/src/protobuf/trigger_out_state.proto rename to sdk/modules/stream/cpp/src/protobuf/trigger_out_state.proto diff --git a/sdk/modules/driver/cpp/src/raw_data.cpp b/sdk/modules/stream/cpp/src/raw_data.cpp similarity index 92% rename from sdk/modules/driver/cpp/src/raw_data.cpp rename to sdk/modules/stream/cpp/src/raw_data.cpp index 0d2f05724..91a4f22a4 100644 --- a/sdk/modules/driver/cpp/src/raw_data.cpp +++ b/sdk/modules/stream/cpp/src/raw_data.cpp @@ -9,11 +9,11 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/raw_data.h" +#include "metavision/sdk/stream/raw_data.h" #include "metavision/sdk/core/utils/index_manager.h" -#include "metavision/sdk/driver/internal/raw_data_internal.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/internal/raw_data_internal.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" namespace Metavision { diff --git a/sdk/modules/driver/cpp/src/raw_event_file_writer.cpp b/sdk/modules/stream/cpp/src/raw_event_file_logger.cpp similarity index 82% rename from sdk/modules/driver/cpp/src/raw_event_file_writer.cpp rename to sdk/modules/stream/cpp/src/raw_event_file_logger.cpp index b8d70874b..8acc8bf56 100644 --- a/sdk/modules/driver/cpp/src/raw_event_file_writer.cpp +++ b/sdk/modules/stream/cpp/src/raw_event_file_logger.cpp @@ -18,15 +18,15 @@ #include "metavision/hal/facilities/i_hw_identification.h" #include "metavision/hal/utils/raw_file_header.h" -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/internal/event_file_writer_internal.h" -#include "metavision/sdk/driver/raw_event_file_writer.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/event_file_writer_internal.h" +#include "metavision/sdk/stream/raw_event_file_logger.h" namespace Metavision { -class RAWEventFileWriter::Private { +class RAWEventFileLogger::Private { public: - Private(RAWEventFileWriter &writer, const std::string &path, + Private(RAWEventFileLogger &writer, const std::filesystem::path &path, const std::unordered_map &metadata_map) : writer_(writer), header_written_(false) { if (!path.empty()) { @@ -41,10 +41,10 @@ class RAWEventFileWriter::Private { return static_cast(writer_).get_pimpl(); } - void open_impl(const std::string &path) { + void open_impl(const std::filesystem::path &path) { ofs_ = std::ofstream(path, std::ios::binary); if (!ofs_.is_open()) { - throw std::runtime_error("Unable to open " + path + " for writing"); + throw std::runtime_error("Unable to open " + path.string() + " for writing"); } raw_data_buffer_ptr_ = raw_data_buffer_pool_.acquire(); } @@ -132,7 +132,7 @@ class RAWEventFileWriter::Private { return true; } - RAWEventFileWriter &writer_; + RAWEventFileLogger &writer_; RawFileHeader header_; std::ofstream ofs_; bool header_written_; @@ -144,51 +144,51 @@ class RAWEventFileWriter::Private { RawDataBufferPtr raw_data_buffer_ptr_; }; -RAWEventFileWriter::RAWEventFileWriter(const std::string &path, - const std::unordered_map &metadata_map) : +RAWEventFileLogger::RAWEventFileLogger(const std::filesystem::path &path, + const std::unordered_map &metadata_map) : EventFileWriter(path), pimpl_(new Private(*this, path, metadata_map)) {} -RAWEventFileWriter::~RAWEventFileWriter() { +RAWEventFileLogger::~RAWEventFileLogger() { close(); } -void RAWEventFileWriter::open_impl(const std::string &path) { +void RAWEventFileLogger::open_impl(const std::filesystem::path &path) { pimpl_->open_impl(path); } -void RAWEventFileWriter::close_impl() { +void RAWEventFileLogger::close_impl() { pimpl_->close_impl(); } -bool RAWEventFileWriter::is_open_impl() const { +bool RAWEventFileLogger::is_open_impl() const { return pimpl_->is_open_impl(); } -void RAWEventFileWriter::add_metadata_impl(const std::string &key, const std::string &value) { +void RAWEventFileLogger::add_metadata_impl(const std::string &key, const std::string &value) { pimpl_->add_metadata_impl(key, value); } -void RAWEventFileWriter::add_metadata_map_from_camera_impl(const Camera &camera) { +void RAWEventFileLogger::add_metadata_map_from_camera_impl(const Camera &camera) { pimpl_->add_metadata_map_from_camera_impl(camera); } -void RAWEventFileWriter::remove_metadata_impl(const std::string &key) { +void RAWEventFileLogger::remove_metadata_impl(const std::string &key) { pimpl_->remove_metadata_impl(key); } -bool RAWEventFileWriter::add_events_impl(const EventCD *begin, const EventCD *end) { +bool RAWEventFileLogger::add_events_impl(const EventCD *begin, const EventCD *end) { throw std::runtime_error("RAW does not support writing decoded events"); } -bool RAWEventFileWriter::add_events_impl(const EventExtTrigger *begin, const EventExtTrigger *end) { +bool RAWEventFileLogger::add_events_impl(const EventExtTrigger *begin, const EventExtTrigger *end) { throw std::runtime_error("RAW does not support writing decoded events"); } -bool RAWEventFileWriter::add_raw_data(const std::uint8_t *ptr, size_t size) { +bool RAWEventFileLogger::add_raw_data(const std::uint8_t *ptr, size_t size) { return pimpl_->add_raw_data(ptr, size); } -void RAWEventFileWriter::flush_impl() { +void RAWEventFileLogger::flush_impl() { return pimpl_->flush_impl(); } diff --git a/sdk/modules/driver/cpp/src/raw_event_file_reader.cpp b/sdk/modules/stream/cpp/src/raw_event_file_reader.cpp similarity index 96% rename from sdk/modules/driver/cpp/src/raw_event_file_reader.cpp rename to sdk/modules/stream/cpp/src/raw_event_file_reader.cpp index fead35264..7e3eb925c 100644 --- a/sdk/modules/driver/cpp/src/raw_event_file_reader.cpp +++ b/sdk/modules/stream/cpp/src/raw_event_file_reader.cpp @@ -14,9 +14,9 @@ #include "metavision/hal/facilities/i_events_stream_decoder.h" #include "metavision/hal/facilities/i_hw_identification.h" #include "metavision/sdk/base/utils/generic_header.h" -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/internal/event_file_reader_internal.h" -#include "metavision/sdk/driver/raw_event_file_reader.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/event_file_reader_internal.h" +#include "metavision/sdk/stream/raw_event_file_reader.h" namespace Metavision { @@ -119,8 +119,8 @@ class RAWEventFileReader::Private { } if (i_events_stream_) { data_buffer_ = i_events_stream_->get_latest_raw_data(); - raw_data_cur_ptr_ = data_buffer_->data(); - raw_data_end_ptr_ = data_buffer_->data() + data_buffer_->size(); + raw_data_cur_ptr_ = data_buffer_.data(); + raw_data_end_ptr_ = data_buffer_.end(); } } @@ -225,11 +225,11 @@ class RAWEventFileReader::Private { I_EventsStream *i_events_stream_ = nullptr; I_EventsStreamDecoder *i_events_stream_decoder_ = nullptr; I_Decoder *i_decoder_ = nullptr; - DataTransfer::BufferPtr data_buffer_ = nullptr; - std::uint8_t *raw_data_cur_ptr_ = nullptr, *raw_data_end_ptr_ = nullptr; + DataTransfer::BufferPtr data_buffer_; + const std::uint8_t *raw_data_cur_ptr_ = nullptr, *raw_data_end_ptr_ = nullptr; }; -RAWEventFileReader::RAWEventFileReader(Device &device, const std::string &path) : +RAWEventFileReader::RAWEventFileReader(Device &device, const std::filesystem::path &path) : EventFileReader(path), pimpl_(new Private(*this, device)) {} RAWEventFileReader::~RAWEventFileReader() {} diff --git a/sdk/modules/stream/cpp/src/raw_evt2_event_file_writer.cpp b/sdk/modules/stream/cpp/src/raw_evt2_event_file_writer.cpp new file mode 100644 index 000000000..b3b0be274 --- /dev/null +++ b/sdk/modules/stream/cpp/src/raw_evt2_event_file_writer.cpp @@ -0,0 +1,204 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/hal/decoders/evt2/evt2_encoder.h" +#include "metavision/sdk/base/utils/sdk_log.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/event_file_writer_internal.h" +#include "metavision/sdk/stream/raw_evt2_event_file_writer.h" + +namespace Metavision { + +RAWEvt2EventFileWriter::RAWEvt2EventFileWriter(int stream_width, int stream_height, const std::filesystem::path &path, + bool enable_trigger_support, + const std::unordered_map &metadata_map, + timestamp max_events_add_latency) : + EventFileWriter(path.string()), + exttrigger_support_enabled_(enable_trigger_support), + max_events_add_latency_(max_events_add_latency <= 0 ? std::numeric_limits::max() : + max_events_add_latency), + encoder_(std::make_unique()) { + get_pimpl().set_max_event_trigger_buffer_size(1); + if (!path.empty()) { + open_impl(path); + } + for (auto &p : metadata_map) { + add_metadata_impl(p.first, p.second); + } + std::stringstream ss; + ss << "EVT2;width=" << stream_width << ";height=" << stream_height; + add_metadata_impl("format", ss.str()); + add_metadata_impl("camera_integrator_name", "MetavisionSDK"); + add_metadata_impl("plugin_integrator_name", "MetavisionSDK"); + header_.add_date(); +} + +RAWEvt2EventFileWriter::~RAWEvt2EventFileWriter() { + if (is_open_impl()) { + close(); + } +} + +void RAWEvt2EventFileWriter::open_impl(const std::filesystem::path &path) { + if (is_open_impl()) { + close_impl(); + } + ofs_ = std::ofstream(path, std::ios::binary); + if (!ofs_.is_open()) { + std::stringstream ss; + ss << "[RAWEvt2EventFileWriter] Unable to open " << path << " for writing"; + MV_SDK_LOG_ERROR() << ss.str(); + throw std::runtime_error(ss.str()); + } +} + +void RAWEvt2EventFileWriter::close_impl() { + if (!header_written_) { + ofs_ << header_; + header_written_ = true; + } + encode_buffered_events(true); + ofs_.close(); +} + +bool RAWEvt2EventFileWriter::is_open_impl() const { + return ofs_.is_open(); +} + +void RAWEvt2EventFileWriter::add_metadata_impl(const std::string &key, const std::string &value) { + if (header_written_) { + MV_SDK_LOG_ERROR() << "[RAWEvt2EventFileWriter] Unable to modify metadata in RAW once data has been added"; + throw std::runtime_error("Unable to modify metadata in RAW once data has been added"); + } + header_.set_field(key, value); +} + +void RAWEvt2EventFileWriter::add_metadata_map_from_camera_impl(const Camera &camera) { + MV_SDK_LOG_ERROR() << "[RAWEvt2EventFileWriter] add_metadata_map_from_camera is not supported!"; + throw std::runtime_error("add_metadata_map_from_camera is not supported!"); +} + +void RAWEvt2EventFileWriter::remove_metadata_impl(const std::string &key) { + if (header_written_) { + MV_SDK_LOG_ERROR() << "[RAWEvt2EventFileWriter] Unable to modify metadata in RAW once data has been added"; + throw std::runtime_error("Unable to modify metadata in RAW once data has been added"); + } + header_.remove_field(key); +} + +bool RAWEvt2EventFileWriter::add_events_impl(const EventCD *begin, const EventCD *end) { + if (!is_open_impl()) { + MV_SDK_LOG_ERROR() << "[RAWEvt2EventFileWriter] File writer is not open, ignoring input events"; + return false; + } + if (begin != end) { + events_cd_.insert(events_cd_.end(), begin, end); + ts_last_cd_ = std::prev(end)->t; + encode_buffered_events(false); + } + return true; +} + +bool RAWEvt2EventFileWriter::add_events_impl(const EventExtTrigger *begin, const EventExtTrigger *end) { + if (!exttrigger_support_enabled_) { + MV_SDK_LOG_ERROR() + << "[RAWEvt2EventFileWriter] External trigger support is not enabled, ignoring input trigger events"; + return false; + } + if (!is_open_impl()) { + MV_SDK_LOG_ERROR() << "[RAWEvt2EventFileWriter] File writer is not open, ignoring input events"; + return false; + } + if (begin != end) { + events_trigger_.insert(events_trigger_.end(), begin, end); + ts_last_trigger_ = std::prev(end)->t; + encode_buffered_events(false); + } + return true; +} + +void RAWEvt2EventFileWriter::flush_impl() { + if (!is_open_impl()) { + return; + } + std::atomic done{false}; + get_pimpl().writer_thread_.add_task([&done, this]() { + encode_buffered_events(false); + ofs_.flush(); + done = true; + }); + while (!done) { + std::this_thread::yield(); + } +} + +void RAWEvt2EventFileWriter::encode_buffered_events(bool flush_all_queued_events) { + if (!header_written_) { + ofs_ << header_; + header_written_ = true; + } + if (exttrigger_support_enabled_) { + merge_encode_buffered_events(flush_all_queued_events); + } else { + for (const auto &ev : events_cd_) { + encoder_->encode_event_cd(ofs_, ev); + } + events_cd_.clear(); + } +} + +void RAWEvt2EventFileWriter::merge_encode_buffered_events(bool flush_all_queued_events) { + timestamp ts_encode_up_to; + if (flush_all_queued_events) { + ts_encode_up_to = std::numeric_limits::max(); + } else if (max_events_add_latency_ == std::numeric_limits::max()) { + ts_encode_up_to = std::min(ts_last_cd_, ts_last_trigger_); + } else { + const timestamp ts_last = std::max(ts_last_cd_, ts_last_trigger_); + ts_encode_up_to = ts_last < std::numeric_limits::min() + max_events_add_latency_ ? + std::numeric_limits::min() : + ts_last - max_events_add_latency_; + } + auto it_cd = events_cd_.begin(), + it_cd_end = std::lower_bound(events_cd_.begin(), events_cd_.end(), ts_encode_up_to, + [](const EventCD &ev, timestamp ts) { return ev.t < ts; }); + auto it_trigger = events_trigger_.begin(), + it_trigger_end = std::lower_bound(events_trigger_.begin(), events_trigger_.end(), ts_encode_up_to, + [](const EventExtTrigger &ev, timestamp ts) { return ev.t < ts; }); + + while (it_cd != it_cd_end || it_trigger != it_trigger_end) { + if (it_cd != it_cd_end && it_trigger != it_trigger_end) { + if (it_cd->t < it_trigger->t) { + encoder_->encode_event_cd(ofs_, *it_cd); + ++it_cd; + } else { + encoder_->encode_event_trigger(ofs_, *it_trigger); + ++it_trigger; + } + } else if (it_cd != it_cd_end) { + encoder_->encode_event_cd(ofs_, *it_cd); + ++it_cd; + } else { + encoder_->encode_event_trigger(ofs_, *it_trigger); + ++it_trigger; + } + } + events_cd_.erase(events_cd_.begin(), it_cd_end); + events_trigger_.erase(events_trigger_.begin(), it_trigger_end); +} + +} // namespace Metavision diff --git a/sdk/modules/driver/cpp/tests/CMakeLists.txt b/sdk/modules/stream/cpp/tests/CMakeLists.txt similarity index 64% rename from sdk/modules/driver/cpp/tests/CMakeLists.txt rename to sdk/modules/stream/cpp/tests/CMakeLists.txt index ab680a624..0861e73e0 100644 --- a/sdk/modules/driver/cpp/tests/CMakeLists.txt +++ b/sdk/modules/stream/cpp/tests/CMakeLists.txt @@ -7,58 +7,57 @@ # 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(metavision_sdk_driver_tests_srcs - ${CMAKE_CURRENT_SOURCE_DIR}/biases_gtest.cpp +set(metavision_sdk_stream_tests_srcs + ${CMAKE_CURRENT_SOURCE_DIR}/raw_evt2_event_file_writer_gtest.cpp ) if (HDF5_FOUND) - list(APPEND metavision_sdk_driver_tests_srcs + list(APPEND metavision_sdk_stream_tests_srcs ${CMAKE_CURRENT_SOURCE_DIR}/event_file_reader_writer_gtest.cpp ) endif () -add_executable(gtest_metavision_sdk_driver ${metavision_sdk_driver_tests_srcs}) +add_executable(gtest_metavision_sdk_stream ${metavision_sdk_stream_tests_srcs}) if (HDF5_FOUND) - target_compile_definitions(gtest_metavision_sdk_driver + target_compile_definitions(gtest_metavision_sdk_stream PRIVATE HAS_HDF5 ${HDF5_DEFINITIONS} ${HDF5_CXX_DEFINITIONS} ) - target_include_directories(gtest_metavision_sdk_driver + target_include_directories(gtest_metavision_sdk_stream PRIVATE ${HDF5_INCLUDE_DIRS} ) - target_link_libraries(gtest_metavision_sdk_driver + target_link_libraries(gtest_metavision_sdk_stream PRIVATE - ${HDF5_LIBRARIES} + ${HDF5_LIBRARIES} hdf5_ecf_codec ) endif () -target_link_libraries(gtest_metavision_sdk_driver +target_link_libraries(gtest_metavision_sdk_stream PRIVATE - MetavisionSDK::driver + MetavisionSDK::stream MetavisionUtils::gtest-main - Boost::filesystem ) if (TARGET metavision_hal_gtest_utils) - target_sources(gtest_metavision_sdk_driver PRIVATE + target_sources(gtest_metavision_sdk_stream PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/camera_generation_gtest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/camera_stage_gtest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/camera_stream_slicer_gtest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/camera_gtest.cpp # TODO : remove this, we should not have to link with this file, it's only used # in the camera gtest because we need functions that are not yet part of HAL I_ROI API ${PROJECT_SOURCE_DIR}/hal/cpp/test/dummy_test_plugin_facilities_builder.cpp ) - target_link_libraries(gtest_metavision_sdk_driver PRIVATE metavision_hal_gtest_utils) + target_link_libraries(gtest_metavision_sdk_stream PRIVATE metavision_hal_gtest_utils) endif (TARGET metavision_hal_gtest_utils) -add_dependencies(gtest_metavision_sdk_driver hal_dummy_test_plugin) +add_dependencies(gtest_metavision_sdk_stream hal_dummy_test_plugin) # Until we execute ctest in docker on Windows, the embedded paths to resources used in the code # can not be absolute. Here the path is relative to the working directory of the test (which is the # current binary dir). -target_compile_definitions(gtest_metavision_sdk_driver PRIVATE HAL_DUMMY_TEST_PLUGIN="${CMAKE_CURRENT_BINARY_DIR}/../../../../../hal/cpp/test/plugins") +target_compile_definitions(gtest_metavision_sdk_stream PRIVATE HAL_DUMMY_TEST_PLUGIN="${CMAKE_CURRENT_BINARY_DIR}/../../../../../hal/cpp/test/plugins") if(USE_PROTOBUF) find_package(Protobuf CONFIG QUIET) @@ -67,13 +66,13 @@ if(USE_PROTOBUF) endif(NOT Protobuf_FOUND) if (Protobuf_FOUND) - target_compile_definitions(gtest_metavision_sdk_driver PRIVATE HAS_PROTOBUF) + target_compile_definitions(gtest_metavision_sdk_stream PRIVATE HAS_PROTOBUF) endif() endif(USE_PROTOBUF) -target_include_directories(gtest_metavision_sdk_driver PRIVATE - ${PROJECT_SOURCE_DIR}/sdk/modules/driver/cpp/src/include +target_include_directories(gtest_metavision_sdk_stream PRIVATE + ${PROJECT_SOURCE_DIR}/sdk/modules/stream/cpp/src/include ${GENERATE_FILES_DIRECTORY} ) -register_gtest(TEST sdk-driver-unit-tests TARGET gtest_metavision_sdk_driver) \ No newline at end of file +register_gtest(TEST sdk-stream-unit-tests TARGET gtest_metavision_sdk_stream) diff --git a/sdk/modules/driver/cpp/tests/camera_generation_gtest.cpp b/sdk/modules/stream/cpp/tests/camera_generation_gtest.cpp similarity index 93% rename from sdk/modules/driver/cpp/tests/camera_generation_gtest.cpp rename to sdk/modules/stream/cpp/tests/camera_generation_gtest.cpp index 878171099..a778bc55b 100644 --- a/sdk/modules/driver/cpp/tests/camera_generation_gtest.cpp +++ b/sdk/modules/stream/cpp/tests/camera_generation_gtest.cpp @@ -9,12 +9,12 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include +#include #include "metavision/utils/gtest/gtest_custom.h" -#include "metavision/sdk/driver/camera_generation.h" -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/internal/camera_generation_internal.h" +#include "metavision/sdk/stream/camera_generation.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/camera_generation_internal.h" using namespace Metavision; @@ -30,8 +30,8 @@ class CameraGeneration_GTest : public ::testing::Test { virtual void TearDown() override {} void run_test(const std::string &file_basename, short version_major_expected, short version_minor_expected) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / file_basename).string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / file_basename; Camera camera; diff --git a/sdk/modules/driver/cpp/tests/camera_gtest.cpp b/sdk/modules/stream/cpp/tests/camera_gtest.cpp similarity index 86% rename from sdk/modules/driver/cpp/tests/camera_gtest.cpp rename to sdk/modules/stream/cpp/tests/camera_gtest.cpp index f7282fcdd..58d5952d1 100644 --- a/sdk/modules/driver/cpp/tests/camera_gtest.cpp +++ b/sdk/modules/stream/cpp/tests/camera_gtest.cpp @@ -9,40 +9,44 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include #include #include #include +#include #include -#include #include +#include #include // std::iota #include #include #include "metavision/hal/device/device_discovery.h" +#include "metavision/hal/facilities/i_antiflicker_module.h" #include "metavision/hal/facilities/i_camera_synchronization.h" #include "metavision/hal/facilities/i_digital_crop.h" #include "metavision/hal/facilities/i_digital_event_mask.h" +#include "metavision/hal/facilities/i_erc_module.h" #include "metavision/hal/facilities/i_event_rate_activity_filter_module.h" +#include "metavision/hal/facilities/i_event_trail_filter_module.h" #include "metavision/hal/facilities/i_events_stream_decoder.h" #include "metavision/hal/facilities/i_hw_register.h" +#include "metavision/hal/facilities/i_ll_biases.h" +#include "metavision/hal/facilities/i_roi.h" #include "metavision/hal/facilities/i_trigger_in.h" #include "metavision/hal/facilities/i_trigger_out.h" #include "metavision/hal/utils/raw_file_header.h" #include "metavision/sdk/base/utils/timestamp.h" -#include "metavision/sdk/driver/camera_error_code.h" +#include "metavision/sdk/stream/camera_error_code.h" #include "metavision/utils/gtest/gtest_with_tmp_dir.h" #include "metavision/utils/gtest/gtest_custom.h" #include "metavision/sdk/core/utils/callback_manager.h" -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/internal/camera_internal.h" -#include "metavision/sdk/driver/internal/callback_tag_ids.h" -#include "metavision/sdk/driver/camera_exception.h" -#include "metavision/sdk/driver/internal/camera_error_code_internal.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/internal/camera_internal.h" +#include "metavision/sdk/stream/internal/callback_tag_ids.h" +#include "metavision/sdk/stream/camera_exception.h" +#include "metavision/sdk/stream/internal/camera_error_code_internal.h" #include "encoding_policies.h" #include "tencoder_gtest_common.h" -#include "device_builder_maker.h" using namespace Metavision; @@ -69,16 +73,16 @@ class Camera_Gtest : public GTestWithTmpDir { } RawFileHeader get_default_header(bool evt2 = true) { - RawFileHeader header_to_write; - header_to_write.set_plugin_name(evt2 ? "hal_plugin_gen31_fx3" : "hal_plugin_gen4_fx3"); - header_to_write.set_plugin_integrator_name("Prophesee"); - header_to_write.set_camera_integrator_name("Prophesee"); - header_to_write.set_field("serial_number", dummy_serial_); + auto header = std::stringstream(); + header << "% date 2014-02-28 13:37:42\n" + << "% camera_integrator_name Prophesee\n" + << "% plugin_integrator_name Prophesee\n" + << "% plugin_name hal_plugin_prophesee\n" + << "% format " << std::string(evt2?"EVT2":"EVT3") << ";height=720;width=1280\n" + << "% serial_number " << dummy_serial_ << '\n' + << "% end\n"; - // Prophesee header only. Duplicated what PropheseeRawHeader does to be able to encode then read test RAW - // file - header_to_write.set_field("system_ID", std::to_string(dummy_system_id)); - return header_to_write; + return RawFileHeader(header); } void open_file() { @@ -130,7 +134,7 @@ class Camera_Gtest : public GTestWithTmpDir { std::pair, std::vector> write_evt2_raw_data_with_trigger() { static bool written = false; - static std::string evt2_file_name; + static std::filesystem::path evt2_file_name; static std::pair, std::vector> data; if (written) { tmp_file_ = evt2_file_name; @@ -150,14 +154,13 @@ class Camera_Gtest : public GTestWithTmpDir { enum class DatasetFileType { RAW = 1 << 0, HDF5 = 1 << 1, ALL = 1 << 0 | 1 << 1 }; - std::vector get_datasets_paths(DatasetFileType type) { - std::vector datasets; + std::vector get_datasets_paths(DatasetFileType type) { + std::vector datasets; if (static_cast(type) & static_cast(DatasetFileType::RAW)) { for (const auto &p : {"gen31_timer.raw", "gen4_evt2_hand.raw", "gen4_evt3_hand.raw", "blinking_gen4_with_ext_triggers.raw", "claque_doigt_evt21.raw", "standup_evt21-legacy.raw"}) { - datasets.push_back( - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / p).string()); + datasets.push_back(std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / p); } } #ifdef HAS_HDF5 @@ -165,25 +168,20 @@ class Camera_Gtest : public GTestWithTmpDir { for (const auto &p : {"gen31_timer.hdf5", "gen4_evt2_hand.hdf5", "gen4_evt3_hand.hdf5", "blinking_gen4_with_ext_triggers.hdf5", "claque_doigt_evt21.hdf5", "standup_evt21-legacy.hdf5"}) { - datasets.push_back( - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / p).string()); + datasets.push_back(std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / p); } } #endif return datasets; } - std::string tmp_file_; + std::filesystem::path tmp_file_; std::unique_ptr log_raw_data_; size_t bytes_written_{0}; static const std::string dummy_serial_; - static const std::string dummy_plugin_name_; - - static constexpr long dummy_system_id = 28; // Prophesee gen31 system id }; -constexpr long Camera_Gtest::dummy_system_id; const std::string Camera_Gtest::dummy_serial_ = "dummy_serial"; TEST_F_WITH_CAMERA(Camera_Gtest, available_online_sources) { @@ -225,12 +223,6 @@ TEST_F(Camera_Gtest, basic_exceptions) { FAIL(); } catch (CameraException &e) { ASSERT_EQ(e.code().value(), CameraErrorCode::CameraNotInitialized); } - try { - camera.biases().set_from_file(tmpdir_handler_->get_tmpdir_path() + ".bias"); - std::cout << "Should have thrown exception..." << std::endl; - FAIL(); - } catch (CameraException &e) { ASSERT_EQ(e.code().value(), CameraErrorCode::CameraNotInitialized); } - try { camera.raw_data().add_callback([](const uint8_t *data, size_t size) {}); std::cout << "Should have thrown exception..." << std::endl; @@ -264,28 +256,6 @@ TEST_F(Camera_Gtest, basic_exceptions_with_additional_info) { } catch (CameraException &e) { ASSERT_TRUE(std::string(e.what()).find(additional_info) != std::string::npos); } } -TEST_F_WITH_CAMERA(Camera_Gtest, camera_set_biases) { - ////////////////////////////////////////////////////// - // PURPOSE - // Checks that you can set biases from files - - Camera camera; - if (GtestsParameters::instance().serial.empty()) { - camera = Camera::from_first_available(); - } else { - camera = Camera::from_serial(GtestsParameters::instance().serial); - } - - try { - camera.biases().set_from_file("not_a_bias_file.yolo"); - std::cout << "Should have thrown exception..." << std::endl; - FAIL(); - } catch (CameraException &e) { - // internal errors should appear to the user as the main category error - ASSERT_NE(CameraErrorCode::InvalidArgument, e.code().value()); - } -} - TEST_F_WITHOUT_CAMERA(Camera_Gtest, no_camera_constructors) { try { Camera camera = Camera::from_first_available(); @@ -361,7 +331,7 @@ TEST_F_WITH_CAMERA(Camera_Gtest, camera_file_logger_some_events) { } camera.stop(); - ASSERT_TRUE(boost::filesystem::exists(file)); + ASSERT_TRUE(std::filesystem::exists(file)); ASSERT_NO_THROW(camera = Camera::from_file(file)); } @@ -406,7 +376,7 @@ TYPED_TEST_WITH_CAMERA(Camera_GtestT, camera_file_logger_n_events, } camera.stop(); - ASSERT_TRUE(boost::filesystem::exists(file)); + ASSERT_TRUE(std::filesystem::exists(file)); Metavision::FileConfigHints hints = Metavision::FileConfigHints().time_shift(TypeParam::do_time_shifting_); ASSERT_NO_THROW(camera = Camera::from_file(file, hints)); @@ -437,53 +407,25 @@ TEST_F(Camera_Gtest, raw_default_constructor) { } catch (CameraException &e) { ASSERT_EQ(e.code().value(), CameraErrorCode::FileDoesNotExist); } try { - std::ofstream file(tmp_file_ + ".fake"); + std::ofstream file(tmp_file_.string() + ".fake"); file.close(); - Camera camera = Camera::from_file(tmp_file_ + ".fake"); + Camera camera = Camera::from_file(tmp_file_.string() + ".fake"); std::cout << "Should have thrown exception..." << std::endl; FAIL(); } catch (CameraException &e) { ASSERT_EQ(e.code().value(), CameraErrorCode::WrongExtension); } - - try { - Camera camera = Camera::from_file(tmp_file_); - camera.biases().set_from_file(tmpdir_handler_->get_tmpdir_path() + ".bias"); // should throw exception - FAIL(); - } catch (CameraException &e) { - // internal errors should appear to the user as the main category error - ASSERT_NE(UnsupportedFeatureErrors::BiasesUnavailable, e.code().value()); - ASSERT_EQ(CameraErrorCode::UnsupportedFeature, e.code().value()); - - // but the real error code must appear in the camera exception message - ASSERT_TRUE(error_message_found_in_exception(UnsupportedFeatureErrors::BiasesUnavailable, e)); - } - - try { - Camera camera = Camera::from_file(tmp_file_); - camera.biases(); - std::cout << "Should have thrown exception..." << std::endl; - FAIL(); - } catch (CameraException &e) { - // internal errors should appear to the user as the main category error - ASSERT_NE(UnsupportedFeatureErrors::BiasesUnavailable, e.code().value()); - ASSERT_EQ(CameraErrorCode::UnsupportedFeature, e.code().value()); - - // but the real error code must appear in the camera exception message - ASSERT_TRUE(error_message_found_in_exception(UnsupportedFeatureErrors::BiasesUnavailable, e)); - } } TEST_F(Camera_Gtest, raw_file_logger_invalid_filename) { write_evt2_raw_data(); - std::string file = - (boost::filesystem::path(tmpdir_handler_->get_full_path("inexistent_directory")) / "Camera_Gtest_log.raw") - .string(); + std::filesystem::path file = + std::filesystem::path(tmpdir_handler_->get_full_path("inexistent_directory")) / "Camera_Gtest_log.raw"; Camera camera = Camera::from_file(tmp_file_); - ASSERT_FALSE(boost::filesystem::exists( - file)); // Just to check that the file does not exists already, otherwise it bias the test + // Just to check that the file does not exists already, otherwise it bias the test + ASSERT_FALSE(std::filesystem::exists(file)); // REMARK : file is an invalid filename because the directory tmpdir_ / - // boost::filesystem::path("inexistent_directory") does not exist + // std::filesystem::path("inexistent_directory") does not exist try { camera.start_recording(file); @@ -494,14 +436,14 @@ TEST_F(Camera_Gtest, raw_file_logger_invalid_filename) { EXPECT_EQ(e.code().value(), CameraErrorCode::CouldNotOpenFile); } - EXPECT_FALSE(boost::filesystem::exists(file)); + EXPECT_FALSE(std::filesystem::exists(file)); } TEST_F(Camera_Gtest, raw_file_logger_invalid_filename2) { write_evt2_raw_data(); std::string file = tmpdir_handler_->get_full_path("other_directory.raw"); - if (!boost::filesystem::create_directories(file)) { + if (!std::filesystem::create_directories(file)) { FAIL(); } Camera camera = Camera::from_file(tmp_file_); @@ -521,40 +463,39 @@ TEST_F(Camera_Gtest, raw_file_logger_permissions) { write_evt2_raw_data(); // Create a directory and set permissions - boost::filesystem::path tmpdir_perm = tmpdir_handler_->get_full_path("tmp_directory_permissions"); - if (!boost::filesystem::create_directory(tmpdir_perm)) { + std::filesystem::path tmpdir_perm = tmpdir_handler_->get_full_path("tmp_directory_permissions"); + if (!std::filesystem::create_directory(tmpdir_perm)) { FAIL(); } - boost::filesystem::path file = tmpdir_perm / boost::filesystem::path("Camera_Gtest_log.raw"); - ASSERT_FALSE(boost::filesystem::exists( - file)); // Just to check that the file does not exists already, otherwise it bias the test + std::filesystem::path file = tmpdir_perm / std::filesystem::path("Camera_Gtest_log.raw"); + // Just to check that the file does not exists already, otherwise it bias the test + ASSERT_FALSE(std::filesystem::exists(file)); Camera camera = Camera::from_file(tmp_file_); // First, before removing permissions, check that we could potentially write the file in the directory : ASSERT_NO_THROW(camera.start_recording(file.string())); - ASSERT_TRUE(boost::filesystem::exists(file)); + ASSERT_TRUE(std::filesystem::exists(file)); // Remove the file camera.stop_recording(); - ASSERT_TRUE(boost::filesystem::remove(file)); + ASSERT_TRUE(std::filesystem::remove(file)); // REMOVE PERMISSIONS FROM THE DIRECTORY - boost::filesystem::permissions(tmpdir_perm, boost::filesystem::perms::owner_all | - boost::filesystem::perms::group_all | - boost::filesystem::remove_perms); + std::filesystem::permissions(tmpdir_perm, std::filesystem::perms::owner_all | std::filesystem::perms::group_all, + std::filesystem::perm_options::remove); try { camera.start_recording(file.string()); camera.stop(); // On Windows, the file can be opened but can't be written to (i.e. no header at most) - EXPECT_EQ(0, boost::filesystem::file_size(file)); + EXPECT_EQ(0, std::filesystem::file_size(file)); } catch (CameraException &e) { EXPECT_EQ(e.code().value(), CameraErrorCode::CouldNotOpenFile); } // ADD BACK THE PERMISSIONS IN ORDER TO BE ABLE TO REMOVE THE DIRECTORY - boost::filesystem::permissions(tmpdir_perm, boost::filesystem::perms::owner_all | - boost::filesystem::perms::group_all | boost::filesystem::add_perms); + std::filesystem::permissions(tmpdir_perm, std::filesystem::perms::owner_all | std::filesystem::perms::group_all, + std::filesystem::perm_options::add); // Chek the file does not exists. WARNING : this check has to be done after adding the permissions back, otherwise - // an exception is thrown EXPECT_FALSE(boost::filesystem:: ::exists(file)); + // an exception is thrown EXPECT_FALSE(std::filesystem:: ::exists(file)); } TEST_F(Camera_Gtest, raw_file_logger) { @@ -571,7 +512,7 @@ TEST_F(Camera_Gtest, raw_file_logger) { camera.stop(); camera.stop_recording(); - ASSERT_TRUE(boost::filesystem::exists(file)); + ASSERT_TRUE(std::filesystem::exists(file)); } TEST_F(Camera_Gtest, start_stop) { @@ -654,32 +595,34 @@ TEST_F_WITH_CAMERA(Camera_Gtest, camera_succession_of_open_start_stop) { } TEST_F(Camera_Gtest, robust_start_stop) { - auto buffer = write_evt2_raw_data(); - + auto buffer = write_evt2_raw_data(); Metavision::FileConfigHints hints = Metavision::FileConfigHints().max_read_per_op(1 * 32); - Camera camera = Camera::from_file(tmp_file_, hints); - std::atomic wait(true); - std::atomic n_events_read(0); - camera.cd().add_callback([&wait, &n_events_read](const EventCD *begin, const EventCD *end) { - n_events_read += end - begin; - while (wait) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } + Camera camera = Camera::from_file(tmp_file_, hints); + + std::atomic_uint64_t n_events_read = 0; + std::condition_variable new_events; + std::mutex mutex; + + camera.cd().add_callback([&](const EventCD *begin, const EventCD *end) { + n_events_read += std::distance(begin, end); + new_events.notify_one(); }); - do { - uint32_t last_n_events_read = n_events_read; - wait = true; + + while (n_events_read < buffer.size()) { ASSERT_TRUE(camera.start()); ASSERT_TRUE(camera.is_running()); - while (n_events_read == last_n_events_read) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + { + std::unique_lock lock(mutex); + new_events.wait(lock); } - wait = false; + ASSERT_TRUE(camera.stop()); ASSERT_FALSE(camera.is_running()); - } while (n_events_read != buffer.size()); + } + + EXPECT_EQ(n_events_read, buffer.size()) << "Sould have decoded the same number of encoded envets"; } TEST_F_WITH_CAMERA(Camera_Gtest, camera_start_stop_keeps_callback) { @@ -961,14 +904,12 @@ TEST_F_WITHOUT_CAMERA(Camera_Gtest, roi_with_file) { Camera camera = Camera::from_file(tmp_file_); try { - camera.roi(); + camera.get_facility(); std::cout << "Should have thrown exception..." << std::endl; FAIL(); } catch (CameraException &e) { // internal errors should appear to the user as the main category error ASSERT_EQ(CameraErrorCode::UnsupportedFeature, e.code().value()); - // but the real error code must appear in the camera exception message - ASSERT_TRUE(error_message_found_in_exception(UnsupportedFeatureErrors::RoiUnavailable, e)); } } @@ -1010,7 +951,9 @@ TEST_F_WITH_CAMERA(Camera_Gtest, roi_with_camera) { }); ASSERT_TRUE(camera.start()); - ASSERT_NO_THROW(camera.roi().set({roi_x, roi_y, roi_width, roi_height})); + ASSERT_NO_THROW(camera.get_facility().set_window({roi_x, roi_y, roi_width, roi_height})); + ASSERT_NO_THROW(camera.get_facility().enable(true)); + // wait for the ROI to be set std::this_thread::sleep_for(std::chrono::seconds(1)); roi_set = true; @@ -1034,7 +977,8 @@ TEST_F_WITH_CAMERA(Camera_Gtest, roi_advanced_bitmap_fit_dimension_with_camera) camera = Camera::from_serial(GtestsParameters::instance().serial); } - std::vector rows_to_enable(camera.geometry().height(), true), cols_to_enable(camera.geometry().width(), true); + std::vector rows_to_enable(camera.geometry().get_height(), true); + std::vector cols_to_enable(camera.geometry().get_width(), true); std::vector rows_disabled(100, 0); std::vector cols_disabled(100, 0); @@ -1081,7 +1025,8 @@ TEST_F_WITH_CAMERA(Camera_Gtest, roi_advanced_bitmap_fit_dimension_with_camera) }); ASSERT_TRUE(camera.start()); - ASSERT_NO_THROW(camera.roi().set(cols_to_enable, rows_to_enable)); + ASSERT_NO_THROW(camera.get_facility().set_lines(cols_to_enable, rows_to_enable)); + ASSERT_NO_THROW(camera.get_facility().enable(true)); // wait for the ROI to be set std::this_thread::sleep_for(std::chrono::seconds(1)); roi_set = true; @@ -1092,26 +1037,6 @@ TEST_F_WITH_CAMERA(Camera_Gtest, roi_advanced_bitmap_fit_dimension_with_camera) ASSERT_TRUE(camera.stop()); } -TEST_F_WITH_CAMERA(Camera_Gtest, roi_advanced_bitmap_wrong_dimension_with_camera) { - ////////////////////////////////////////////////////// - // PURPOSE - // Checks that you can't set ROI from bitmap when these bitmaps don't have the correct dimensions - - Camera camera; - if (GtestsParameters::instance().serial.empty()) { - camera = Camera::from_first_available(); - } else { - camera = Camera::from_serial(GtestsParameters::instance().serial); - } - - ASSERT_TRUE(camera.start()); - try { - camera.roi().set({false}, {false}); // bool vector of size 1 - FAIL(); - } catch (CameraException &e) { ASSERT_EQ(e.code().value(), CameraErrorCode::RoiError); } - ASSERT_TRUE(camera.stop()); -} - TEST_F(Camera_Gtest, trigger_out_unsupported_with_file) { ////////////////////////////////////////////////////// // PURPOSE @@ -1119,22 +1044,21 @@ TEST_F(Camera_Gtest, trigger_out_unsupported_with_file) { write_evt2_raw_data(); Camera camera = Camera::from_file(tmp_file_); - ASSERT_THROW(camera.trigger_out(), CameraException); + ASSERT_THROW(camera.get_facility(), CameraException); try { - camera.trigger_out(); + camera.get_facility(); std::cerr << "Expected throw..." << std::endl; FAIL(); } catch (CameraException &e) { - ASSERT_TRUE( - error_message_found_in_exception(static_cast(UnsupportedFeatureErrors::TriggerOutUnavailable), e)); + ASSERT_TRUE(error_message_found_in_exception(static_cast(CameraErrorCode::UnsupportedFeature), e)); } } TEST_F(Camera_Gtest, test_afk_unsupported_on_rawfile) { write_evt2_raw_data(); Camera camera = Camera::from_file(tmp_file_); - ASSERT_THROW(camera.antiflicker_module(), CameraException); - ASSERT_THROW(camera.event_trail_filter_module(), CameraException); + ASSERT_THROW(camera.get_facility(), CameraException); + ASSERT_THROW(camera.get_facility(), CameraException); } TEST_F(Camera_Gtest, decode_evt2_data) { @@ -1172,9 +1096,8 @@ TEST_F(Camera_Gtest, decode_evt2_data) { TEST_F_WITH_DATASET(Camera_Gtest, decode_evt3_data) { // Read the dataset provided - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "blinking_gen4_with_ext_triggers.raw") - .string(); + std::filesystem::path dataset_file_path = std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / + "blinking_gen4_with_ext_triggers.raw"; Camera camera = Camera::from_file(dataset_file_path, FileConfigHints().real_time_playback(false)); @@ -1205,9 +1128,8 @@ TEST_F_WITH_DATASET(Camera_Gtest, decode_evt3_data) { #ifdef HAS_HDF5 TEST_F_WITH_DATASET(Camera_Gtest, decode_hdf5_data) { // Read the dataset provided - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "blinking_gen4_with_ext_triggers.hdf5") - .string(); + std::filesystem::path dataset_file_path = std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / + "blinking_gen4_with_ext_triggers.hdf5"; Camera camera = Camera::from_file(dataset_file_path, FileConfigHints().real_time_playback(false)); @@ -1236,8 +1158,8 @@ TEST_F_WITH_DATASET(Camera_Gtest, decode_hdf5_data) { TEST_F_WITH_DATASET(Camera_Gtest, decode_evt3_erccounter_data) { // Read the dataset provided - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen4_evt3_hand.raw"; Camera camera = Camera::from_file(dataset_file_path, FileConfigHints().real_time_playback(false)); @@ -1264,11 +1186,11 @@ TEST_F_WITH_DATASET(Camera_Gtest, decode_evt3_erccounter_data) { } TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_not_ready) { - std::vector datasets = get_datasets_paths(DatasetFileType::RAW); + std::vector datasets = get_datasets_paths(DatasetFileType::RAW); for (const auto &dataset : datasets) { - boost::filesystem::remove(dataset + "_index"); - ASSERT_FALSE(boost::filesystem::exists(dataset + "_index")); + std::filesystem::remove(dataset.string() + "_index"); + ASSERT_FALSE(std::filesystem::exists(dataset.string() + "_index")); // With this function, index building is not requested, so OSC is never ready Metavision::FileConfigHints hints; @@ -1284,11 +1206,11 @@ TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_not_ready) { } TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_ready_raw_files) { - std::vector datasets = get_datasets_paths(DatasetFileType::RAW); + std::vector datasets = get_datasets_paths(DatasetFileType::RAW); for (const auto &dataset : datasets) { - boost::filesystem::remove(dataset + "_index"); - ASSERT_FALSE(boost::filesystem::exists(dataset + "_index")); + std::filesystem::remove(dataset.string() + "_index"); + ASSERT_FALSE(std::filesystem::exists(dataset.string() + "_index")); // With this function, index building is requested, so OSC should be ready Camera camera = Camera::from_file(dataset); @@ -1309,7 +1231,7 @@ TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_ready_raw_files) { } TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_ready_hdf5_files) { - std::vector datasets = get_datasets_paths(DatasetFileType::HDF5); + std::vector datasets = get_datasets_paths(DatasetFileType::HDF5); for (const auto &dataset : datasets) { Metavision::FileConfigHints hints = Metavision::FileConfigHints().real_time_playback(false); @@ -1320,7 +1242,7 @@ TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_ready_hdf5_files) { } TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_seek_range) { - std::vector datasets = get_datasets_paths(DatasetFileType::ALL); + std::vector datasets = get_datasets_paths(DatasetFileType::ALL); std::vector> ranges; // RAW @@ -1350,7 +1272,7 @@ TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_seek_range) { } TEST_F_WITH_DATASET(Camera_Gtest, offline_streaming_control_seeks) { - std::vector datasets = get_datasets_paths(DatasetFileType::ALL); + std::vector datasets = get_datasets_paths(DatasetFileType::ALL); std::vector> ranges; // RAW @@ -1557,8 +1479,7 @@ TEST_F(Camera_Gtest, should_load_serialized_state) { 144'398, camera.get_device().get_facility()->get_thresholds().lower_bound_start); EXPECT_EQ( - 0, - camera.get_device().get_facility()->get_thresholds().lower_bound_stop); + 0, camera.get_device().get_facility()->get_thresholds().lower_bound_stop); EXPECT_EQ( 126, camera.get_device().get_facility()->get_thresholds().upper_bound_start); @@ -1838,9 +1759,8 @@ TEST_F(Camera_Gtest, serialization_unavailable_with_empty_camera) { } TEST_F_WITH_DATASET(Camera_Gtest, serialization_unavailable_with_raw_file) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "blinking_gen4_with_ext_triggers.raw") - .string(); + std::filesystem::path dataset_file_path = std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / + "blinking_gen4_with_ext_triggers.raw"; Camera camera = Camera::from_file(dataset_file_path, FileConfigHints().real_time_playback(false)); EXPECT_THROW(camera.save(""), CameraException); @@ -1850,12 +1770,11 @@ TEST_F_WITH_DATASET(Camera_Gtest, serialization_unavailable_with_raw_file) { #ifdef HAS_HDF5 TEST_F_WITH_DATASET(Camera_Gtest, serialization_unavailable_with_hdf5_file) { // Read the dataset provided - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "blinking_gen4_with_ext_triggers.hdf5") - .string(); + std::filesystem::path dataset_file_path = std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / + "blinking_gen4_with_ext_triggers.hdf5"; Camera camera = Camera::from_file(dataset_file_path, FileConfigHints().real_time_playback(false)); EXPECT_THROW(camera.save(""), CameraException); EXPECT_THROW(camera.load(""), CameraException); } -#endif \ No newline at end of file +#endif diff --git a/sdk/modules/stream/cpp/tests/camera_stream_slicer_gtest.cpp b/sdk/modules/stream/cpp/tests/camera_stream_slicer_gtest.cpp new file mode 100644 index 000000000..66c854ad9 --- /dev/null +++ b/sdk/modules/stream/cpp/tests/camera_stream_slicer_gtest.cpp @@ -0,0 +1,145 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/stream/camera_stream_slicer.h" +#include "metavision/utils/gtest/gtest_custom.h" + +using namespace Metavision; + +namespace fs = std::filesystem; + +class CameraStreamSlicerTest : public ::testing::Test { +protected: + void SetUp() final { + dataset_dir_ = GtestsParameters::instance().dataset_dir; + } + + std::string dataset_dir_; +}; + +TEST_F(CameraStreamSlicerTest, from_file_returns_valid_iterator) { + const auto record_path = fs::path(dataset_dir_) / "openeb" / "gen4_evt3_hand.raw"; + + // WHEN we create a slicer from this file + auto camera = Camera::from_file(record_path.string()); + CameraStreamSlicer slicer(std::move(camera)); + + // THEN the iterator is valid + auto begin = slicer.begin(); + auto end = slicer.end(); + + ASSERT_NE(begin, end); +} + +TEST_F(CameraStreamSlicerTest, from_file_returns_valid_slices) { + static constexpr int kNevents = 20000; + static constexpr int kNus = 20000; + + const auto record_path = fs::path(dataset_dir_) / "openeb" / "gen4_evt3_hand.raw"; + + // WHEN we create a slicer from this file based on the N us condition + auto camera = Camera::from_file(record_path.string()); + auto slicing_condition = CameraStreamSlicer::SliceCondition::make_n_us(kNus); + CameraStreamSlicer slicer(std::move(camera), slicing_condition); + + for (const auto &slice : slicer) { + ASSERT_TRUE(slice.status == Detail::ReslicingConditionStatus::MET_N_US || + slice.status == Detail::ReslicingConditionStatus::MET_AUTOMATIC); + + if (slice.status == Detail::ReslicingConditionStatus::MET_N_US) { + ASSERT_TRUE(slice.t % kNus == 0); + } + } + + slicing_condition = CameraStreamSlicer::SliceCondition::make_n_events(kNevents); + camera = Camera::from_file(record_path.string()); + slicer = CameraStreamSlicer(std::move(camera), slicing_condition); + + for (const auto &slice : slicer) { + ASSERT_TRUE(slice.status == Detail::ReslicingConditionStatus::MET_N_EVENTS || + slice.status == Detail::ReslicingConditionStatus::MET_AUTOMATIC); + + if (slice.status == Detail::ReslicingConditionStatus::MET_N_EVENTS) { + ASSERT_EQ(slice.events->size(), kNevents); + } + } +} + +TEST_F(CameraStreamSlicerTest, throw_if_camera_is_already_running) { + const auto record_path = fs::path(dataset_dir_) / "openeb" / "gen4_evt3_hand.raw"; + auto camera = Camera::from_file(record_path.string()); + camera.start(); + + ASSERT_THROW(CameraStreamSlicer slicer(std::move(camera)), std::runtime_error); +} + +TEST_F_WITH_ANY_CAMERA(CameraStreamSlicerTest, from_device_returns_valid_iterator) { + // GIVEN a slicer created from a device + auto camera = Camera::from_first_available(); + CameraStreamSlicer slicer(std::move(camera)); + + auto begin = slicer.begin(); + auto end = slicer.end(); + + ASSERT_NE(begin, end); +} + +TEST_F_WITH_ANY_CAMERA(CameraStreamSlicerTest, from_device_returns_valid_slices) { + static constexpr std::uint8_t kNSlicesToTest = 10; + static constexpr int kNevents = 20000; + static constexpr int kNus = 20000; + + auto slicing_condition = CameraStreamSlicer::SliceCondition::make_n_us(kNus); + auto camera = Camera::from_first_available(); + + { + CameraStreamSlicer slicer(std::move(camera), slicing_condition); + + // THEN the slice is created every N us (except for the last slice) + std::uint8_t num_slices = 0; + for (const auto &slice : slicer) { + ASSERT_TRUE(slice.status == Detail::ReslicingConditionStatus::MET_N_US || + slice.status == Detail::ReslicingConditionStatus::MET_AUTOMATIC); + + if (slice.status == Detail::ReslicingConditionStatus::MET_N_US) { + ASSERT_TRUE(slice.t % kNus == 0); + } + + if (++num_slices >= kNSlicesToTest) { + break; + } + } + } + + slicing_condition = CameraStreamSlicer::SliceCondition::make_n_events(kNevents); + camera = Camera::from_first_available(); + + { + CameraStreamSlicer slicer(std::move(camera), slicing_condition); + // THEN the slice is created every N events (except for the last slice) + std::uint8_t num_slices = 0; + for (const auto &slice : slicer) { + ASSERT_TRUE(slice.status == Detail::ReslicingConditionStatus::MET_N_EVENTS || + slice.status == Detail::ReslicingConditionStatus::MET_AUTOMATIC); + + if (slice.status == Detail::ReslicingConditionStatus::MET_N_EVENTS) { + ASSERT_EQ(slice.events->size(), kNevents); + } + + if (++num_slices >= kNSlicesToTest) { + break; + } + } + } +} \ No newline at end of file diff --git a/sdk/modules/driver/cpp/tests/event_file_reader_writer_gtest.cpp b/sdk/modules/stream/cpp/tests/event_file_reader_writer_gtest.cpp similarity index 79% rename from sdk/modules/driver/cpp/tests/event_file_reader_writer_gtest.cpp rename to sdk/modules/stream/cpp/tests/event_file_reader_writer_gtest.cpp index 8651dbc4f..ad1136082 100644 --- a/sdk/modules/driver/cpp/tests/event_file_reader_writer_gtest.cpp +++ b/sdk/modules/stream/cpp/tests/event_file_reader_writer_gtest.cpp @@ -9,6 +9,7 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ +#include #include #include #include @@ -26,13 +27,13 @@ #include "metavision/sdk/base/events/event_ext_trigger.h" #include "metavision/sdk/base/utils/generic_header.h" #include "metavision/sdk/base/utils/timestamp.h" -#include "metavision/sdk/driver/camera.h" -#include "metavision/sdk/driver/ext_trigger.h" -#include "metavision/sdk/driver/dat_event_file_reader.h" -#include "metavision/sdk/driver/raw_event_file_reader.h" -#include "metavision/sdk/driver/raw_event_file_writer.h" -#include "metavision/sdk/driver/hdf5_event_file_reader.h" -#include "metavision/sdk/driver/hdf5_event_file_writer.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/ext_trigger.h" +#include "metavision/sdk/stream/dat_event_file_reader.h" +#include "metavision/sdk/stream/raw_event_file_reader.h" +#include "metavision/sdk/stream/raw_event_file_logger.h" +#include "metavision/sdk/stream/hdf5_event_file_reader.h" +#include "metavision/sdk/stream/hdf5_event_file_writer.h" #include "metavision/utils/gtest/gtest_with_tmp_dir.h" #include "metavision/utils/gtest/gtest_custom.h" @@ -44,7 +45,7 @@ class HDF5EventFileReader_Gtest : public GTestWithTmpDir { tmp_file_ = tmpdir_handler_->get_full_path("test.hdf5"); } - std::string tmp_file_; + std::filesystem::path tmp_file_; }; TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, constructor_invalid) { @@ -54,22 +55,22 @@ TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, constructor_invalid) { } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, constructor_valid) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; std::unique_ptr reader; ASSERT_NO_THROW(reader = std::make_unique(dataset_file_path)); } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, get_path) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; HDF5EventFileReader reader(dataset_file_path); ASSERT_EQ(dataset_file_path, reader.get_path()); } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, has_read_callbacks) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; HDF5EventFileReader reader(dataset_file_path); ASSERT_FALSE(reader.has_read_callbacks()); size_t id = reader.add_read_callback([](const EventCD *, const EventCD *) {}); @@ -81,8 +82,8 @@ TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, has_read_callbacks) { } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, get_metadata_map) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; HDF5EventFileReader reader(dataset_file_path); auto metadata_map = reader.get_metadata_map(); ASSERT_FALSE(metadata_map.empty()); @@ -92,9 +93,6 @@ TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, get_metadata_map) { it = metadata_map.find("serial_number"); ASSERT_TRUE(it != metadata_map.end()); EXPECT_EQ("00001621", it->second); - it = metadata_map.find("system_ID"); - ASSERT_TRUE(it != metadata_map.end()); - EXPECT_EQ("28", it->second); it = metadata_map.find("generation"); ASSERT_TRUE(it != metadata_map.end()); EXPECT_EQ("3.1", it->second); @@ -107,8 +105,8 @@ TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, get_metadata_map) { } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, has_seek_callbacks) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; HDF5EventFileReader reader(dataset_file_path); ASSERT_FALSE(reader.has_seek_callbacks()); size_t id = reader.add_seek_callback([](const auto &) {}); @@ -118,8 +116,8 @@ TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, has_seek_callbacks) { } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, get_seek_range) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; HDF5EventFileReader reader(dataset_file_path); timestamp min_t, max_t; ASSERT_TRUE(reader.get_seek_range(min_t, max_t)); @@ -128,16 +126,15 @@ TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, get_seek_range) { } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, get_duration) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; HDF5EventFileReader reader(dataset_file_path); EXPECT_EQ(13043033, reader.get_duration()); } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, read) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "blinking_gen4_with_ext_triggers.hdf5") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "blinking_gen4_with_ext_triggers.hdf5"; HDF5EventFileReader reader(dataset_file_path); size_t num_cd_events = 0; reader.add_read_callback( @@ -156,8 +153,8 @@ TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, read) { } TEST_F_WITH_DATASET(HDF5EventFileReader_Gtest, seek) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.hdf5"; HDF5EventFileReader reader(dataset_file_path); timestamp ts = -1; reader.add_seek_callback([&ts](const timestamp &t) { ts = t; }); @@ -200,7 +197,7 @@ TEST_F(HDF5EventFileReader_Gtest, read_cd_events_written_without_direct_calls) { { // write HDF5 file using chunking and filtering through HDF5 API (indirect) calls // and the ECF plugin - auto file = H5::H5File(tmp_file_, H5F_ACC_TRUNC); + auto file = H5::H5File(tmp_file_.string(), H5F_ACC_TRUNC); file.createGroup("/CD"); file.createGroup("/EXT_TRIGGER"); if (ecf_register_h5filter() < 0) { @@ -273,24 +270,24 @@ TEST_F(HDF5EventFileReader_Gtest, read_cd_events_written_without_direct_calls) { } TEST_WITH_DATASET(RAWEventFileReader_Gtest, constructor_valid) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path); std::unique_ptr reader; ASSERT_NO_THROW(reader = std::make_unique(*device, dataset_file_path)); } TEST_WITH_DATASET(RAWEventFileReader_Gtest, get_path) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path); RAWEventFileReader reader(*device, dataset_file_path); ASSERT_EQ(dataset_file_path, reader.get_path()); } TEST_WITH_DATASET(RAWEventFileReader_Gtest, has_read_callbacks) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path); RAWEventFileReader reader(*device, dataset_file_path); ASSERT_FALSE(reader.has_read_callbacks()); @@ -303,8 +300,8 @@ TEST_WITH_DATASET(RAWEventFileReader_Gtest, has_read_callbacks) { } TEST_WITH_DATASET(RAWEventFileReader_Gtest, get_metadata_map) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path); RAWEventFileReader reader(*device, dataset_file_path); auto metadata_map = reader.get_metadata_map(); @@ -315,17 +312,14 @@ TEST_WITH_DATASET(RAWEventFileReader_Gtest, get_metadata_map) { it = metadata_map.find("serial_number"); ASSERT_TRUE(it != metadata_map.end()); EXPECT_EQ("00001621", it->second); - it = metadata_map.find("system_ID"); - ASSERT_TRUE(it != metadata_map.end()); - EXPECT_EQ("28", it->second); it = metadata_map.find("evt"); ASSERT_TRUE(it != metadata_map.end()); EXPECT_EQ("2.0", it->second); } TEST_WITH_DATASET(RAWEventFileReader_Gtest, has_seek_callbacks) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path); RAWEventFileReader reader(*device, dataset_file_path); ASSERT_FALSE(reader.has_seek_callbacks()); @@ -336,8 +330,8 @@ TEST_WITH_DATASET(RAWEventFileReader_Gtest, has_seek_callbacks) { } TEST_WITH_DATASET(RAWEventFileReader_Gtest, get_seek_range) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; RawFileConfig raw_file_stream_config; raw_file_stream_config.build_index_ = true; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path, raw_file_stream_config); @@ -351,17 +345,17 @@ TEST_WITH_DATASET(RAWEventFileReader_Gtest, get_seek_range) { } TEST_WITH_DATASET(RAWEventFileReader_Gtest, get_duration) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path); RAWEventFileReader reader(*device, dataset_file_path); EXPECT_EQ(13043033, reader.get_duration()); } TEST_WITH_DATASET(RAWEventFileReader_Gtest, read) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "blinking_gen4_with_ext_triggers.raw") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "blinking_gen4_with_ext_triggers.raw"; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path); RAWEventFileReader reader(*device, dataset_file_path); size_t num_cd_events = 0; @@ -381,8 +375,8 @@ TEST_WITH_DATASET(RAWEventFileReader_Gtest, read) { } TEST_WITH_DATASET(RAWEventFileReader_Gtest, seek) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; RawFileConfig raw_file_stream_config; raw_file_stream_config.build_index_ = true; std::unique_ptr device = DeviceDiscovery::open_raw_file(dataset_file_path, raw_file_stream_config); @@ -400,25 +394,25 @@ TEST_WITH_DATASET(RAWEventFileReader_Gtest, seek) { } TEST_WITH_DATASET(DATEventFileReader_Gtest, constructor_valid) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; std::unique_ptr reader; ASSERT_NO_THROW(reader = std::make_unique(dataset_file_path)); } TEST_WITH_DATASET(DATEventFileReader_Gtest, get_path) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; DATEventFileReader reader(dataset_file_path); ASSERT_EQ(dataset_file_path, reader.get_path()); } TEST_WITH_DATASET(DATEventFileReader_Gtest, has_read_callbacks) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; DATEventFileReader reader(dataset_file_path); ASSERT_FALSE(reader.has_read_callbacks()); @@ -431,9 +425,9 @@ TEST_WITH_DATASET(DATEventFileReader_Gtest, has_read_callbacks) { } TEST_WITH_DATASET(DATEventFileReader_Gtest, get_metadata_map) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; DATEventFileReader reader(dataset_file_path); auto metadata_map = reader.get_metadata_map(); @@ -444,15 +438,12 @@ TEST_WITH_DATASET(DATEventFileReader_Gtest, get_metadata_map) { it = metadata_map.find("generation"); ASSERT_TRUE(it != metadata_map.end()); EXPECT_EQ("3.0", it->second); - it = metadata_map.find("system_ID"); - ASSERT_TRUE(it != metadata_map.end()); - EXPECT_EQ("0", it->second); } TEST_WITH_DATASET(DATEventFileReader_Gtest, has_seek_callbacks) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; DATEventFileReader reader(dataset_file_path); ASSERT_FALSE(reader.has_seek_callbacks()); @@ -463,9 +454,9 @@ TEST_WITH_DATASET(DATEventFileReader_Gtest, has_seek_callbacks) { } TEST_WITH_DATASET(DATEventFileReader_Gtest, get_seek_range) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; DATEventFileReader reader(dataset_file_path); timestamp min_t, max_t; @@ -473,18 +464,18 @@ TEST_WITH_DATASET(DATEventFileReader_Gtest, get_seek_range) { } TEST_WITH_DATASET(DATEventFileReader_Gtest, get_duration) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; DATEventFileReader reader(dataset_file_path); EXPECT_EQ(7702845, reader.get_duration()); } TEST_WITH_DATASET(DATEventFileReader_Gtest, read) { - std::string dataset_file_path = (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / - "core" / "event_io" / "recording_td.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / + "openeb" / "core" / "event_io" / "recording_td.dat"; DATEventFileReader reader(dataset_file_path); size_t num_cd_events = 0; reader.add_read_callback( @@ -503,9 +494,8 @@ TEST_WITH_DATASET(DATEventFileReader_Gtest, read) { } TEST_WITH_DATASET(DATEventFileReader_Gtest, read_delayed_recording) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "test_start_after_0.dat") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "test_start_after_0.dat"; DATEventFileReader reader(dataset_file_path); size_t num_cd_events = 0; reader.add_read_callback( @@ -523,31 +513,31 @@ TEST_WITH_DATASET(DATEventFileReader_Gtest, read_delayed_recording) { EXPECT_EQ(0, num_ext_trigger_events); } -class RAWEventFileWriter_Gtest : public GTestWithTmpDir { +class RAWEventFileLogger_Gtest : public GTestWithTmpDir { protected: virtual void SetUp() { tmp_file_ = tmpdir_handler_->get_full_path("test.raw"); } - std::string tmp_file_; + std::filesystem::path tmp_file_; }; -TEST_F(RAWEventFileWriter_Gtest, empty_constructor) { - std::unique_ptr writer; - ASSERT_NO_THROW(writer = std::make_unique()); +TEST_F(RAWEventFileLogger_Gtest, empty_constructor) { + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique()); } -TEST_F(RAWEventFileWriter_Gtest, constructor_invalid) { - std::unique_ptr writer; - std::string file = - (boost::filesystem::path(tmpdir_handler_->get_full_path("inexistent_directory")) / "file.raw").string(); - ASSERT_THROW(writer = std::make_unique(file), std::runtime_error); +TEST_F(RAWEventFileLogger_Gtest, constructor_invalid) { + std::unique_ptr writer; + std::filesystem::path file = + std::filesystem::path(tmpdir_handler_->get_full_path("inexistent_directory")) / "file.raw"; + ASSERT_THROW(writer = std::make_unique(file), std::runtime_error); } -TEST_F(RAWEventFileWriter_Gtest, constructor) { +TEST_F(RAWEventFileLogger_Gtest, constructor) { { - std::unique_ptr writer; - ASSERT_NO_THROW(writer = std::make_unique(tmp_file_)); + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique(tmp_file_)); } { std::ifstream ifs(tmp_file_); @@ -555,33 +545,33 @@ TEST_F(RAWEventFileWriter_Gtest, constructor) { } } -TEST_F(RAWEventFileWriter_Gtest, not_is_open) { - std::unique_ptr writer; - writer = std::make_unique(); +TEST_F(RAWEventFileLogger_Gtest, not_is_open) { + std::unique_ptr writer; + writer = std::make_unique(); ASSERT_FALSE(writer->is_open()); } -TEST_F(RAWEventFileWriter_Gtest, is_open) { - std::unique_ptr writer; - writer = std::make_unique(tmp_file_); +TEST_F(RAWEventFileLogger_Gtest, is_open) { + std::unique_ptr writer; + writer = std::make_unique(tmp_file_); ASSERT_TRUE(writer->is_open()); } -TEST_F(RAWEventFileWriter_Gtest, open) { - std::unique_ptr writer; - ASSERT_NO_THROW(writer = std::make_unique()); +TEST_F(RAWEventFileLogger_Gtest, open) { + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique()); ASSERT_NO_THROW(writer->open(tmp_file_)); } -TEST_F(RAWEventFileWriter_Gtest, close) { - std::unique_ptr writer; - writer = std::make_unique(tmp_file_); +TEST_F(RAWEventFileLogger_Gtest, close) { + std::unique_ptr writer; + writer = std::make_unique(tmp_file_); ASSERT_NO_THROW(writer->close()); } -TEST_F(RAWEventFileWriter_Gtest, open_close) { - std::unique_ptr writer; - ASSERT_NO_THROW(writer = std::make_unique()); +TEST_F(RAWEventFileLogger_Gtest, open_close) { + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique()); ASSERT_NO_THROW(writer->open(tmp_file_)); ASSERT_TRUE(writer->is_open()); ASSERT_NO_THROW(writer->close()); @@ -589,18 +579,18 @@ TEST_F(RAWEventFileWriter_Gtest, open_close) { ASSERT_NO_THROW(writer->open(tmp_file_)); } -TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, constructor_metadata_map) { +TEST_F_WITH_DATASET(RAWEventFileLogger_Gtest, constructor_metadata_map) { { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::ifstream ifs(dataset_file_path); GenericHeader header(ifs); auto header_map = header.get_header_map(); std::unordered_map m(header_map.begin(), header_map.end()); m["toto"] = "blub"; - std::unique_ptr writer; - ASSERT_NO_THROW(writer = std::make_unique(tmp_file_, m)); + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique(tmp_file_, m)); } { std::ifstream ifs(tmp_file_); @@ -610,20 +600,20 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, constructor_metadata_map) { } } -TEST_F(RAWEventFileWriter_Gtest, get_path) { - RAWEventFileWriter writer(tmp_file_); +TEST_F(RAWEventFileLogger_Gtest, get_path) { + RAWEventFileLogger writer(tmp_file_); ASSERT_EQ(tmp_file_, writer.get_path()); } -TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata) { +TEST_F_WITH_DATASET(RAWEventFileLogger_Gtest, add_metadata) { { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::ifstream ifs(dataset_file_path); GenericHeader header(ifs); auto header_map = header.get_header_map(); - RAWEventFileWriter writer(tmp_file_, + RAWEventFileLogger writer(tmp_file_, std::unordered_map(header_map.begin(), header_map.end())); writer.add_metadata("toto", "blub"); } @@ -635,14 +625,14 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata) { } } -TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata_no_flush_succeed) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); +TEST_F_WITH_DATASET(RAWEventFileLogger_Gtest, add_metadata_no_flush_succeed) { + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::ifstream ifs(dataset_file_path); GenericHeader header(ifs); auto header_map = header.get_header_map(); - RAWEventFileWriter writer(tmp_file_, + RAWEventFileLogger writer(tmp_file_, std::unordered_map(header_map.begin(), header_map.end())); uint8_t buf[1] = {0}; @@ -652,7 +642,7 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata_no_flush_succeed) { ASSERT_NO_THROW(writer.add_metadata("toto", "blub")); } -TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata_flush_raw_fail) { +TEST_F_WITH_DATASET(RAWEventFileLogger_Gtest, add_metadata_flush_raw_fail) { (void)(::testing::GTEST_FLAG(death_test_style) = "threadsafe"); const std::string expected_output_regex = @@ -664,14 +654,13 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata_flush_raw_fail) { ASSERT_DEATH( { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw") - .string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::ifstream ifs(dataset_file_path); GenericHeader header(ifs); auto header_map = header.get_header_map(); - RAWEventFileWriter writer( + RAWEventFileLogger writer( tmp_file_, std::unordered_map(header_map.begin(), header_map.end())); uint8_t buf[1] = {0}; @@ -684,15 +673,15 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata_flush_raw_fail) { expected_output_regex); } -TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, remove_metadata) { +TEST_F_WITH_DATASET(RAWEventFileLogger_Gtest, remove_metadata) { { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; std::ifstream ifs(dataset_file_path); GenericHeader header(ifs); auto header_map = header.get_header_map(); - RAWEventFileWriter writer(tmp_file_, + RAWEventFileLogger writer(tmp_file_, std::unordered_map(header_map.begin(), header_map.end())); writer.add_metadata("toto1", "blub"); writer.add_metadata("toto2", "blub"); @@ -707,12 +696,12 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, remove_metadata) { } } -TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata_map_from_camera) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); +TEST_F_WITH_DATASET(RAWEventFileLogger_Gtest, add_metadata_map_from_camera) { + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; Camera cam = Camera::from_file(dataset_file_path); { - RAWEventFileWriter writer(tmp_file_); + RAWEventFileLogger writer(tmp_file_); writer.add_metadata_map_from_camera(cam); } { @@ -735,14 +724,14 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, add_metadata_map_from_camera) { } } -TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, write_raw) { +TEST_F_WITH_DATASET(RAWEventFileLogger_Gtest, write_raw) { std::vector expected_data; { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; Camera cam = Camera::from_file(dataset_file_path); - RAWEventFileWriter writer(tmp_file_); + RAWEventFileLogger writer(tmp_file_); writer.add_metadata_map_from_camera(cam); cam.raw_data().add_callback([&writer, &expected_data](const uint8_t *ptr, size_t size) { @@ -763,6 +752,11 @@ TEST_F_WITH_DATASET(RAWEventFileWriter_Gtest, write_raw) { EXPECT_TRUE(std::equal(data_ptr, data_ptr + size, ptr)); data_ptr += size; }); + + cam.start(); + while (cam.is_running()) { + std::this_thread::yield(); + } } } @@ -772,7 +766,7 @@ class HDF5EventFileWriter_Gtest : public GTestWithTmpDir { tmp_file_ = tmpdir_handler_->get_full_path("test.hdf5"); } - std::string tmp_file_; + std::filesystem::path tmp_file_; }; TEST_F(HDF5EventFileWriter_Gtest, empty_constructor) { @@ -782,8 +776,8 @@ TEST_F(HDF5EventFileWriter_Gtest, empty_constructor) { TEST_F(HDF5EventFileWriter_Gtest, constructor_invalid) { std::unique_ptr writer; - std::string file = - (boost::filesystem::path(tmpdir_handler_->get_full_path("inexistent_directory")) / "file.hdf5").string(); + std::filesystem::path file = + std::filesystem::path(tmpdir_handler_->get_full_path("inexistent_directory")) / "file.hdf5"; ASSERT_THROW(writer = std::make_unique(file), H5::FileIException); } @@ -890,8 +884,8 @@ TEST_F(HDF5EventFileWriter_Gtest, remove_metata) { } TEST_F_WITH_DATASET(HDF5EventFileWriter_Gtest, add_metata_map_from_camera) { - std::string dataset_file_path = - (boost::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw").string(); + std::filesystem::path dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; Camera cam = Camera::from_file(dataset_file_path); { HDF5EventFileWriter writer(tmp_file_); @@ -954,7 +948,7 @@ TEST_F(HDF5EventFileWriter_Gtest, simple_write_triggers) { HDF5EventFileReader reader(tmp_file_); size_t num_calls = 0; reader.add_read_callback([&num_calls](const EventExtTrigger *begin, const EventExtTrigger *end) { - ASSERT_EQ(1, std::distance(begin, end)); + ASSERT_EQ(1, std::distance(begin, end)); ASSERT_EQ(0, begin->p); ASSERT_EQ(0, begin->t); ASSERT_EQ(0, begin->id); @@ -1045,7 +1039,7 @@ TEST_F(HDF5EventFileWriter_Gtest, write_first_ts_is_big) { } { // check that we don't have a long list of Index(0,-1) at the beginning of the indexes table - H5::H5File file(tmp_file_, H5F_ACC_RDONLY); + H5::H5File file(tmp_file_.string(), H5F_ACC_RDONLY); H5::DataSet dset = file.openDataSet("/CD/indexes"); struct Index { Index(size_t id = 0, std::int64_t ts = 0) : id(id), ts(ts) {} @@ -1128,7 +1122,7 @@ TEST_F(HDF5EventFileWriter_Gtest, random_writes) { while (reader.read()) { std::this_thread::yield(); } - + ASSERT_EQ(expected_events_cd.size(), events_cd.size()); for (size_t i = 0; i < expected_events_cd.size(); ++i) { @@ -1139,7 +1133,7 @@ TEST_F(HDF5EventFileWriter_Gtest, random_writes) { } ASSERT_EQ(expected_events_trigger.size(), events_trigger.size()); - + for (size_t i = 0; i < expected_events_trigger.size(); ++i) { ASSERT_EQ(expected_events_trigger[i].p, events_trigger[i].p); ASSERT_EQ(expected_events_trigger[i].id, events_trigger[i].id); diff --git a/sdk/modules/stream/cpp/tests/raw_evt2_event_file_writer_gtest.cpp b/sdk/modules/stream/cpp/tests/raw_evt2_event_file_writer_gtest.cpp new file mode 100644 index 000000000..7c64e6ad0 --- /dev/null +++ b/sdk/modules/stream/cpp/tests/raw_evt2_event_file_writer_gtest.cpp @@ -0,0 +1,355 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/base/utils/generic_header.h" +#include "metavision/sdk/base/utils/log.h" +#include "metavision/sdk/base/utils/sdk_log.h" +#include "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/raw_event_file_reader.h" +#include "metavision/sdk/stream/raw_evt2_event_file_writer.h" +#include "metavision/utils/gtest/gtest_with_tmp_dir.h" +#include "metavision/utils/gtest/gtest_custom.h" + +using namespace Metavision; + +class RAWEvt2EventFileWriter_Gtest : public GTestWithTmpDir { +protected: + virtual void SetUp() { + std::string tmp_file = tmpdir_handler_->get_full_path("test.raw"); + tmp_file_path_ = std::filesystem::path(tmp_file); + } + + std::filesystem::path tmp_file_path_; +}; + +TEST_F(RAWEvt2EventFileWriter_Gtest, empty_constructor) { + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique(640, 480)); +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, constructor_invalid) { + std::unique_ptr writer; + const auto filepath = std::filesystem::path(tmpdir_handler_->get_full_path("inexistent_directory")) / "file.raw"; + ASSERT_THROW(writer = std::make_unique(640, 480, filepath), std::runtime_error); +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, constructor) { + { + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique(640, 480, tmp_file_path_)); + } + { + std::ifstream ifs(tmp_file_path_.string()); + ASSERT_TRUE(ifs.is_open()); + } +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, not_is_open) { + std::unique_ptr writer; + writer = std::make_unique(640, 480); + ASSERT_FALSE(writer->is_open()); +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, is_open) { + std::unique_ptr writer; + writer = std::make_unique(640, 480, tmp_file_path_); + ASSERT_TRUE(writer->is_open()); +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, open) { + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique(640, 480)); + ASSERT_NO_THROW(writer->open(tmp_file_path_.string())); +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, close) { + std::unique_ptr writer; + writer = std::make_unique(640, 480, tmp_file_path_); + ASSERT_NO_THROW(writer->close()); +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, open_close) { + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique(640, 480)); + ASSERT_NO_THROW(writer->open(tmp_file_path_.string())); + ASSERT_TRUE(writer->is_open()); + ASSERT_NO_THROW(writer->close()); + ASSERT_FALSE(writer->is_open()); + ASSERT_NO_THROW(writer->open(tmp_file_path_.string())); +} + +TEST_F_WITH_DATASET(RAWEvt2EventFileWriter_Gtest, constructor_metadata_map) { + { + const auto dataset_file_path = + std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / "gen31_timer.raw"; + std::ifstream ifs(dataset_file_path.string()); + GenericHeader header(ifs); + auto header_map = header.get_header_map(); + std::unordered_map m(header_map.begin(), header_map.end()); + m["toto"] = "blub"; + + std::unique_ptr writer; + ASSERT_NO_THROW(writer = std::make_unique(640, 480, tmp_file_path_, false, m)); + } + { + std::ifstream ifs(tmp_file_path_.string()); + GenericHeader header(ifs); + auto metadata_map = header.get_header_map(); + ASSERT_EQ("blub", metadata_map["toto"]); + } +} + +TEST_F(RAWEvt2EventFileWriter_Gtest, get_path) { + RAWEvt2EventFileWriter writer(640, 480, tmp_file_path_); + ASSERT_EQ(tmp_file_path_.string(), writer.get_path()); +} + +TEST_F_WITH_DATASET(RAWEvt2EventFileWriter_Gtest, add_metadata) { + { + RAWEvt2EventFileWriter writer(640, 480, tmp_file_path_); + writer.add_metadata("toto", "blub"); + } + { + std::ifstream ifs(tmp_file_path_.string()); + GenericHeader header(ifs); + auto metadata_map = header.get_header_map(); + ASSERT_EQ("blub", metadata_map["toto"]); + } +} + +TEST_F_WITH_DATASET(RAWEvt2EventFileWriter_Gtest, add_metadata_flush_raw_fail) { + (void)(::testing::GTEST_FLAG(death_test_style) = "threadsafe"); + + const std::string expected_output_regex = +#ifdef _WIN32 + ""; +#else + "Unable to modify metadata in RAW"; +#endif + + ASSERT_DEATH( + { + RAWEvt2EventFileWriter writer(640, 480, tmp_file_path_); + + std::vector events = {EventCD(0, 0, 0, 0)}; + writer.add_events(events.data(), events.data() + 1); + writer.flush(); + + // can't add metadata to RAW once data has been added + writer.add_metadata("toto", "blub"); + }, + expected_output_regex); +} + +TEST_F_WITH_DATASET(RAWEvt2EventFileWriter_Gtest, remove_metadata) { + { + RAWEvt2EventFileWriter writer(640, 480, tmp_file_path_); + writer.add_metadata("toto1", "blub"); + writer.add_metadata("toto2", "blub"); + writer.remove_metadata("toto1"); + } + { + std::ifstream ifs(tmp_file_path_.string()); + GenericHeader header(ifs); + auto metadata_map = header.get_header_map(); + ASSERT_EQ("blub", metadata_map["toto2"]); + ASSERT_TRUE(metadata_map.find("toto1") == metadata_map.end()); + } +} + +TEST_F_WITH_DATASET(RAWEvt2EventFileWriter_Gtest, write_raw_cd_only) { + std::vector expected_data_cd; + expected_data_cd.reserve(10000); + { + const auto dataset_file_path = std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / + "blinking_gen4_with_ext_triggers.raw"; + Camera cam = + Camera::from_file(dataset_file_path.string(), Metavision::FileConfigHints().real_time_playback(false)); + + const int sensor_width = cam.geometry().get_width(); + const int sensor_height = cam.geometry().get_height(); + RAWEvt2EventFileWriter writer(sensor_width, sensor_height, tmp_file_path_, false); + + cam.cd().add_callback([&writer, &expected_data_cd](const EventCD *begin, const EventCD *end) { + expected_data_cd.insert(expected_data_cd.end(), begin, end); + writer.add_events(begin, end); + }); + + cam.start(); + while (cam.is_running()) { + std::this_thread::yield(); + } + cam.stop(); + } + + { + Camera cam = + Camera::from_file(tmp_file_path_.string(), Metavision::FileConfigHints().real_time_playback(false)); + auto data_cd_it = expected_data_cd.cbegin(); + cam.cd().add_callback([&data_cd_it](const EventCD *begin, const EventCD *end) { + while (begin != end) { + EXPECT_EQ(begin->t, data_cd_it->t); + EXPECT_EQ(begin->p, data_cd_it->p); + EXPECT_EQ(begin->x, data_cd_it->x); + EXPECT_EQ(begin->y, data_cd_it->y); + ++begin; + ++data_cd_it; + } + }); + + cam.start(); + while (cam.is_running()) { + std::this_thread::yield(); + } + cam.stop(); + EXPECT_EQ(expected_data_cd.size(), std::distance(expected_data_cd.cbegin(), data_cd_it)); + } +} + +TEST_F_WITH_DATASET(RAWEvt2EventFileWriter_Gtest, write_raw_cd_trigger) { + std::vector expected_data_cd; + expected_data_cd.reserve(10000); + std::vector expected_data_trigger; + expected_data_trigger.reserve(1000); + { + const auto dataset_file_path = std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / + "blinking_gen4_with_ext_triggers.raw"; + Camera cam = + Camera::from_file(dataset_file_path.string(), Metavision::FileConfigHints().real_time_playback(false)); + + const int sensor_width = cam.geometry().get_width(); + const int sensor_height = cam.geometry().get_height(); + RAWEvt2EventFileWriter writer(sensor_width, sensor_height, tmp_file_path_, true); + + cam.cd().add_callback([&writer, &expected_data_cd](const EventCD *begin, const EventCD *end) { + expected_data_cd.insert(expected_data_cd.end(), begin, end); + writer.add_events(begin, end); + }); + + cam.ext_trigger().add_callback( + [&writer, &expected_data_trigger](const EventExtTrigger *begin, const EventExtTrigger *end) { + expected_data_trigger.insert(expected_data_trigger.end(), begin, end); + writer.add_events(begin, end); + }); + + cam.start(); + while (cam.is_running()) { + std::this_thread::yield(); + } + cam.stop(); + } + + { + Camera cam = + Camera::from_file(tmp_file_path_.string(), Metavision::FileConfigHints().real_time_playback(false)); + auto data_cd_it = expected_data_cd.cbegin(); + cam.cd().add_callback([&data_cd_it](const EventCD *begin, const EventCD *end) { + while (begin != end) { + ASSERT_EQ(begin->t, data_cd_it->t); + ASSERT_EQ(begin->p, data_cd_it->p); + ASSERT_EQ(begin->x, data_cd_it->x); + ASSERT_EQ(begin->y, data_cd_it->y); + ++begin; + ++data_cd_it; + } + }); + auto data_trig_it = expected_data_trigger.cbegin(); + cam.ext_trigger().add_callback([&data_trig_it](const EventExtTrigger *begin, const EventExtTrigger *end) { + while (begin != end) { + EXPECT_EQ(begin->t, data_trig_it->t); + EXPECT_EQ(begin->p, data_trig_it->p); + EXPECT_EQ(begin->id, data_trig_it->id); + ++begin; + ++data_trig_it; + } + }); + + cam.start(); + while (cam.is_running()) { + std::this_thread::yield(); + } + cam.stop(); + EXPECT_EQ(expected_data_cd.size(), std::distance(expected_data_cd.cbegin(), data_cd_it)); + EXPECT_EQ(expected_data_trigger.size(), std::distance(expected_data_trigger.cbegin(), data_trig_it)); + } +} + +TEST_F_WITH_DATASET(RAWEvt2EventFileWriter_Gtest, write_raw_cd_trigger_1s_max_add_latency) { + std::vector expected_data_cd; + expected_data_cd.reserve(10000); + std::vector expected_data_trigger; + expected_data_trigger.reserve(1000); + { + const auto dataset_file_path = std::filesystem::path(GtestsParameters::instance().dataset_dir) / "openeb" / + "blinking_gen4_with_ext_triggers.raw"; + Camera cam = + Camera::from_file(dataset_file_path.string(), Metavision::FileConfigHints().real_time_playback(false)); + + const int sensor_width = cam.geometry().get_width(); + const int sensor_height = cam.geometry().get_height(); + RAWEvt2EventFileWriter writer(sensor_width, sensor_height, tmp_file_path_, true, {}, 1'000'000); + + cam.cd().add_callback([&writer, &expected_data_cd](const EventCD *begin, const EventCD *end) { + expected_data_cd.insert(expected_data_cd.end(), begin, end); + writer.add_events(begin, end); + }); + + cam.ext_trigger().add_callback( + [&writer, &expected_data_trigger](const EventExtTrigger *begin, const EventExtTrigger *end) { + expected_data_trigger.insert(expected_data_trigger.end(), begin, end); + writer.add_events(begin, end); + }); + + cam.start(); + while (cam.is_running()) { + std::this_thread::yield(); + } + cam.stop(); + } + + { + Camera cam = + Camera::from_file(tmp_file_path_.string(), Metavision::FileConfigHints().real_time_playback(false)); + auto data_cd_it = expected_data_cd.cbegin(); + cam.cd().add_callback([&data_cd_it](const EventCD *begin, const EventCD *end) { + while (begin != end) { + ASSERT_EQ(begin->t, data_cd_it->t); + ASSERT_EQ(begin->p, data_cd_it->p); + ASSERT_EQ(begin->x, data_cd_it->x); + ASSERT_EQ(begin->y, data_cd_it->y); + ++begin; + ++data_cd_it; + } + }); + auto data_trig_it = expected_data_trigger.cbegin(); + cam.ext_trigger().add_callback([&data_trig_it](const EventExtTrigger *begin, const EventExtTrigger *end) { + while (begin != end) { + EXPECT_EQ(begin->t, data_trig_it->t); + EXPECT_EQ(begin->p, data_trig_it->p); + EXPECT_EQ(begin->id, data_trig_it->id); + ++begin; + ++data_trig_it; + } + }); + + cam.start(); + while (cam.is_running()) { + std::this_thread::yield(); + } + cam.stop(); + EXPECT_EQ(expected_data_cd.size(), std::distance(expected_data_cd.cbegin(), data_cd_it)); + EXPECT_EQ(expected_data_trigger.size(), std::distance(expected_data_trigger.cbegin(), data_trig_it)); + } +} diff --git a/sdk/modules/stream/python/CMakeLists.txt b/sdk/modules/stream/python/CMakeLists.txt new file mode 100644 index 000000000..12ed812c8 --- /dev/null +++ b/sdk/modules/stream/python/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +# Add bindings +add_subdirectory(bindings) + +if (GENERATE_DOC_PYTHON_BINDINGS) + add_subdirectory(doc) +endif(GENERATE_DOC_PYTHON_BINDINGS) + +# Samples +add_subdirectory(samples) + +# Tests +add_subdirectory(tests) + +# Cpack +add_cpack_component(PUBLIC metavision-sdk-stream-python-samples) +add_python_cpack_components(PUBLIC metavision-sdk-stream) diff --git a/sdk/modules/stream/python/bindings/CMakeLists.txt b/sdk/modules/stream/python/bindings/CMakeLists.txt new file mode 100644 index 000000000..f42b22beb --- /dev/null +++ b/sdk/modules/stream/python/bindings/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) Prophesee S.A. +# +# 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(sdk_stream_python_srcs + ${CMAKE_CURRENT_SOURCE_DIR}/camera_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/hdf5_event_file_writer_python.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/metavision_sdk_stream_bindings.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/raw_evt2_event_file_writer_python.cpp +) + +if (GENERATE_DOC_PYTHON_BINDINGS) + set (sdk_stream_python_dependencies metavision_sdk_stream_python_doc_from_cpp) + set (sdk_stream_python_include_directories ${GENERATE_PYTHON_BINDINGS_DOC_DIRECTORY}) + set (sdk_stream_python_compile_definitions GENERATE_DOC_PYTHON_BINDINGS_USING_CPP_COMMENTS) +endif() + +add_sdk_python_bindings(stream + SOURCES ${sdk_stream_python_srcs} + LINK_LIBRARIES + PRIVATE + MetavisionSDK::stream + MetavisionUtils::pybind + INCLUDE_DIRECTORIES PRIVATE ${sdk_stream_python_include_directories} + COMPILE_DEFINITIONS PRIVATE ${sdk_stream_python_compile_definitions} + DEPENDENCIES ${sdk_stream_python_dependencies} +) diff --git a/sdk/modules/stream/python/bindings/__init__.py b/sdk/modules/stream/python/bindings/__init__.py new file mode 100644 index 000000000..eb308e5eb --- /dev/null +++ b/sdk/modules/stream/python/bindings/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +#!/usr/bin/env python + +import metavision_sdk_base_paths_internal +import metavision_hal_internal +from metavision_sdk_stream_internal import * diff --git a/sdk/modules/stream/python/bindings/camera_python.cpp b/sdk/modules/stream/python/bindings/camera_python.cpp new file mode 100644 index 000000000..fff857d4c --- /dev/null +++ b/sdk/modules/stream/python/bindings/camera_python.cpp @@ -0,0 +1,72 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/file_config_hints.h" +#include "pb_doc_stream.h" + +namespace py = pybind11; + +namespace Metavision { + +void export_camera(py::module &m) { + py::class_(m, "FileConfigHints", pybind_doc_stream["Metavision::FileConfigHints"]) + .def(py::init<>(), pybind_doc_stream["Metavision::FileConfigHints::FileConfigHints"]) + .def("real_time_playback", static_cast(&FileConfigHints::real_time_playback), + pybind_doc_stream["Metavision::FileConfigHints::real_time_playback() const"]) + .def("real_time_playback", py::overload_cast(&FileConfigHints::real_time_playback), py::arg("enabled"), + pybind_doc_stream["Metavision::FileConfigHints::real_time_playback(bool enabled)"]) + .def("time_shift", static_cast(&FileConfigHints::time_shift), + pybind_doc_stream["Metavision::FileConfigHints::time_shift() const"]) + .def("time_shift", py::overload_cast(&FileConfigHints::time_shift), py::arg("enabled"), + pybind_doc_stream["Metavision::FileConfigHints::time_shift(bool enabled)"]) + .def("max_memory", static_cast(&FileConfigHints::max_memory), + pybind_doc_stream["Metavision::FileConfigHints::max_memory() const"]) + .def("max_memory", py::overload_cast(&FileConfigHints::max_memory), py::arg("max_memory"), + pybind_doc_stream["Metavision::FileConfigHints::max_memory(std::size_t max_memory)"]) + .def("max_read_per_op", static_cast(&FileConfigHints::max_read_per_op), + pybind_doc_stream["Metavision::FileConfigHints::max_read_per_op() const"]) + .def("max_memory", py::overload_cast(&FileConfigHints::max_read_per_op), py::arg("max_read_per_op"), + pybind_doc_stream["Metavision::FileConfigHints::max_read_per_op(std::size_t max_read_per_op)"]) + .def("set", + static_cast(&FileConfigHints::set), + py::arg("key"), py::arg("value"), + pybind_doc_stream["Metavision::FileConfigHints::set(const std::string &key, const std::string &value)"]) + .def("get", &FileConfigHints::get, py::arg("key"), py::arg("def") = std::string(), + pybind_doc_stream["Metavision::FileConfigHints::get"]); + + py::class_(m, "Camera", pybind_doc_stream["Metavision::Camera"]) + .def_static("from_first_available", py::overload_cast<>(&Camera::from_first_available), + pybind_doc_stream["Metavision::Camera::from_first_available()"]) + .def_static("from_first_available", py::overload_cast(&Camera::from_first_available), + py::arg("config"), + pybind_doc_stream["Metavision::Camera::from_first_available(const DeviceConfig &config)"]) + .def_static("from_serial", py::overload_cast(&Camera::from_serial), py::arg("serial"), + pybind_doc_stream["Metavision::Camera::from_serial(const std::string &serial)"]) + .def_static("from_serial", py::overload_cast(&Camera::from_serial), + py::arg("serial"), py::arg("config"), + pybind_doc_stream["Metavision::Camera::from_serial(const std::string &serial, const DeviceConfig &config)"]) + .def_static("from_file", &Camera::from_file, py::arg("file_path"), py::arg("hints") = FileConfigHints(), + pybind_doc_stream["Metavision::Camera::from_file"]) + .def("get_device", static_cast(&Camera::get_device), py::return_value_policy::reference, + pybind_doc_stream["Metavision::Camera::get_device"]) + .def("save", &Camera::save, py::arg("path"), pybind_doc_stream["Metavision::Camera::save"]) + .def("load", &Camera::load, py::arg("path"), pybind_doc_stream["Metavision::Camera::load"]) + .def("width", [](const Camera &camera) { return camera.geometry().get_width(); }, + "Returns the width of the camera\n") + .def("height", [](const Camera &camera) { return camera.geometry().get_height(); }, + "Returns the height of the camera\n"); +} + +} // namespace Metavision diff --git a/sdk/modules/stream/python/bindings/hdf5_event_file_writer_python.cpp b/sdk/modules/stream/python/bindings/hdf5_event_file_writer_python.cpp new file mode 100644 index 000000000..e2c7ebf67 --- /dev/null +++ b/sdk/modules/stream/python/bindings/hdf5_event_file_writer_python.cpp @@ -0,0 +1,78 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/hdf5_event_file_writer.h" +#include "pb_doc_stream.h" + +namespace py = pybind11; + +namespace Metavision { + +void export_hdf5_event_file_writer(py::module &m) { + py::class_(m, "HDF5EventFileWriter", pybind_doc_stream["Metavision::HDF5EventFileWriter"]) + .def(py::init>(), + py::arg("path") = "", py::arg("metadata_map") = std::unordered_map()) + .def("open", &HDF5EventFileWriter::open, py::arg("path"), + pybind_doc_stream["Metavision::EventFileWriter::open"]) + .def("close", &HDF5EventFileWriter::close, pybind_doc_stream["Metavision::EventFileWriter::close"]) + .def("is_open", &HDF5EventFileWriter::is_open, pybind_doc_stream["Metavision::EventFileWriter::is_open"]) + .def("flush", &HDF5EventFileWriter::flush, pybind_doc_stream["Metavision::EventFileWriter::flush"]) + .def("add_metadata", &HDF5EventFileWriter::add_metadata, py::arg("key"), py::arg("value"), + pybind_doc_stream["Metavision::EventFileWriter::add_metadata"]) + .def("add_metadata_map_from_camera", &HDF5EventFileWriter::add_metadata_map_from_camera, py::arg("camera"), + pybind_doc_stream["Metavision::EventFileWriter::add_metadata_map_from_camera"]) + .def( + "add_cd_events", + [](HDF5EventFileWriter &writer, py::array_t buffer) { + py::buffer_info buffer_info = buffer.request(); + if (buffer_info.ndim > 1) { + throw std::invalid_argument("EventFileWriter.add_cd_events expects one dimentional arrays"); + } + if (buffer_info.itemsize != sizeof(EventCD)) { + throw std::invalid_argument("EventFileWriter.add_cd_events received array with invalid items"); + } + bool res = writer.add_events(static_cast(buffer_info.ptr), + static_cast(buffer_info.ptr) + buffer_info.size); + }, + py ::arg("events"), + "Adds an array of EventCD to write to the file\n" + "\n" + "Args:\n" + " events: numpy array of EventCD\n") + .def( + "add_ext_trigger_events", + [](HDF5EventFileWriter &writer, py::array_t buffer) { + py::buffer_info buffer_info = buffer.request(); + if (buffer_info.ndim > 1) { + throw std::invalid_argument( + "EventFileWriter.add_ext_trigger_events expects one dimentional arrays"); + } + if (buffer_info.itemsize != sizeof(EventExtTrigger)) { + throw std::invalid_argument( + "EventFileWriter.add_ext_trigger_events received array with invalid items"); + } + bool res = writer.add_events(static_cast(buffer_info.ptr), + static_cast(buffer_info.ptr) + buffer_info.size); + }, + py ::arg("events"), + "Adds an array of EventExtTrigger to write to the file\n" + "\n" + "Args:\n" + " events: numpy array of EventExtTrigger\n"); +} + +} // namespace Metavision diff --git a/sdk/modules/stream/python/bindings/metavision_sdk_stream_bindings.cpp b/sdk/modules/stream/python/bindings/metavision_sdk_stream_bindings.cpp new file mode 100644 index 000000000..21661a8e7 --- /dev/null +++ b/sdk/modules/stream/python/bindings/metavision_sdk_stream_bindings.cpp @@ -0,0 +1,71 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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. * + **********************************************************************************************************************/ + +#ifdef _WIN32 +#define MODULE_NAME metavision_sdk_stream_internal +#else +#define MODULE_NAME metavision_sdk_stream +#endif + +#include +#include +#if defined(__APPLE__) +#include +#include "metavision/sdk/base/events/event_cd.h" +#endif +#include "metavision/sdk/base/utils/python_bindings_doc.h" +#include "pb_doc_stream.h" + +#ifdef GENERATE_DOC_PYTHON_BINDINGS_USING_CPP_COMMENTS +#include "python_doc_strings.stream.hpp" +#endif + +namespace py = pybind11; + +namespace Metavision { + +#ifdef GENERATE_DOC_PYTHON_BINDINGS_USING_CPP_COMMENTS +PythonBindingsDoc pybind_doc_stream(Metavision::PythonDoc::python_doc_strings_stream); + +#else +PythonBindingsDoc pybind_doc_stream; +#endif + +void export_camera(py::module &); +void export_hdf5_event_file_writer(py::module &); +void export_raw_evt2_event_file_writer(py::module &); +} // namespace Metavision + +PYBIND11_MODULE(MODULE_NAME, m) { + // 1. Import dependencies + try { + py::module::import("metavision_sdk_base"); + } catch (const std::exception &e) { + std::cerr << "Exception Raised while loading metavision_sdk_base: " << e.what() << std::endl; + throw(e); + } + + try { + py::module::import("metavision_hal"); + } catch (const std::exception &e) { + std::cerr << "Exception Raised while loading metavision_hal: " << e.what() << std::endl; + throw(e); + } + +#if defined(__APPLE__) + PYBIND11_NUMPY_DTYPE(Metavision::Event2d, x, y, p, t); + PYBIND11_NUMPY_DTYPE(Metavision::EventCD, x, y, p, t); +#endif + + Metavision::export_camera(m); + Metavision::export_hdf5_event_file_writer(m); + Metavision::export_raw_evt2_event_file_writer(m); +} diff --git a/sdk/modules/driver/cpp/src/geometry.cpp b/sdk/modules/stream/python/bindings/pb_doc_stream.h similarity index 77% rename from sdk/modules/driver/cpp/src/geometry.cpp rename to sdk/modules/stream/python/bindings/pb_doc_stream.h index bf3664e64..1cf1bdfb5 100644 --- a/sdk/modules/driver/cpp/src/geometry.cpp +++ b/sdk/modules/stream/python/bindings/pb_doc_stream.h @@ -9,24 +9,14 @@ * See the License for the specific language governing permissions and limitations under the License. * **********************************************************************************************************************/ -#include "metavision/sdk/driver/geometry.h" +#ifndef METAVISION_SDK_CORE_PYTHON_BINDINGS_DOC_STREAM_H +#define METAVISION_SDK_CORE_PYTHON_BINDINGS_DOC_STREAM_H -namespace Metavision { - -Geometry::Geometry(I_Geometry *geom) : pimpl_(geom) {} - -Geometry::~Geometry() {} - -int Geometry::width() const { - return pimpl_->get_width(); -} - -int Geometry::height() const { - return pimpl_->get_height(); -} +#include +#include "metavision/sdk/base/utils/python_bindings_doc.h" -I_Geometry *Geometry::get_facility() const { - return pimpl_; +namespace Metavision { +extern PythonBindingsDoc pybind_doc_stream; } -} // namespace Metavision +#endif // METAVISION_SDK_CORE_PYTHON_BINDINGS_DOC_STREAM_H diff --git a/sdk/modules/stream/python/bindings/raw_evt2_event_file_writer_python.cpp b/sdk/modules/stream/python/bindings/raw_evt2_event_file_writer_python.cpp new file mode 100644 index 000000000..d54b90868 --- /dev/null +++ b/sdk/modules/stream/python/bindings/raw_evt2_event_file_writer_python.cpp @@ -0,0 +1,83 @@ +/********************************************************************************************************************** + * Copyright (c) Prophesee S.A. * + * * + * 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 "metavision/sdk/stream/camera.h" +#include "metavision/sdk/stream/raw_evt2_event_file_writer.h" +#include "pb_doc_stream.h" + +namespace py = pybind11; + +namespace Metavision { + +void export_raw_evt2_event_file_writer(py::module &m) { + py::class_(m, "RAWEvt2EventFileWriter", + pybind_doc_stream["Metavision::RAWEvt2EventFileWriter"]) + .def(py::init &, timestamp>(), + py::arg("stream_width"), py::arg("stream_height"), py::arg("path") = std::filesystem::path(), + py::arg("enable_trigger_support") = false, + py::arg("metadata_map") = std::unordered_map(), + py::arg("max_events_add_latency") = std::numeric_limits::max()) + .def("open", &RAWEvt2EventFileWriter::open, py::arg("path"), + pybind_doc_stream["Metavision::EventFileWriter::open"]) + .def("close", &RAWEvt2EventFileWriter::close, pybind_doc_stream["Metavision::EventFileWriter::close"]) + .def("is_open", &RAWEvt2EventFileWriter::is_open, pybind_doc_stream["Metavision::EventFileWriter::is_open"]) + .def("flush", &RAWEvt2EventFileWriter::flush, pybind_doc_stream["Metavision::EventFileWriter::flush"]) + .def("add_metadata", &RAWEvt2EventFileWriter::add_metadata, py::arg("key"), py::arg("value"), + pybind_doc_stream["Metavision::EventFileWriter::add_metadata"]) + .def( + "add_cd_events", + [](RAWEvt2EventFileWriter &writer, py::array_t buffer) { + py::buffer_info buffer_info = buffer.request(); + if (buffer_info.ndim > 1) { + throw std::invalid_argument("EventFileWriter.add_cd_events expects one dimentional arrays"); + } + if (buffer_info.itemsize != sizeof(EventCD)) { + throw std::invalid_argument("EventFileWriter.add_cd_events received array with invalid items"); + } + bool res = writer.add_events(static_cast(buffer_info.ptr), + static_cast(buffer_info.ptr) + buffer_info.size); + }, + py ::arg("events"), + "Adds an array of EventCD to write to the file\n" + "\n" + "Args:\n" + " events: numpy array of EventCD\n") + .def( + "add_ext_trigger_events", + [](RAWEvt2EventFileWriter &writer, py::array_t buffer) { + py::buffer_info buffer_info = buffer.request(); + if (buffer_info.ndim > 1) { + throw std::invalid_argument( + "EventFileWriter.add_ext_trigger_events expects one dimentional arrays"); + } + if (buffer_info.itemsize != sizeof(EventExtTrigger)) { + throw std::invalid_argument( + "EventFileWriter.add_ext_trigger_events received array with invalid items"); + } + bool res = writer.add_events(static_cast(buffer_info.ptr), + static_cast(buffer_info.ptr) + buffer_info.size); + }, + py ::arg("events"), + "Adds an array of EventExtTrigger to write to the file\n" + "\n" + "Args:\n" + " events: numpy array of EventExtTrigger\n"); +} + +} // namespace Metavision diff --git a/sdk/modules/driver/CMakeLists.txt b/sdk/modules/stream/python/samples/CMakeLists.txt similarity index 92% rename from sdk/modules/driver/CMakeLists.txt rename to sdk/modules/stream/python/samples/CMakeLists.txt index c3641ee89..6ea35bfc7 100644 --- a/sdk/modules/driver/CMakeLists.txt +++ b/sdk/modules/stream/python/samples/CMakeLists.txt @@ -7,5 +7,4 @@ # 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. -# C++ -add_subdirectory(cpp) \ No newline at end of file +add_subdirectory(metavision_raw_evt_encoder) \ No newline at end of file diff --git a/sdk/modules/stream/python/samples/metavision_raw_evt_encoder/CMakeLists.txt b/sdk/modules/stream/python/samples/metavision_raw_evt_encoder/CMakeLists.txt new file mode 100644 index 000000000..ecab46cb3 --- /dev/null +++ b/sdk/modules/stream/python/samples/metavision_raw_evt_encoder/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +install(FILES metavision_raw_evt_encoder.py + DESTINATION share/metavision/sdk/stream/python_samples/metavision_raw_evt_encoder + COMPONENT metavision-sdk-stream-python-samples +) diff --git a/sdk/modules/stream/python/samples/metavision_raw_evt_encoder/metavision_raw_evt_encoder.py b/sdk/modules/stream/python/samples/metavision_raw_evt_encoder/metavision_raw_evt_encoder.py new file mode 100644 index 000000000..b7e2ed8e0 --- /dev/null +++ b/sdk/modules/stream/python/samples/metavision_raw_evt_encoder/metavision_raw_evt_encoder.py @@ -0,0 +1,77 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +""" +This application demonstrates how to use Metavision SDK Stream module to decode an event recording, process it and +encode it back to RAW EVT2 format. +""" + +import os +import sys +from metavision_sdk_base import EventCDBuffer +from metavision_core.event_io import EventsIterator +from metavision_sdk_core import FlipYAlgorithm +from metavision_sdk_stream import RAWEvt2EventFileWriter + + +def parse_args(): + import argparse + """Parse command line arguments.""" + parser = argparse.ArgumentParser(description='Metavision RAW EVT encoder sample.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-i', '--input-event-file', type=str, dest='event_file_path', + required=True, help="Path to input event file (RAW or HDF5)") + parser.add_argument('-o', '--output-file', type=str, dest='output_file', default="", + help="Path to RAW output file. If not specified, will use a modified version of the input path.") + parser.add_argument('--encode-triggers', action='store_true', dest='encode_triggers', + help="Flag to activate encoding of external trigger events.") + parser.add_argument('--max-event-latency', type=int, dest='max_event_latency', default=-1, + help="Maximum latency in camera time for the reception of events, infinite by default.") + parser.add_argument('-s', '--start-ts', type=int, + default=0, help="Start time in microsecond") + parser.add_argument('-d', '--max-duration', type=int, + default=sys.maxsize, help="Maximum duration in microsecond") + parser.add_argument('--delta-t', type=int, default=100000, + help="Duration of served event slice in us.") + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + + if not os.path.isfile(args.event_file_path): + raise TypeError(f'Fail to access file: {args.event_file_path}') + if args.output_file == "": + args.output_file = args.event_file_path[:-4] + "_evt_encoded.raw" + + mv_iterator = EventsIterator(input_path=args.event_file_path, delta_t=args.delta_t, start_ts=args.start_ts, + max_duration=args.max_duration) + stream_height, stream_width = mv_iterator.get_size() + yflipper = FlipYAlgorithm(stream_height-1) + writer = RAWEvt2EventFileWriter( + stream_width, stream_height, args.output_file, args.encode_triggers, {}, args.max_event_latency) + + print("Processing input file...") + evs_processed_buf = EventCDBuffer() + for evs in mv_iterator: + yflipper.process_events(evs, evs_processed_buf) + writer.add_cd_events(evs_processed_buf) + if args.encode_triggers: + writer.add_ext_trigger_events( + mv_iterator.reader.get_ext_trigger_events()) + mv_iterator.reader.clear_ext_trigger_events() + + writer.flush() + writer.close() + print("Done!") + + +if __name__ == "__main__": + main() diff --git a/sdk/modules/stream/python/tests/CMakeLists.txt b/sdk/modules/stream/python/tests/CMakeLists.txt new file mode 100644 index 000000000..45682b017 --- /dev/null +++ b/sdk/modules/stream/python/tests/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +lfs_download("datasets/openeb/gen4_evt3_hand.raw" VALIDATION) +lfs_download("datasets/openeb/gen4_evt3_hand.hdf5" VALIDATION) + +add_sdk_python_module_test(stream) + +set(HDF5_ECF_PLUGIN_BUILD_PATH "${CMAKE_BINARY_DIR}/lib/hdf5/plugin") +get_prepended_env_paths(HDF5_PLUGIN_PATH hdf5_plugin_path "${HDF5_ECF_PLUGIN_BUILD_PATH}" "${HDF5_ECF_PLUGIN_DEB_INSTALL_PATH}") +set_property(TEST pytests_stream APPEND PROPERTY ENVIRONMENT "HDF5_PLUGIN_PATH=${hdf5_plugin_path}") diff --git a/sdk/modules/stream/python/tests/metavision_sdk_stream_bindings_pytest.py b/sdk/modules/stream/python/tests/metavision_sdk_stream_bindings_pytest.py new file mode 100644 index 000000000..89f141075 --- /dev/null +++ b/sdk/modules/stream/python/tests/metavision_sdk_stream_bindings_pytest.py @@ -0,0 +1,148 @@ +# Copyright (c) Prophesee S.A. +# +# 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. + +import os +import pytest + +import metavision_sdk_base +import metavision_sdk_stream + +# pylint: disable=no-member + + +def pytestcase_camera_from_raw_file(dataset_dir): + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + assert (camera is not None) + + +def pytestcase_camera_from_raw_file_pathlib(dataset_dir): + import pathlib + camera = metavision_sdk_stream.Camera.from_file(pathlib.Path(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + assert(camera is not None) + + +def pytestcase_camera_from_hdf5_file(dataset_dir): + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.hdf5")) + assert (camera is not None) + + +def pytestcase_camera_access_facility(dataset_dir): + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + assert (camera is not None) + geom = camera.get_device().get_i_geometry() + assert (geom is not None) + assert (geom.get_width() == 1280 and geom.get_height() == 720) + + +def pytestcase_camera_check_geometry(dataset_dir): + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.hdf5")) + assert (camera is not None) + assert (camera.width() == 1280 and camera.height() == 720) + + +def pytestcase_camera_check_geometry(dataset_dir): + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.hdf5")) + assert (camera is not None) + assert (camera.width() == 1280 and camera.height() == 720) + + +def pytestcase_camera_from_file_config_hints(dataset_dir): + fch = metavision_sdk_stream.FileConfigHints( + ).real_time_playback(False).max_memory(1024 * 1024) + + assert (fch.max_memory() == 1024 * 1024) + assert (not fch.real_time_playback()) + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.raw"), + fch) + assert (camera is not None) + + +def pytestcase_hdf5_file_writer_test(tmpdir, dataset_dir): + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + file_writer = metavision_sdk_stream.HDF5EventFileWriter() + file_writer.open(os.path.join(tmpdir, "hdf5_written_file.hdf5")) + file_writer.add_metadata_map_from_camera(camera) + buf = metavision_sdk_base.EventCDBuffer(10) + np_from_buf = buf.numpy() + for i in range(0, 10): + np_from_buf[i]["x"] = 1 + np_from_buf[i]["y"] = 1 + np_from_buf[i]["p"] = 1 + np_from_buf[i]["t"] = 1 + + file_writer.add_cd_events(np_from_buf) + + buf = metavision_sdk_base.EventExtTriggerBuffer(1) + np_from_buf = buf.numpy() + np_from_buf[0]["p"] = 0 + file_writer.add_ext_trigger_events(np_from_buf) + + file_writer.flush() + file_writer.close() + + +def pytestcase_raw_evt2_file_writer_test(tmpdir, dataset_dir): + camera = metavision_sdk_stream.Camera.from_file(os.path.join(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + file_writer = metavision_sdk_stream.RAWEvt2EventFileWriter( + camera.width(), camera.height(), "", True) + file_writer.open(os.path.join(tmpdir, "rawevt2_written_file.raw")) + buf = metavision_sdk_base.EventCDBuffer(10) + np_from_buf = buf.numpy() + for i in range(0, 10): + np_from_buf[i]["x"] = 1 + np_from_buf[i]["y"] = 1 + np_from_buf[i]["p"] = 1 + np_from_buf[i]["t"] = i + + file_writer.add_cd_events(np_from_buf) + + buf = metavision_sdk_base.EventExtTriggerBuffer(1) + np_from_buf = buf.numpy() + np_from_buf[0]["p"] = 0 + np_from_buf[0]["id"] = 6 + np_from_buf[0]["t"] = 5 + file_writer.add_ext_trigger_events(np_from_buf) + + file_writer.flush() + file_writer.close() + + +def pytestcase_hdf5_file_writer_pathlib_test(tmpdir, dataset_dir): + import pathlib + camera = metavision_sdk_stream.Camera.from_file(pathlib.Path(dataset_dir, + "openeb", "gen4_evt3_hand.raw")) + file_writer = metavision_sdk_stream.HDF5EventFileWriter(pathlib.Path(tmpdir, + "hdf5_written_file.hdf5")) + file_writer.add_metadata_map_from_camera(camera) + buf = metavision_sdk_base.EventCDBuffer(10) + np_from_buf = buf.numpy() + for i in range(0, 10): + np_from_buf[i]["x"] = 1 + np_from_buf[i]["y"] = 1 + np_from_buf[i]["p"] = 1 + np_from_buf[i]["t"] = 1 + + file_writer.add_cd_events(np_from_buf) + + buf = metavision_sdk_base.EventExtTriggerBuffer(1) + np_from_buf = buf.numpy() + np_from_buf[0]["p"] = 0 + file_writer.add_ext_trigger_events(np_from_buf) + + file_writer.flush() + file_writer.close() diff --git a/sdk/modules/ui/cpp/include/metavision/sdk/ui/detail/texture_utils.h b/sdk/modules/ui/cpp/include/metavision/sdk/ui/detail/texture_utils.h index 3e6517b48..a255e372e 100644 --- a/sdk/modules/ui/cpp/include/metavision/sdk/ui/detail/texture_utils.h +++ b/sdk/modules/ui/cpp/include/metavision/sdk/ui/detail/texture_utils.h @@ -30,10 +30,6 @@ struct TextureOptions { unsigned int initialize_texture(const TextureOptions &options); -[[deprecated("This function is deprecated since version 4.2.0. Please use initialize_texture(const TextureOptions &) " - "instead.")]] unsigned int - initialize_texture(int width, int height, bool is_gray); - void upload_texture(const cv::Mat &img, const unsigned int &tex_id); } // namespace detail diff --git a/sdk/modules/ui/cpp/include/metavision/sdk/ui/pipeline/frame_display_stage.h b/sdk/modules/ui/cpp/include/metavision/sdk/ui/pipeline/frame_display_stage.h deleted file mode 100644 index 124881b9d..000000000 --- a/sdk/modules/ui/cpp/include/metavision/sdk/ui/pipeline/frame_display_stage.h +++ /dev/null @@ -1,77 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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. * - **********************************************************************************************************************/ - -#ifndef METAVISION_SDK_CORE_FRAME_DISPLAY_STAGE_H -#define METAVISION_SDK_CORE_FRAME_DISPLAY_STAGE_H - -#include -#include - -#include "metavision/sdk/base/utils/sdk_log.h" -#include "metavision/sdk/core/pipeline/base_stage.h" -#include "metavision/sdk/core/pipeline/pipeline.h" -#include "metavision/sdk/ui/utils/window.h" -#include "metavision/sdk/ui/utils/event_loop.h" - -namespace Metavision { - -/// @brief Stage that displays the input frame in a window -/// -/// The window is refreshed every time a new frame is received. -class FrameDisplayStage : public BaseStage { -public: - using FramePool = SharedObjectPool; - using FramePtr = FramePool::ptr_type; - using FrameData = std::pair; - - /// @brief Constructs a new frame display stage - /// @param title Window's title - /// @param width Window's initial width - /// @param height Window's initial height - /// @param mode Window's rendering mode (i.e. either BGR or GRAY). Cannot be changed afterwards - /// @param auto_exit Flag indicating if the application automatically closes if the user presses 'Q' or 'ESCAPE' - /// @warning Must only be called from the main thread - FrameDisplayStage(const std::string &title, int width, int height, - Window::RenderMode mode = Window::RenderMode::BGR, bool auto_exit = true); - - /// @brief Constructs a new frame display stage given an explicit previous stage - /// @param prev_stage Stage producing the input image for this display stage - /// @param title Window's title - /// @param width Window's initial width - /// @param height Window's initial height - /// @param mode Window's rendering mode (i.e. either BGR or GRAY). Cannot be changed afterwards - /// @param auto_exit Flag indicating if the application automatically closes if the user presses 'Q' or 'ESCAPE' - /// @warning Must only be called from the main thread - FrameDisplayStage(BaseStage &prev_stage, const std::string &title, int width, int height, - Window::RenderMode mode = Window::RenderMode::BGR, bool auto_exit = true); - - /// @brief Destructor - /// @warning Must only be called from the main thread - ~FrameDisplayStage(); - - /// @brief Sets a callback that is called when the user presses a key - /// - /// @note The callback is only called when the window has the focus - /// @param cb The callback to call - void set_key_callback(const Window::KeyCallback &cb); - -private: - void init(bool auto_exit); - - // Key pressed callback - Window window_; - Window::KeyCallback on_key_cb_; - static std::uint32_t instance_counter_; -}; - -} // namespace Metavision - -#endif // METAVISION_SDK_CORE_FRAME_DISPLAY_STAGE_H diff --git a/sdk/modules/ui/cpp/src/CMakeLists.txt b/sdk/modules/ui/cpp/src/CMakeLists.txt index ea95c3506..780c38350 100644 --- a/sdk/modules/ui/cpp/src/CMakeLists.txt +++ b/sdk/modules/ui/cpp/src/CMakeLists.txt @@ -10,7 +10,6 @@ target_sources(metavision_sdk_ui PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/base_glfw_window.cpp ${CMAKE_CURRENT_SOURCE_DIR}/base_window.cpp ${CMAKE_CURRENT_SOURCE_DIR}/event_loop.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/frame_display_stage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mt_window.cpp ${CMAKE_CURRENT_SOURCE_DIR}/texture_utils.cpp ${CMAKE_CURRENT_SOURCE_DIR}/window.cpp diff --git a/sdk/modules/ui/cpp/src/frame_display_stage.cpp b/sdk/modules/ui/cpp/src/frame_display_stage.cpp deleted file mode 100644 index 84c4cf98f..000000000 --- a/sdk/modules/ui/cpp/src/frame_display_stage.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/********************************************************************************************************************** - * Copyright (c) Prophesee S.A. * - * * - * 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 "metavision/sdk/ui/pipeline/frame_display_stage.h" - -namespace Metavision { - -std::uint32_t FrameDisplayStage::instance_counter_ = 0; - -FrameDisplayStage::FrameDisplayStage(const std::string &title, int width, int height, Window::RenderMode mode, - bool auto_exit) : - window_(title, width, height, mode) { - init(auto_exit); -} - -FrameDisplayStage::FrameDisplayStage(BaseStage &prev_stage, const std::string &title, int width, int height, - Window::RenderMode mode, bool auto_exit) : - FrameDisplayStage(title, width, height, mode, auto_exit) { - set_previous_stage(prev_stage); -} - -FrameDisplayStage::~FrameDisplayStage() { - --instance_counter_; -} - -void FrameDisplayStage::set_key_callback(const Window::KeyCallback &cb) { - on_key_cb_ = cb; -} - -void FrameDisplayStage::init(bool auto_exit) { - if (instance_counter_++ == 0) { - set_setup_callback([this]() { pipeline().add_pre_step_callback([]() { EventLoop::poll_and_dispatch(); }); }); - } - - set_consuming_callback([this](const boost::any &data) { - try { - auto res = boost::any_cast(data); - timestamp t = res.first; - FramePtr &f = res.second; - if (f && !f->empty()) - window_.show(*f); - } catch (boost::bad_any_cast &c) { MV_SDK_LOG_ERROR() << c.what(); } - }); - - window_.set_keyboard_callback([this, auto_exit](UIKeyEvent key, int scancode, UIAction action, int mods) { - on_key_cb_(key, scancode, action, mods); - - if (auto_exit) { - if (action == UIAction::RELEASE) { - if (key == UIKeyEvent::KEY_ESCAPE || key == UIKeyEvent::KEY_Q) - this->pipeline().cancel(); - } - } - }); - - on_key_cb_ = [](UIKeyEvent key, int scancode, UIAction action, int mods) {}; -} - -} // namespace Metavision \ No newline at end of file diff --git a/sdk/modules/ui/cpp/src/texture_utils.cpp b/sdk/modules/ui/cpp/src/texture_utils.cpp index 7e7faa1e2..11e3f99b9 100644 --- a/sdk/modules/ui/cpp/src/texture_utils.cpp +++ b/sdk/modules/ui/cpp/src/texture_utils.cpp @@ -52,13 +52,6 @@ unsigned int initialize_texture(const TextureOptions &options) { return tex_id; } -unsigned int initialize_texture(int width, int height, bool is_gray) { - const TextureOptions opt = {static_cast(width), static_cast(height), - is_gray ? TextureFormat::Gray : TextureFormat::RGB, TextureFilter::Linear, - TextureFilter::Linear}; - return initialize_texture(opt); -} - static std::unordered_map cv_to_gl_internal_format = { {CV_8UC1, GL_R8}, {CV_8UC3, GL_RGB8}, {CV_8UC4, GL_RGBA8}}; diff --git a/standalone_samples/test/raw_file_decoder_with_hal.cpp b/standalone_samples/test/raw_file_decoder_with_hal.cpp index c31c0e584..52c74bcb2 100644 --- a/standalone_samples/test/raw_file_decoder_with_hal.cpp +++ b/standalone_samples/test/raw_file_decoder_with_hal.cpp @@ -109,7 +109,7 @@ int main(int argc, char *argv[]) { auto ev_buffer = i_eventsstream->get_latest_raw_data(); // Decode the raw buffer - i_decoder->decode(ev_buffer->data(), ev_buffer->data() + ev_buffer->size()); + i_decoder->decode(ev_buffer.begin(), ev_buffer.end()); } return 0; diff --git a/utils/containers/Dockerfile.OpenEB b/utils/containers/Dockerfile.OpenEB index afb6faec9..4e9b5938a 100644 --- a/utils/containers/Dockerfile.OpenEB +++ b/utils/containers/Dockerfile.OpenEB @@ -1,13 +1,16 @@ -# This is the command to build the Docker image for Ubuntu 20.04 -# 'docker build --build-arg UBUNTU_VERSION=20.04 -t openeb:ubuntu-20.04 .' -# If you want to build for Ubuntu 22.04, replace "20.04" to "22.04" +# This is the command to build the Docker image for Ubuntu 20.04 from the root +# of the source folder +# 'docker build --build-arg BASE_IMAGE_TAG=22.04 -t openeb:ubuntu-22.04 -f utils/jenkins/containers/Dockerfile.OpenEB .' +# If you want to build for Ubuntu 24.04, replace "22.04" to "24.04" -ARG UBUNTU_VERSION -FROM ubuntu:${UBUNTU_VERSION} +ARG BASE_IMAGE_TAG +FROM ubuntu:${BASE_IMAGE_TAG} ENV DEBIAN_FRONTEND "noninteractive" ENV TZ "Europe/Paris" +COPY ./utils/python/requirements_openeb.txt ./openeb_environment/requirements_openeb.txt + # Install dependencies RUN apt-get update && apt-get -y install \ apt-utils \ @@ -32,20 +35,22 @@ RUN apt-get update && apt-get -y install \ libgtest-dev \ libgmock-dev \ python3-pip \ - python3-distutils \ python3-dev \ + python3-venv \ && rm -rf /var/lib/apt/lists/* +RUN python3 -m venv /opt/prophesee/psee-py3venv --system-site-packages + # Install pip dependencies -RUN python3 -m pip install pip --upgrade \ - && python3 -m pip install "opencv-python==4.5.5.64" "sk-video==1.1.10" "fire==0.4.0" "numpy==1.23.4" "h5py==3.7.0" \ - pandas scipy jupyter jupyterlab matplotlib "ipywidgets==7.6.5" pytest command_runner "numba==0.56.3" \ - "profilehooks==1.12.0" "pytorch_lightning==1.8.6" "tqdm==4.63.0" "kornia==0.6.8" scikit-image \ +RUN /opt/prophesee/psee-py3venv/bin/python3 -m pip install pip --upgrade \ + && /opt/prophesee/psee-py3venv/bin/python3 -m pip install -r openeb_environment/requirements_openeb.txt \ && rm -rf ~/.cache/pip/* # Pybind11 -RUN wget -O /tmp/pybind11.zip https://github.com/pybind/pybind11/archive/v2.6.0.zip \ +RUN wget -O /tmp/pybind11.zip https://github.com/pybind/pybind11/archive/v2.12.0.zip \ && unzip /tmp/pybind11.zip -d /opt \ - && cmake -S /opt/pybind11-2.6.0 -B /tmp/pybind11_build -DPYBIND11_TEST=OFF \ + && cmake -S /opt/pybind11-2.12.0 -B /tmp/pybind11_build -DPYBIND11_TEST=OFF \ && cmake --build /tmp/pybind11_build --target install -j`nproc` \ - && rm -rf /tmp/pybind11* \ No newline at end of file + && rm -rf /tmp/pybind11* + +RUN rm -rf openeb_environment diff --git a/utils/cpp/gtest/include/metavision/utils/gtest/detail/temporary_directory_handler_impl.h b/utils/cpp/gtest/include/metavision/utils/gtest/detail/temporary_directory_handler_impl.h index b6c5dc6ad..4dda1978b 100644 --- a/utils/cpp/gtest/include/metavision/utils/gtest/detail/temporary_directory_handler_impl.h +++ b/utils/cpp/gtest/include/metavision/utils/gtest/detail/temporary_directory_handler_impl.h @@ -12,6 +12,7 @@ #ifndef METAVISION_UTILS_GTEST_DETAIL_TEMPORARY_DIRECTORY_HANDLER_IMPL_H #define METAVISION_UTILS_GTEST_DETAIL_TEMPORARY_DIRECTORY_HANDLER_IMPL_H +#include #include namespace Metavision { @@ -23,27 +24,31 @@ inline TemporaryDirectoryHandler::TemporaryDirectoryHandler(const std::string &d int counter = 1; do { tmpdir_ = - boost::filesystem::temp_directory_path() / boost::filesystem::path(dir_name + std::to_string(counter++)); - } while (boost::filesystem::exists(tmpdir_)); + std::filesystem::temp_directory_path() / std::filesystem::path(dir_name + std::to_string(counter++)); + } while (std::filesystem::exists(tmpdir_)); - if (!boost::filesystem::create_directory(tmpdir_)) { + if (!std::filesystem::create_directory(tmpdir_)) { throw std::runtime_error("Could not create temporary directory " + tmpdir_.string()); } } inline TemporaryDirectoryHandler::~TemporaryDirectoryHandler() { - if (!boost::filesystem::remove_all(tmpdir_)) { + if (remove_on_destruction_ && std::filesystem::remove_all(tmpdir_) == 0) { // one reason can be the directory was deleted manually by the user while program is running - std::cerr << "Could not delete temporary directory" << tmpdir_.string() << std::endl; + std::cerr << "Could not delete temporary directory" << tmpdir_ << std::endl; } } inline std::string TemporaryDirectoryHandler::get_tmpdir_path() const { - return boost::filesystem::canonical(tmpdir_).make_preferred().string(); + return std::filesystem::canonical(tmpdir_).make_preferred().string(); } inline std::string TemporaryDirectoryHandler::get_full_path(const std::string &file_basename) const { - return (tmpdir_ / boost::filesystem::path(file_basename)).string(); + return (tmpdir_ / std::filesystem::path(file_basename)).string(); +} + +inline void TemporaryDirectoryHandler::disable_remove_on_destruction() { + remove_on_destruction_ = false; } } // namespace Metavision diff --git a/utils/cpp/gtest/include/metavision/utils/gtest/temporary_directory_handler.h b/utils/cpp/gtest/include/metavision/utils/gtest/temporary_directory_handler.h index a2b16140f..bded41adb 100644 --- a/utils/cpp/gtest/include/metavision/utils/gtest/temporary_directory_handler.h +++ b/utils/cpp/gtest/include/metavision/utils/gtest/temporary_directory_handler.h @@ -12,8 +12,8 @@ #ifndef METAVISION_UTILS_GTEST_TEMPORARY_DIRECTORY_HANDLER_H #define METAVISION_UTILS_GTEST_TEMPORARY_DIRECTORY_HANDLER_H +#include #include -#include namespace Metavision { @@ -46,8 +46,11 @@ class TemporaryDirectoryHandler { /// @note It does NOT create the file/directory returned std::string get_full_path(const std::string &basename) const; + void disable_remove_on_destruction(); + private: - boost::filesystem::path tmpdir_; + std::filesystem::path tmpdir_; + bool remove_on_destruction_ = true; }; } // namespace Metavision diff --git a/utils/cpp/gtest/lib/CMakeLists.txt b/utils/cpp/gtest/lib/CMakeLists.txt index 2d89bc007..bdf5feb4d 100644 --- a/utils/cpp/gtest/lib/CMakeLists.txt +++ b/utils/cpp/gtest/lib/CMakeLists.txt @@ -24,7 +24,6 @@ set(gtest_link_libraries target_link_libraries(metavision_utils_gtest INTERFACE ${gtest_link_libraries} - Boost::filesystem Boost::program_options ) diff --git a/utils/cpp/profiling/include/metavision/utils/profiling/chrome_tracing_profiler.h b/utils/cpp/profiling/include/metavision/utils/profiling/chrome_tracing_profiler.h index f9933874a..4350df06f 100644 --- a/utils/cpp/profiling/include/metavision/utils/profiling/chrome_tracing_profiler.h +++ b/utils/cpp/profiling/include/metavision/utils/profiling/chrome_tracing_profiler.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -127,7 +128,7 @@ class ChromeTracingProfiler { void store_event(ProfileEvent &&event); - std::string output_path_; ///< Path to the file where profiling logs will be saved + std::filesystem::path output_path_; ///< Path to the file where profiling logs will be saved bool save_on_destruction_; ///< Flag to indicate if the profiling logs have to be saved when the destructor is ///< called chrono::time_point start_; ///< Starting timestamp diff --git a/utils/cpp/profiling/lib/CMakeLists.txt b/utils/cpp/profiling/lib/CMakeLists.txt index e60df953b..2a2155128 100644 --- a/utils/cpp/profiling/lib/CMakeLists.txt +++ b/utils/cpp/profiling/lib/CMakeLists.txt @@ -7,9 +7,6 @@ # 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. -# Boost::filesystem -find_package(Boost REQUIRED COMPONENTS filesystem system) - # Create shared library for internal profiling tools: add_library(metavision_utils_profiling INTERFACE) add_library(MetavisionUtils::profiling ALIAS metavision_utils_profiling) # Create alias target to refer to @@ -19,11 +16,6 @@ target_include_directories(metavision_utils_profiling $ ) -target_link_libraries(metavision_utils_profiling - INTERFACE - Boost::filesystem Boost::system -) - install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../include/" DESTINATION include ) diff --git a/utils/cpp/profiling/src/chrome_tracing_profiler.cpp b/utils/cpp/profiling/src/chrome_tracing_profiler.cpp index 3f9201841..cc8c2ef24 100644 --- a/utils/cpp/profiling/src/chrome_tracing_profiler.cpp +++ b/utils/cpp/profiling/src/chrome_tracing_profiler.cpp @@ -6,7 +6,6 @@ * A copy of these License T&C's is located in the "licensing" folder accompanying this file. * **********************************************************************************************************************/ -#include #include #include #include @@ -15,8 +14,6 @@ #include "metavision/utils/profiling/chrome_tracing_profiler.h" #include "metavision/utils/profiling/utils/chrome_tracing_event_serializer.h" -namespace fs = boost::filesystem; - namespace Profiling { #ifdef ENABLE_MAIN_PROFILER @@ -78,9 +75,7 @@ void ChromeTracingProfiler::add_counter_event(const std::string &name, const std } ChromeTracingProfiler::ChromeTracingProfiler(const std::string &name, bool save_on_destruction) { - fs::path output_path = fs::temp_directory_path() / fs::path(name); - - output_path_ = output_path.string(); + output_path_ = std::filesystem::temp_directory_path() / name; save_on_destruction_ = save_on_destruction; reset_impl(); } diff --git a/utils/python/metavision_utils/os_tools.py b/utils/python/metavision_utils/os_tools.py index 36423ac4e..0dcf657ab 100644 --- a/utils/python/metavision_utils/os_tools.py +++ b/utils/python/metavision_utils/os_tools.py @@ -34,7 +34,7 @@ def shorten_path(path, length=80): def which(program): - """"Tests if an executable program exists""" + """Tests if an executable program exists""" def is_exe(fpath): """Returns True if path is an executable""" return os.path.isfile(fpath) and os.access(fpath, os.X_OK) @@ -54,7 +54,7 @@ def is_exe(fpath): def get_parent_directory(filepath, level=1): - """"Return parent directory of a file + """Return parent directory of a file Args: filepath (str): path of the file diff --git a/utils/python/requirements_openeb.txt b/utils/python/requirements_openeb.txt new file mode 100644 index 000000000..76f28c187 --- /dev/null +++ b/utils/python/requirements_openeb.txt @@ -0,0 +1,20 @@ +command_runner +fire==0.4.0 +h5py +kornia +# Newer versions of networkx require python3.9 or newer +networkx<3 +numba>=0.58.1,<0.60 +opencv-python==4.5.5.64 +pandas +profilehooks==1.12.0 +pytest +--extra-index-url https://download.pytorch.org/whl/cpu +torch==2.2.1 +torchvision==0.17.1 +pytorch_lightning==2.2.1 +scipy +scikit-image +sk-video==1.1.10 +tensorboard +importlib-metadata<=7.1,>=6.0 diff --git a/utils/scripts/get_prefered_site_packages.py b/utils/scripts/get_prefered_site_packages.py new file mode 100644 index 000000000..384eb207c --- /dev/null +++ b/utils/scripts/get_prefered_site_packages.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 + +# Copyright (c) Prophesee S.A. - All Rights Reserved +# +# Subject to Prophesee Metavision Licensing Terms and Conditions ("License T&C's"). +# You may not use this file except in compliance with these License T&C's. +# A copy of these License T&C's is located in the "licensing" folder accompanying this file. + +import argparse +import functools +import site + +def parse_args(): + """Utility function to define and input arguments + + Returns: + argparse.ArgumentParser: to parse input arguments + """ + + parser = argparse.ArgumentParser( + add_help=True, formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('--site-type', type=str, required=True, choices=['system', 'local'], + help='Specifies the type of desired python site packages') + parser.add_argument('--prefer-pattern', action='append', default=[], + help='Provide additional patterns to look for in candidate site packages paths') + return parser.parse_args() + + +# select a suitable python module path by following ranking (i.e a path that meets +# criteria 1. is better than 2., and a path that meets criteria 1.+2. is better than 1.+3.) +# 1-a path that does not contain 'local' +# 2-a path that contains 'dist-packages' +# 3-a path that contains 'site-packages' +# 1-a path that does not contain '.local' +# 2-a path that does not contain 'home' +# 3-a path that does not contain '/opt/' +# 4-a path that does not contain '/local/' +# 5-a path that contains 'dist-packages' +# 6-a path that contains 'site-packages' +def system_site_score(site_path): + return (('.local' not in site_path) * 100000.0 + + ('home' not in site_path) * 10000.0 + + ('/opt/' not in site_path) * 1000.0 + + ('/local/' not in site_path) * 100.0 + + ('dist-packages' in site_path) * 10.0 + + ('site-packages' in site_path) * 1.0) + + +# select a suitable python module path by following ranking (i.e a path that meets +# criteria 1. is better than 2., and a path that meets criteria 1.+2.) +# 1-the cmake install prefix +# 2-a path that contains 'dist-packages' +def local_site_score(site_path): + return (('dist-packages' in site_path) * 10.0 + + ('site-packages' in site_path) * 1.0) + + +def prefered_patterns_score(site_path, prefer_patterns): + return functools.reduce(lambda score, pattern: score + (1000000.0 if pattern in site_path else 0.0), + prefer_patterns, 0.0) + + +def get_sorted_site_packages(site_score, prefer_patterns): + return sorted(site.getsitepackages(), + key=lambda path: prefered_patterns_score(path, prefer_patterns) + site_score(path), + reverse=True) + + +if __name__ == '__main__': + args = parse_args() + if args.site_type == 'system': + site_score = system_site_score + else: + site_score = local_site_score + print(get_sorted_site_packages(site_score, args.prefer_pattern)[0]) diff --git a/utils/windows/vcpkg.json b/utils/windows/vcpkg.json index 51884e0c7..5d3803a73 100644 --- a/utils/windows/vcpkg.json +++ b/utils/windows/vcpkg.json @@ -11,7 +11,8 @@ "eigen3", { "name" : "hdf5" , "features" : ["cpp","threadsafe","tools","zlib"] }, { "name" : "ogre", "default-features": false, "features" : ["assimp","overlay","zip"] }, - "protobuf" + "protobuf", + "ceres" ], "vcpkg-configuration" : { "default-registry": {