From e080e16874c6ec12d82991da65f51b7db859ed94 Mon Sep 17 00:00:00 2001 From: flipflip Date: Tue, 1 Sep 2026 12:55:15 +0200 Subject: [PATCH] fix extract --- .gitignore | 2 + fpsdk.sh | 19 +++++++--- fpsdk_apps/fpltool/fpltool_extract.cpp | 51 ++++++++++++++++---------- fpsdk_apps/fpltool/fpltool_extract.hpp | 1 + fpsdk_apps/fpltool/fpltool_opts.hpp | 14 ++++--- fpsdk_common/src/app.cpp | 7 ++-- 6 files changed, 60 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 30ef670..3bb2e40 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ CMakeCache.txt *.bak /.devcontainer/.bash_history.d /.devcontainer/.vscode-server +/.devcontainer/.claude +/.devcontainer/.local .devcontainer/.gdb/__pycache__ /ws /ws2 diff --git a/fpsdk.sh b/fpsdk.sh index f5b7465..8e2c9df 100755 --- a/fpsdk.sh +++ b/fpsdk.sh @@ -27,7 +27,8 @@ function main local volume_args= local docker_args= local dochecks=1 - while getopts ":hduxti:v:" opt; do + local hwaccel=0 + while getopts ":hduxtai:v:" opt; do case $opt in h) echo @@ -35,7 +36,7 @@ function main echo echo "This uses Docker images with pre-built binaries of the Fixposition SDK apps." echo - echo "Usage: $0 [-d] [-u] [-x] [-i ] [-v ...] ..." + echo "Usage: $0 [-d] [-u] [-x] [-t] [-a] [-i ] [-v ...] ..." echo echo "Where:" echo @@ -43,6 +44,7 @@ function main echo " -x Bypass checks (check for running in Docker, running as root, ...)" echo " -u Update (pull) the necessary Docker " echo " -t Executes with docker run --tty" + echo " -a Try to enable hw acceleration for video decoding" echo " -i Specifies which Docker image to use (default: trixie). Available images are:" echo " trixie -- Debian Trixie (no ROS, some functionality not available)" echo " noetic -- ROS1 Noetic (additional ROS1 functionality available)" @@ -91,6 +93,9 @@ function main t) docker_args="--tty" ;; + a) + hwaccel=1 + ;; i) image=${OPTARG} ;; @@ -183,10 +188,12 @@ function main args="${args} --user $(id -u):$(id -g) --volume /etc/passwd:/etc/passwd:ro --volume /etc/group:/etc/group:ro" # - Allow FFmpeg vaapi access on some systems. Note: this doesn't work with "-i noetic" (Ubuntu 20). # Related: https://github.com/joedefen/ffmpeg-vaapi-docker - if [ -r /dev/dri ]; then - args="${args} --device=/dev/dri" - rendergid=$(awk -F: '/^render:/ { print $3 }' /etc/group) - args="${args} --group-add ${rendergid}" + if [ ${hwaccel} -gt 0 ]; then + if [ -r /dev/dri ]; then + args="${args} --device=/dev/dri" + rendergid=$(awk -F: '/^render:/ { print $3 }' /etc/group) + args="${args} --group-add ${rendergid}" + fi fi [ ${DEBUG} -gt 0 ] && set -x diff --git a/fpsdk_apps/fpltool/fpltool_extract.cpp b/fpsdk_apps/fpltool/fpltool_extract.cpp index 13f0443..9788a8c 100644 --- a/fpsdk_apps/fpltool/fpltool_extract.cpp +++ b/fpsdk_apps/fpltool/fpltool_extract.cpp @@ -89,12 +89,12 @@ bool FplToolExtract::Run() return false; } - // Check which output formats we want + // Check which output formats we want. Keep defaults in sync with help screen! do_jsonl_ = opts_.formats_.empty(); do_raw_ = opts_.formats_.empty(); do_file_ = opts_.formats_.empty(); - do_ros_ = opts_.formats_.empty(); - do_cam_ = opts_.formats_.empty(); + do_ros_ = false; + do_cam_ = false; for (auto& fmt : opts_.formats_) { // clang-format off if (fmt == opts_.FORMAT_JSONL) { do_jsonl_ = true; } else if (fmt == opts_.FORMAT_RAW) { do_raw_ = true; } @@ -111,31 +111,37 @@ bool FplToolExtract::Run() return false; } + DEBUG("do_jsonl=%s do_raw=%s do_file=%s do_ros=%s do_cam=%s", ToStr(do_jsonl_), ToStr(do_raw_), ToStr(do_file_), + ToStr(do_ros_), ToStr(do_cam_)); + NOTICE("Extracting from %s to %s_...", input_fpl.c_str(), output_prefix_.c_str()); TicToc tt; + std::string output_bag; + if (do_ros_) { #if FPSDK_USE_ROS2 - const auto output_bag = output_prefix_ + "_bag"; // Directory! (even for single-file .mcap) + output_bag = output_prefix_ + "_bag"; // Directory! (even for single-file .mcap) #else - const auto output_bag = output_prefix_ + ".bag"; // File + output_bag = output_prefix_ + ".bag"; // File #endif - if (PathExists(output_bag)) { - if (!opts_.overwrite_) { - WARNING("Output bag %s already exists", output_bag.c_str()); - return false; - } else { - RemoveAll(output_bag); + if (PathExists(output_bag)) { + if (!opts_.overwrite_) { + WARNING("Output bag %s already exists", output_bag.c_str()); + return false; + } else { + RemoveAll(output_bag); + } } - } #if FPSDK_USE_ROS2 - if (do_ros_ && !bag_.Open(output_bag, opts_.mcap_, opts_.compress_)) { + if (do_ros_ && !bag_.Open(output_bag, opts_.mcap_, opts_.compress_)) { #else - if (do_ros_ && !bag_.Open(output_bag, opts_.compress_)) { + if (do_ros_ && !bag_.Open(output_bag, opts_.compress_)) { #endif - return false; - } + return false; + } - NOTICE("Extracting to %s", output_bag.c_str()); + NOTICE("Extracting to %s", output_bag.c_str()); + } // Handle SIGINT (C-c) to abort nicely SigIntHelper sig_int; @@ -508,8 +514,9 @@ FplToolExtract::ProcRes FplToolExtract::ProcessCamData(const FplMessage& fpl_msg } // Decode this frame - fut = std::async(std::launch::async, - [&dec, /*copy!*/ camdata]() -> AsyncDecData { return { camdata, dec->DecodeFrame(camdata.data_) }; }); + fut = std::async(std::launch::async, [&dec, /*copy!*/ camdata]() -> AsyncDecData { + return { camdata, dec->DecodeFrame(camdata.data_), dec->IsOkay() }; + }); break; } @@ -526,7 +533,11 @@ FplToolExtract::ProcRes FplToolExtract::ProcessAsyncDecData(const FplToolExtract auto& camdata = decdata.camdata_; if (!decdata.img_) { WARNING("No image from CAMDATA %s", camdata.info_.c_str()); - return ProcRes::ERROR; + if (!decdata.dec_is_okay_) { + return ProcRes::FATAL; + } else { + return ProcRes::ERROR; + } } auto& img = *decdata.img_; TRACE("CAMDATA decoded %s -> %dx%d %s", camdata.info_.c_str(), img.width_, img.height_, PixelFmtToStr(img.fmt_)); diff --git a/fpsdk_apps/fpltool/fpltool_extract.hpp b/fpsdk_apps/fpltool/fpltool_extract.hpp index 150667e..e85906f 100644 --- a/fpsdk_apps/fpltool/fpltool_extract.hpp +++ b/fpsdk_apps/fpltool/fpltool_extract.hpp @@ -89,6 +89,7 @@ class FplToolExtract { common::fpl::CamData camdata_; std::optional img_; + bool dec_is_okay_ = true; }; struct AsyncDecState { diff --git a/fpsdk_apps/fpltool/fpltool_opts.hpp b/fpsdk_apps/fpltool/fpltool_opts.hpp index 29dcd19..8f21c5c 100644 --- a/fpsdk_apps/fpltool/fpltool_opts.hpp +++ b/fpsdk_apps/fpltool/fpltool_opts.hpp @@ -122,7 +122,7 @@ class FplToolOptions : public common::app::ProgramOptions " -o, --output -- Output file prefix (default: derive from name)\n" " -S, --skip -- Skip seconds from start of log (default: 0, i.e. no skip)\n" " -D, --duration -- Process seconds of log (default: everything)\n" - " -e, --formats -- Comma-separated list of output formats for the extract (default: all)\n" + " -e, --formats -- Comma-separated list of output formats for the extract (default: jsonl,raw,file)\n" " -s, --scale -- Scale factor for decoded video frames: 0.1 - 1.0 (default: 1.0)\n" " -t, --pixelfmt -- Pixel format for decoded video frames: Y8, RGB24, GBRP (default: RGB24)\n" " -- The command, see below\n" @@ -240,10 +240,14 @@ class FplToolOptions : public common::app::ProgramOptions "\n" " fpltool -x dump some.fpl > some.txt\n" "\n" - " Extract all data from a .fpl file:\n" + " Extract some data from a .fpl file:\n" "\n" " fpltool extract some.fpl\n" "\n" + " Extract all data from a .fpl file:\n" + "\n" + " fpltool extract -e jsonl,raw,file,ros,cam some.fpl\n" + "\n" " Create a ROS some.bag file (ROS1) resp. some_bag directory (ROS2) from a .fpl file:\n" "\n" " fpltool extract -e ros,cam some.fpl\n" @@ -252,13 +256,13 @@ class FplToolOptions : public common::app::ProgramOptions " Create another.bag (ROS1, another_bag/ for ROS2) with 2 minutes of data starting 60 seconds\n" " into some.fpl:\n" "\n" - " fpltool rosbag some.fpl -c -c -o another.bag -S 60 -D 120\n" + " fpltool rosbag some.fpl -o another.bag -S 60 -D 120\n" "\n" " Check what is in the extracted ROS bag:\n" "\n" " rosbag info some.bag # ROS 1\n" - " ros2 bag info some_bag # ROS 2 (default, see above)\n" - " mcap info some_bag/some.mcap # ROS 2 (with -m, see above)\n" + " ros2 bag info some_bag # ROS 2 (default bag format)\n" + " mcap info some_bag/some.mcap # ROS 2 (with -m, mcap bag format)\n" "\n" " Create a ROS bag, convert encoded video (e.g. from PBx-A1 sensor) to greyscale images of half size:\n" "\n" diff --git a/fpsdk_common/src/app.cpp b/fpsdk_common/src/app.cpp index 8eb8c58..bb7d49e 100644 --- a/fpsdk_common/src/app.cpp +++ b/fpsdk_common/src/app.cpp @@ -404,10 +404,11 @@ void ProgramOptions::PrintVersion() const void ProgramOptions::LogVersion() const { - INFO("%s%s%s (fpsdk: %s%s%s%s%s, %s)\n%s\n%s\n", app_name_.c_str(), version_str_.empty() ? "" : " ", + INFO("%s%s%s (fpsdk: %s%s%s%s%s, %s)", app_name_.c_str(), version_str_.empty() ? "" : " ", version_str_.empty() ? "" : version_str_.c_str(), BUILDSTR, ROSSTR, PROJSTR, FFMPEGSTR, BZ2STR, - utils::GetVersionString(), copy_str_.empty() ? utils::GetCopyrightString() : copy_str_.c_str(), - lic_str_.empty() ? utils::GetLicenseString() : lic_str_.c_str()); + utils::GetVersionString()); + INFO("%s", copy_str_.empty() ? utils::GetCopyrightString() : copy_str_.c_str()); + INFO("%s", lic_str_.empty() ? utils::GetLicenseString() : lic_str_.c_str()); } /* ****************************************************************************************************************** */