From 6e92eb56511cc8621f016ee9f3786be06c2ba30c Mon Sep 17 00:00:00 2001 From: Eran Date: Wed, 25 Oct 2023 14:51:42 +0300 Subject: [PATCH] change ACTUAL_FPS to be x1000 for more syncer precision # Conflicts: # src/sync.cpp # src/sync.h # unit-tests/syncer/sw.py --- common/output-model.cpp | 8 ++--- common/stream-model.cpp | 6 ++-- include/librealsense2/h/rs_frame.h | 2 +- src/metadata-parser.h | 25 ++++++++++------ src/proc/syncer-processing-block.cpp | 2 +- src/sync.cpp | 28 +++++++++--------- src/sync.h | 6 ++-- unit-tests/live/syncer/test-throughput.cpp | 2 +- unit-tests/unit-tests-live.cpp | 34 +++++++++++----------- 9 files changed, 60 insertions(+), 53 deletions(-) diff --git a/common/output-model.cpp b/common/output-model.cpp index e2f73de9d77..643e596136c 100644 --- a/common/output-model.cpp +++ b/common/output-model.cpp @@ -1083,12 +1083,12 @@ void frame_drops_dashboard::process_frame(rs2::frame f) { auto last = stream_to_time[f.get_profile().unique_id()]; - long long fps = f.get_profile().fps(); + double fps = (double)f.get_profile().fps(); - if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) - fps = f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS); + if( f.supports_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) ) + fps = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.; - if (1000.f * (ts - last) > 1.5f * (1000.f / fps)) { + if (1000. * (ts - last) > 1.5 * (1000. / fps)) { drops++; } } diff --git a/common/stream-model.cpp b/common/stream-model.cpp index e9d90c67e6a..eb3941f19f7 100644 --- a/common/stream-model.cpp +++ b/common/stream-model.cpp @@ -895,7 +895,7 @@ namespace rs2 { RS2_FRAME_METADATA_TEMPERATURE, "Temperature of the device, measured at the time of the frame capture. Celsius degrees " }, { RS2_FRAME_METADATA_BACKEND_TIMESTAMP, "Timestamp get from uvc driver. usec" }, - { RS2_FRAME_METADATA_ACTUAL_FPS, "Actual hardware FPS. May differ from requested due to Auto-Exposure" }, + { RS2_FRAME_METADATA_ACTUAL_FPS, "Hardware FPS * 1000, or 1000000*d_frame_number/d_timestamp since previous frame" }, { RS2_FRAME_METADATA_FRAME_LASER_POWER_MODE, "Laser power mode. Zero corresponds to Laser power switched off and one for switched on." }, { RS2_FRAME_METADATA_EXPOSURE_PRIORITY, @@ -912,10 +912,10 @@ namespace rs2 { auto val = (rs2_frame_metadata_value)i; std::string name = rs2_frame_metadata_to_string( val ); - std::string desc = ""; + std::string desc; if( descriptions.find( val ) != descriptions.end() ) desc = descriptions[val]; - stream_details.push_back( { name, rsutils::string::from() << kvp.second, desc } ); + stream_details.push_back( { name, rsutils::string::from( kvp.second ), desc } ); } } diff --git a/include/librealsense2/h/rs_frame.h b/include/librealsense2/h/rs_frame.h index f2d26b3b93b..8dbeacf3656 100644 --- a/include/librealsense2/h/rs_frame.h +++ b/include/librealsense2/h/rs_frame.h @@ -39,7 +39,7 @@ typedef enum rs2_frame_metadata_value RS2_FRAME_METADATA_TIME_OF_ARRIVAL , /**< Time of arrival in system clock */ RS2_FRAME_METADATA_TEMPERATURE , /**< Temperature of the device, measured at the time of the frame capture. Celsius degrees */ RS2_FRAME_METADATA_BACKEND_TIMESTAMP , /**< Timestamp get from uvc driver. usec*/ - RS2_FRAME_METADATA_ACTUAL_FPS , /**< Actual fps */ + RS2_FRAME_METADATA_ACTUAL_FPS , /**< Actual fps, times 1000 (30.1 fps would be 30100 in the metadata) */ RS2_FRAME_METADATA_FRAME_LASER_POWER , /**< Laser power value 0-360. */ RS2_FRAME_METADATA_FRAME_LASER_POWER_MODE , /**< Laser power mode. Zero corresponds to Laser power switched off and one for switched on. deprecated, replaced by RS2_FRAME_METADATA_FRAME_EMITTER_MODE*/ RS2_FRAME_METADATA_EXPOSURE_PRIORITY , /**< Exposure priority. */ diff --git a/src/metadata-parser.h b/src/metadata-parser.h index 818e429b913..3bd06d3c0a0 100644 --- a/src/metadata-parser.h +++ b/src/metadata-parser.h @@ -349,15 +349,23 @@ namespace librealsense { // A computation involving unsigned operands can never overflow (ISO/IEC 9899:1999 (E) \A76.2.5/9) // In case of frame counter reset fallback use fps from the stream configuration - auto num_of_frames = (frm.additional_data.frame_number) ? frm.additional_data.frame_number - frm.additional_data.last_frame_number : 0; + auto num_of_frames = frm.additional_data.frame_number + ? frm.additional_data.frame_number - frm.additional_data.last_frame_number + : 0; if (num_of_frames == 0) { LOG_INFO("Frame counter reset"); } + else + { + auto diff + = ( frm.additional_data.timestamp - frm.additional_data.last_timestamp ) / (double)num_of_frames; + if( diff > 0 ) + return std::max( 1000. / diff, 1. ); + } - auto diff = num_of_frames ? (double)(frm.additional_data.timestamp - frm.additional_data.last_timestamp) / (double)num_of_frames : 0; - return diff > 0 ? std::max(1000.f / std::ceil(diff), (double)1) : frm.get_stream()->get_framerate(); + return frm.get_stream()->get_framerate(); } }; @@ -389,13 +397,13 @@ namespace librealsense auto exp_in_micro = _exposure_modifyer(exp); if (exp_in_micro > 0) { - auto fps = 1000000.f / exp_in_micro; + auto fps = 1000000. / exp_in_micro; if (_discrete) { if (fps >= _fps_values.back()) { - fps = static_cast(_fps_values.back()); + fps = static_cast(_fps_values.back()); } else { @@ -403,18 +411,17 @@ namespace librealsense { if (fps < _fps_values[i + 1]) { - fps = static_cast(_fps_values[i]); + fps = static_cast(_fps_values[i]); break; } } } } - return std::min((int)fps, (int)frm.get_stream()->get_framerate()); + return rs2_metadata_type( std::min( fps, (double)frm.get_stream()->get_framerate() ) * 1000 ); } } - return (rs2_metadata_type)_fps_calculator.get_fps(frm); - + return rs2_metadata_type( _fps_calculator.get_fps( frm ) * 1000 ); } bool supports(const librealsense::frame & frm) const override diff --git a/src/proc/syncer-processing-block.cpp b/src/proc/syncer-processing-block.cpp index 045ff4a4df4..6a8050381c9 100644 --- a/src/proc/syncer-processing-block.cpp +++ b/src/proc/syncer-processing-block.cpp @@ -14,7 +14,7 @@ namespace librealsense : processing_block("syncer"), _matcher((new composite_identity_matcher({}))) , _enable_opts(enable_opts.begin(), enable_opts.end()) { - _matcher->set_callback( [this]( frame_holder f, syncronization_environment env ) { + _matcher->set_callback( []( frame_holder f, syncronization_environment const & env ) { if( env.log ) { LOG_DEBUG( "<-- queueing " << f ); diff --git a/src/sync.cpp b/src/sync.cpp index 4bfb7976622..a94260bdada 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -563,22 +563,17 @@ namespace librealsense void timestamp_composite_matcher::update_last_arrived(frame_holder& f, matcher* m) { - if(f->supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) - _fps[m] = (uint32_t)f->get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS); - else - _fps[m] = f->get_stream()->get_framerate(); - auto const now = time_service::get_time(); //LOG_DEBUG( _name << ": _last_arrived[" << m->get_name() << "] = " << now ); _last_arrived[m] = now; } - unsigned int timestamp_composite_matcher::get_fps( frame_interface const * f ) + double timestamp_composite_matcher::get_fps( frame_interface const * f ) { - uint32_t fps = 0; + double fps = 0.; if(f->supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - fps = (uint32_t)f->get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS); + fps = f->get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.; } if( fps ) { @@ -597,7 +592,7 @@ namespace librealsense const frame_holder & f ) { auto fps = get_fps( f ); - auto gap = 1000.f / (float)fps; + auto gap = 1000. / fps; auto ts = f.frame->get_frame_timestamp(); auto ne = ts + gap; @@ -687,7 +682,7 @@ namespace librealsense { // Wait for the missing stream frame to arrive -- up to a cutout: anything more and we // let the frameset be ready without it... - auto gap = 1000.f / fps; + auto gap = 1000. / fps; // NOTE: the threshold is a function of the gap; the bigger it is, the more latency // between the streams we're willing to live with. Each gap is a frame so we are limited // by the number of frames we're willing to keep (which is our queue limit) @@ -714,10 +709,17 @@ namespace librealsense fps ); // should be min fps to match behavior elsewhere? } - bool timestamp_composite_matcher::are_equivalent( double a, double b, unsigned int fps ) + bool timestamp_composite_matcher::are_equivalent( double a, double b, double fps ) { - float gap = 1000.f / fps; - return abs(a - b) < (gap / 2); + auto gap = 1000. / fps; + if( abs( a - b ) < (gap / 2) ) + { + //LOG_DEBUG( "... " << a << " == " << b << " {diff}" << abs( a - b ) << " < " << (gap / 2) << "{gap/2}" ); + return true; + } + + //LOG_DEBUG( "... " << a << " != " << b << " {diff}" << abs( a - b ) << " >= " << ( gap / 2 ) << "{gap/2}" ); + return false; } composite_identity_matcher::composite_identity_matcher( diff --git a/src/sync.h b/src/sync.h index cebcccc92d4..53893f1658d 100644 --- a/src/sync.h +++ b/src/sync.h @@ -180,10 +180,8 @@ namespace librealsense const frame_holder & f ) override; private: - unsigned int get_fps( frame_interface const * f ); - bool are_equivalent( double a, double b, unsigned int fps ); + double get_fps( frame_interface const * f ); + bool are_equivalent( double a, double b, double fps ); std::map _last_arrived; - std::map _fps; - }; } diff --git a/unit-tests/live/syncer/test-throughput.cpp b/unit-tests/live/syncer/test-throughput.cpp index 2855b3734a0..f01f61b5845 100644 --- a/unit-tests/live/syncer/test-throughput.cpp +++ b/unit-tests/live/syncer/test-throughput.cpp @@ -90,7 +90,7 @@ TEST_CASE( "Syncer dynamic FPS - throughput test" ) if (!f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS) || !f.supports_frame_metadata(RS2_FRAME_METADATA_FRAME_TIMESTAMP)) return; auto frame_num = f.get_frame_number(); - auto actual_fps = (float)f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS); + auto actual_fps = f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS) / 1000.f; auto frame_arrival = f.get_frame_metadata(RS2_FRAME_METADATA_FRAME_TIMESTAMP); // usec if (stream_type == "Infrared 1") _ir_frames_arrival_info.push_back({ (float)frame_arrival, actual_fps }); diff --git a/unit-tests/unit-tests-live.cpp b/unit-tests/unit-tests-live.cpp index f33f5e44cba..189da034b01 100644 --- a/unit-tests/unit-tests-live.cpp +++ b/unit-tests/unit-tests-live.cpp @@ -45,7 +45,7 @@ TEST_CASE("Sync sanity", "[live][mayfail]") { } std::vector> all_timestamps; - auto actual_fps = fps; + auto actual_fps = float( fps ); for (auto i = 0; i < 200; i++) { @@ -61,7 +61,7 @@ TEST_CASE("Sync sanity", "[live][mayfail]") { if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - auto val = static_cast(f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)); + auto val = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.f; if (val < actual_fps) actual_fps = val; } @@ -98,7 +98,7 @@ TEST_CASE("Sync sanity", "[live][mayfail]") { continue; std::sort(set_timestamps.begin(), set_timestamps.end()); - REQUIRE(set_timestamps[set_timestamps.size() - 1] - set_timestamps[0] <= (float)1000 / (float)actual_fps); + REQUIRE(set_timestamps[set_timestamps.size() - 1] - set_timestamps[0] <= 1000.f / actual_fps); } CAPTURE(num_of_partial_sync_sets); @@ -2801,13 +2801,13 @@ TEST_CASE("Auto-complete feature works", "[offline][util::config][using_pipeline //} -void validate(std::vector> frames, std::vector> timestamps, device_profiles requests, int actual_fps) +void validate(std::vector> frames, std::vector> timestamps, device_profiles requests, float actual_fps) { REQUIRE(frames.size() > 0); int successful = 0; - auto gap = (float)1000 / (float)actual_fps; + auto gap = 1000.f / actual_fps; auto ts = 0; @@ -2957,7 +2957,7 @@ TEST_CASE("Pipeline wait_for_frames", "[live][pipeline][using_pipeline][!mayfail for (auto i = 0; i < 30; i++) REQUIRE_NOTHROW(pipe.wait_for_frames(10000)); - auto actual_fps = pipeline_default_configurations.at(PID).fps; + auto actual_fps = float( pipeline_default_configurations.at(PID).fps ); while (frames.size() < 100) { @@ -2970,7 +2970,7 @@ TEST_CASE("Pipeline wait_for_frames", "[live][pipeline][using_pipeline][!mayfail { if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - auto val = static_cast(f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)); + auto val = f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS) / 1000.f; if (val < actual_fps) actual_fps = val; } @@ -3024,7 +3024,7 @@ TEST_CASE("Pipeline poll_for_frames", "[live][pipeline][using_pipeline][!mayfail for (auto i = 0; i < 30; i++) REQUIRE_NOTHROW(pipe.wait_for_frames(5000)); - auto actual_fps = pipeline_default_configurations.at(PID).fps; + auto actual_fps = float( pipeline_default_configurations.at(PID).fps ); while (frames.size() < 100) { frameset frame; @@ -3036,7 +3036,7 @@ TEST_CASE("Pipeline poll_for_frames", "[live][pipeline][using_pipeline][!mayfail { if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - auto val = static_cast(f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)); + auto val = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.f; if (val < actual_fps) actual_fps = val; } @@ -3117,7 +3117,7 @@ TEST_CASE("Pipeline enable stream", "[live][pipeline][using_pipeline]") { for (auto i = 0; i < 30; i++) REQUIRE_NOTHROW(pipe.wait_for_frames(5000)); - auto actual_fps = dev_requests[PID].fps; + auto actual_fps = float( dev_requests[PID].fps ); while (frames.size() < 100) { @@ -3130,7 +3130,7 @@ TEST_CASE("Pipeline enable stream", "[live][pipeline][using_pipeline]") { { if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - auto val = static_cast(f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)); + auto val = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.f; if (val < actual_fps) actual_fps = val; } @@ -3211,7 +3211,7 @@ TEST_CASE("Pipeline enable stream auto complete", "[live][pipeline][using_pipeli for (auto i = 0; i < 30; i++) REQUIRE_NOTHROW(pipe.wait_for_frames(5000)); - auto actual_fps = configurations[PID].fps; + auto actual_fps = float( configurations[PID].fps ); while (frames.size() < 100) { @@ -3223,7 +3223,7 @@ TEST_CASE("Pipeline enable stream auto complete", "[live][pipeline][using_pipeli { if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - auto val = static_cast(f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)); + auto val = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.f; if (val < actual_fps) actual_fps = val; } @@ -3288,7 +3288,7 @@ TEST_CASE("Pipeline disable_all", "[live][pipeline][using_pipeline][!mayfail]") for (auto i = 0; i < 30; i++) REQUIRE_NOTHROW(pipe.wait_for_frames(5000)); - auto actual_fps = default_configurations[PID].fps; + auto actual_fps = float( default_configurations[PID].fps ); while (frames.size() < 100) { @@ -3300,7 +3300,7 @@ TEST_CASE("Pipeline disable_all", "[live][pipeline][using_pipeline][!mayfail]") { if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - auto val = static_cast(f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)); + auto val = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.f; if (val < actual_fps) actual_fps = val; } @@ -3367,7 +3367,7 @@ TEST_CASE("Pipeline disable stream", "[live][pipeline][using_pipeline]") { for (auto i = 0; i < 30; i++) REQUIRE_NOTHROW(pipe.wait_for_frames(5000)); - auto actual_fps = configurations[PID].fps; + auto actual_fps = float( configurations[PID].fps ); while (frames.size() < 100) { frameset frame; @@ -3378,7 +3378,7 @@ TEST_CASE("Pipeline disable stream", "[live][pipeline][using_pipeline]") { { if (f.supports_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)) { - auto val = static_cast(f.get_frame_metadata(RS2_FRAME_METADATA_ACTUAL_FPS)); + auto val = f.get_frame_metadata( RS2_FRAME_METADATA_ACTUAL_FPS ) / 1000.f; if (val < actual_fps) actual_fps = val; }