From 4eae6f2f70041ddb8979fdea8501042facd3dbae Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Tue, 11 Jan 2022 10:02:11 +0200 Subject: [PATCH 1/5] kpi checker added --- src/linux/backend-v4l2.cpp | 56 +++++++++++++++++++++++++++++++++++--- src/linux/backend-v4l2.h | 27 ++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/linux/backend-v4l2.cpp b/src/linux/backend-v4l2.cpp index b1caa103db..5a1d1a4f1a 100644 --- a/src/linux/backend-v4l2.cpp +++ b/src/linux/backend-v4l2.cpp @@ -52,6 +52,7 @@ #pragma GCC diagnostic ignored "-Woverflow" const size_t MAX_DEV_PARENT_DIR = 10; +const int DEFAULT_KPI_FRAME_DROPS_PCT = 5; #include "../tm2/tm-boot.h" @@ -678,6 +679,48 @@ namespace librealsense } } + bool kpi_checker::update_and_check(const stream_profile& profile, const timeval& timestamp) + { + bool is_kpi_violated = false; + long int timestamp_usec = static_cast (timestamp.tv_sec * 1000000 + timestamp.tv_usec); + + auto it = std::find_if(drops_per_stream.begin(), drops_per_stream.end(), + [profile](std::pair>& sp_deq) + {return profile == sp_deq.first; }); + if (it != drops_per_stream.end()) + { + auto& queue_for_profile = it->second; + auto limit = static_cast(200.0 / (profile.fps * _kpi_frames_drops_pct) * 1000000.0); + // removing too old timestamps of partial frames + while (queue_for_profile.size() > 0) + { + auto delta = timestamp_usec - queue_for_profile.front(); + if (delta > limit) + { + queue_for_profile.pop_front(); + } + else + break; + } + // checking kpi violation + if (queue_for_profile.size() >= 2) + { + is_kpi_violated = true; + LOG_DEBUG_V4L("KPI VIOLATED: times are [0]:" << queue_for_profile[0] << " , [1]: " << queue_for_profile[1] << " [2]: " << timestamp_usec); + queue_for_profile.clear(); + } + else + queue_for_profile.push_back(timestamp_usec); + } + else + { + std::deque deque_to_add; + deque_to_add.push_back(timestamp_usec); + drops_per_stream.push_back(std::make_pair(profile, deque_to_add)); + } + return is_kpi_violated; + } + v4l_uvc_device::v4l_uvc_device(const uvc_device_info& info, bool use_memory_map) : _name(""), _info(), _is_capturing(false), @@ -688,7 +731,8 @@ namespace librealsense _use_memory_map(use_memory_map), _fd(-1), _stop_pipe_fd{}, - _buf_dispatch(use_memory_map) + _buf_dispatch(use_memory_map), + _kpi_checker(DEFAULT_KPI_FRAME_DROPS_PCT) { foreach_uvc_device([&info, this](const uvc_device_info& i, const std::string& name) { @@ -1060,9 +1104,13 @@ namespace librealsense << ", payload size " << buffer->get_length_frame_only(); } LOG_WARNING("Incomplete frame received: " << s.str()); // Ev -try1 - librealsense::notification n = { RS2_NOTIFICATION_CATEGORY_FRAME_CORRUPTED, 0, RS2_LOG_SEVERITY_WARN, s.str()}; - - _error_handler(n); + bool kpi_violated = _kpi_checker.update_and_check(_profile, buf.timestamp); + if (kpi_violated) + { + librealsense::notification n = { RS2_NOTIFICATION_CATEGORY_FRAME_CORRUPTED, 0, RS2_LOG_SEVERITY_WARN, s.str() }; + _error_handler(n); + } + // Check if metadata was already allocated if (buf_mgr.metadata_size()) { diff --git a/src/linux/backend-v4l2.h b/src/linux/backend-v4l2.h index 328ed1fbea..dd49a0c8b2 100644 --- a/src/linux/backend-v4l2.h +++ b/src/linux/backend-v4l2.h @@ -252,6 +252,32 @@ namespace librealsense virtual void acquire_metadata(buffers_mgr & buf_mgr,fd_set &fds, bool compressed_format) = 0; }; + // The aim of the kpi checker is to check the frames drops kpi for d400 devices - which requires + // that no more than some percentage of the frames are dropped + // It is checked using the fps, and the previous corrupted frames + // for example, for frame rate of 30 fps, and kpi of 5%, the creteria will be: + // - if at least 2 frames drops have occured in the previous 2/(30 * 5%) seconds ( = 2 * 0.667 = 1.33 sec). + // OR + // - if the delta between the previous frame sequence number and the current's one > 2 (this is not implemented yet - TBD) + // then the kpi is violated + class kpi_checker + { + public: + kpi_checker(int kpi_frames_drops) : _kpi_frames_drops_pct(kpi_frames_drops) {} + bool update_and_check(const stream_profile& profile, const timeval& timestamp); //returns whether the kpi has been violated + //void reset(); // should be called in signal_stop method + //bool is_kpi_violated(stream_profile profile) const; + + private: + /*struct stream_drop_data + { + double prev_partial_frame_ts; + int prev_frame_seq; + };*/ + std::vector>> drops_per_stream; + int _kpi_frames_drops_pct; + }; + class v4l_uvc_device : public uvc_device, public v4l_uvc_interface { public: @@ -341,6 +367,7 @@ namespace librealsense int _max_fd = 0; // specifies the maximal pipe number the polling process will monitor std::vector _fds; // list the file descriptors to be monitored during frames polling buffers_mgr _buf_dispatch; // Holder for partial (MD only) frames that shall be preserved between 'select' calls when polling v4l buffers + kpi_checker _kpi_checker; private: int _fd = 0; // prevent unintentional abuse in derived class From 24382c247abad57e242638fcf20e77f22fab9b46 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Tue, 11 Jan 2022 14:57:32 +0200 Subject: [PATCH 2/5] kpi checked over 1 second --- src/linux/backend-v4l2.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/linux/backend-v4l2.cpp b/src/linux/backend-v4l2.cpp index 5a1d1a4f1a..a5abc94f45 100644 --- a/src/linux/backend-v4l2.cpp +++ b/src/linux/backend-v4l2.cpp @@ -687,10 +687,13 @@ namespace librealsense auto it = std::find_if(drops_per_stream.begin(), drops_per_stream.end(), [profile](std::pair>& sp_deq) {return profile == sp_deq.first; }); + + // setting the kpi checking to be done on the last second + int num_of_frames_to_check = profile.fps; if (it != drops_per_stream.end()) { auto& queue_for_profile = it->second; - auto limit = static_cast(200.0 / (profile.fps * _kpi_frames_drops_pct) * 1000000.0); + auto limit = static_cast(num_of_frames_to_check * 100.0 / (profile.fps * _kpi_frames_drops_pct) * 1000000.0); // removing too old timestamps of partial frames while (queue_for_profile.size() > 0) { @@ -703,10 +706,9 @@ namespace librealsense break; } // checking kpi violation - if (queue_for_profile.size() >= 2) + if (queue_for_profile.size() >= num_of_frames_to_check) { is_kpi_violated = true; - LOG_DEBUG_V4L("KPI VIOLATED: times are [0]:" << queue_for_profile[0] << " , [1]: " << queue_for_profile[1] << " [2]: " << timestamp_usec); queue_for_profile.clear(); } else From 9373c150a6db1bd157d0d7c575629cbb236163eb Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Tue, 11 Jan 2022 17:07:18 +0200 Subject: [PATCH 3/5] criteria corrected, comments added --- src/linux/backend-v4l2.cpp | 24 +++++++++++++++--------- src/linux/backend-v4l2.h | 28 +++++++++++----------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/linux/backend-v4l2.cpp b/src/linux/backend-v4l2.cpp index a5abc94f45..acf6163dcd 100644 --- a/src/linux/backend-v4l2.cpp +++ b/src/linux/backend-v4l2.cpp @@ -52,7 +52,7 @@ #pragma GCC diagnostic ignored "-Woverflow" const size_t MAX_DEV_PARENT_DIR = 10; -const int DEFAULT_KPI_FRAME_DROPS_PCT = 5; +const double DEFAULT_KPI_FRAME_DROPS_PERCENTAGE = 0.05; #include "../tm2/tm-boot.h" @@ -684,29 +684,34 @@ namespace librealsense bool is_kpi_violated = false; long int timestamp_usec = static_cast (timestamp.tv_sec * 1000000 + timestamp.tv_usec); + // checking if the current profile is already in the drops_per_stream container auto it = std::find_if(drops_per_stream.begin(), drops_per_stream.end(), [profile](std::pair>& sp_deq) {return profile == sp_deq.first; }); - // setting the kpi checking to be done on the last second - int num_of_frames_to_check = profile.fps; + // if the profile is already in the drops_per_stream container, + // checking kpi with the new partial frame caught if (it != drops_per_stream.end()) { + // setting the kpi checking to be done on the last 2 seconds + int time_limit = 2; + // max number of drops that can be received in the time_limit, without violation of the kpi + int max_num_of_drops = profile.fps * _kpi_frames_drops_pct * time_limit; + auto& queue_for_profile = it->second; - auto limit = static_cast(num_of_frames_to_check * 100.0 / (profile.fps * _kpi_frames_drops_pct) * 1000000.0); // removing too old timestamps of partial frames while (queue_for_profile.size() > 0) { - auto delta = timestamp_usec - queue_for_profile.front(); - if (delta > limit) + auto delta_ts_usec = timestamp_usec - queue_for_profile.front(); + if (delta_ts_usec > (time_limit * 1000000)) { queue_for_profile.pop_front(); } else - break; + break; // correct because the frames are added chronologically } // checking kpi violation - if (queue_for_profile.size() >= num_of_frames_to_check) + if (queue_for_profile.size() >= max_num_of_drops) { is_kpi_violated = true; queue_for_profile.clear(); @@ -716,6 +721,7 @@ namespace librealsense } else { + // adding the the current partial frame's profile and timestamp to the container std::deque deque_to_add; deque_to_add.push_back(timestamp_usec); drops_per_stream.push_back(std::make_pair(profile, deque_to_add)); @@ -734,7 +740,7 @@ namespace librealsense _fd(-1), _stop_pipe_fd{}, _buf_dispatch(use_memory_map), - _kpi_checker(DEFAULT_KPI_FRAME_DROPS_PCT) + _kpi_checker(DEFAULT_KPI_FRAME_DROPS_PERCENTAGE) { foreach_uvc_device([&info, this](const uvc_device_info& i, const std::string& name) { diff --git a/src/linux/backend-v4l2.h b/src/linux/backend-v4l2.h index dd49a0c8b2..ba72a62816 100644 --- a/src/linux/backend-v4l2.h +++ b/src/linux/backend-v4l2.h @@ -252,30 +252,24 @@ namespace librealsense virtual void acquire_metadata(buffers_mgr & buf_mgr,fd_set &fds, bool compressed_format) = 0; }; - // The aim of the kpi checker is to check the frames drops kpi for d400 devices - which requires + // The aim of the kpi checker is to check the frames drops kpi - which requires // that no more than some percentage of the frames are dropped - // It is checked using the fps, and the previous corrupted frames - // for example, for frame rate of 30 fps, and kpi of 5%, the creteria will be: - // - if at least 2 frames drops have occured in the previous 2/(30 * 5%) seconds ( = 2 * 0.667 = 1.33 sec). - // OR - // - if the delta between the previous frame sequence number and the current's one > 2 (this is not implemented yet - TBD) + // It is checked using the fps, and the previous corrupted frames, on the last 2 seconds + // for example, for frame rate of 30 fps, and kpi of 5%, the criteria will be: + // if at least 3 frames (= 30[fps] * 5%[kpi]* 2[sec]) drops have occured in the 2 seconds, // then the kpi is violated class kpi_checker { public: - kpi_checker(int kpi_frames_drops) : _kpi_frames_drops_pct(kpi_frames_drops) {} - bool update_and_check(const stream_profile& profile, const timeval& timestamp); //returns whether the kpi has been violated - //void reset(); // should be called in signal_stop method - //bool is_kpi_violated(stream_profile profile) const; + kpi_checker(double kpi_frames_drops_percentage) : _kpi_frames_drops_pct(kpi_frames_drops_percentage) {} + // update_and_check method returns whether the kpi has been violated + // it should be called each time a partial frame is caught + bool update_and_check(const stream_profile& profile, const timeval& timestamp); private: - /*struct stream_drop_data - { - double prev_partial_frame_ts; - int prev_frame_seq; - };*/ + // container used to store the latest timestamps of the partial frames, per profile std::vector>> drops_per_stream; - int _kpi_frames_drops_pct; + double _kpi_frames_drops_pct; }; class v4l_uvc_device : public uvc_device, public v4l_uvc_interface @@ -367,7 +361,7 @@ namespace librealsense int _max_fd = 0; // specifies the maximal pipe number the polling process will monitor std::vector _fds; // list the file descriptors to be monitored during frames polling buffers_mgr _buf_dispatch; // Holder for partial (MD only) frames that shall be preserved between 'select' calls when polling v4l buffers - kpi_checker _kpi_checker; + kpi_checker _kpi_checker; // used to check the frames drops kpi private: int _fd = 0; // prevent unintentional abuse in derived class From 71fe923ee4db65f982e7d5f57abac4965fe418f5 Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Thu, 13 Jan 2022 10:47:06 +0200 Subject: [PATCH 4/5] checking kpi each 30 sec --- src/linux/backend-v4l2.cpp | 5 +++-- src/linux/backend-v4l2.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/linux/backend-v4l2.cpp b/src/linux/backend-v4l2.cpp index acf6163dcd..165ddac175 100644 --- a/src/linux/backend-v4l2.cpp +++ b/src/linux/backend-v4l2.cpp @@ -693,8 +693,9 @@ namespace librealsense // checking kpi with the new partial frame caught if (it != drops_per_stream.end()) { - // setting the kpi checking to be done on the last 2 seconds - int time_limit = 2; + // setting the kpi checking to be done on the last 30 seconds + int time_limit = 30; + // max number of drops that can be received in the time_limit, without violation of the kpi int max_num_of_drops = profile.fps * _kpi_frames_drops_pct * time_limit; diff --git a/src/linux/backend-v4l2.h b/src/linux/backend-v4l2.h index ba72a62816..5a948a7a91 100644 --- a/src/linux/backend-v4l2.h +++ b/src/linux/backend-v4l2.h @@ -254,9 +254,9 @@ namespace librealsense // The aim of the kpi checker is to check the frames drops kpi - which requires // that no more than some percentage of the frames are dropped - // It is checked using the fps, and the previous corrupted frames, on the last 2 seconds + // It is checked using the fps, and the previous corrupted frames, on the last 30 seconds // for example, for frame rate of 30 fps, and kpi of 5%, the criteria will be: - // if at least 3 frames (= 30[fps] * 5%[kpi]* 2[sec]) drops have occured in the 2 seconds, + // if at least 45 frames (= 30[fps] * 5%[kpi]* 30[sec]) drops have occured in the previous 30 seconds, // then the kpi is violated class kpi_checker { From 3d8f78aa0cc1c722e2c44c498f5dec4c989bb06f Mon Sep 17 00:00:00 2001 From: Remi Bettan Date: Thu, 13 Jan 2022 11:34:18 +0200 Subject: [PATCH 5/5] semantic changes --- src/linux/backend-v4l2.cpp | 8 ++++---- src/linux/backend-v4l2.h | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/linux/backend-v4l2.cpp b/src/linux/backend-v4l2.cpp index 165ddac175..32ca32abab 100644 --- a/src/linux/backend-v4l2.cpp +++ b/src/linux/backend-v4l2.cpp @@ -679,7 +679,7 @@ namespace librealsense } } - bool kpi_checker::update_and_check(const stream_profile& profile, const timeval& timestamp) + bool frame_drop_monitor::update_and_check_kpi(const stream_profile& profile, const timeval& timestamp) { bool is_kpi_violated = false; long int timestamp_usec = static_cast (timestamp.tv_sec * 1000000 + timestamp.tv_usec); @@ -741,7 +741,7 @@ namespace librealsense _fd(-1), _stop_pipe_fd{}, _buf_dispatch(use_memory_map), - _kpi_checker(DEFAULT_KPI_FRAME_DROPS_PERCENTAGE) + _frame_drop_monitor(DEFAULT_KPI_FRAME_DROPS_PERCENTAGE) { foreach_uvc_device([&info, this](const uvc_device_info& i, const std::string& name) { @@ -1112,8 +1112,8 @@ namespace librealsense s << "overflow video frame detected!\nSize " << buf.bytesused << ", payload size " << buffer->get_length_frame_only(); } - LOG_WARNING("Incomplete frame received: " << s.str()); // Ev -try1 - bool kpi_violated = _kpi_checker.update_and_check(_profile, buf.timestamp); + LOG_DEBUG("Incomplete frame received: " << s.str()); // Ev -try1 + bool kpi_violated = _frame_drop_monitor.update_and_check_kpi(_profile, buf.timestamp); if (kpi_violated) { librealsense::notification n = { RS2_NOTIFICATION_CATEGORY_FRAME_CORRUPTED, 0, RS2_LOG_SEVERITY_WARN, s.str() }; diff --git a/src/linux/backend-v4l2.h b/src/linux/backend-v4l2.h index 5a948a7a91..07369da7c8 100644 --- a/src/linux/backend-v4l2.h +++ b/src/linux/backend-v4l2.h @@ -252,19 +252,19 @@ namespace librealsense virtual void acquire_metadata(buffers_mgr & buf_mgr,fd_set &fds, bool compressed_format) = 0; }; - // The aim of the kpi checker is to check the frames drops kpi - which requires + // The aim of the frame_drop_monitor is to check the frames drops kpi - which requires // that no more than some percentage of the frames are dropped // It is checked using the fps, and the previous corrupted frames, on the last 30 seconds // for example, for frame rate of 30 fps, and kpi of 5%, the criteria will be: // if at least 45 frames (= 30[fps] * 5%[kpi]* 30[sec]) drops have occured in the previous 30 seconds, // then the kpi is violated - class kpi_checker + class frame_drop_monitor { public: - kpi_checker(double kpi_frames_drops_percentage) : _kpi_frames_drops_pct(kpi_frames_drops_percentage) {} - // update_and_check method returns whether the kpi has been violated + frame_drop_monitor(double kpi_frames_drops_percentage) : _kpi_frames_drops_pct(kpi_frames_drops_percentage) {} + // update_and_check_kpi method returns whether the kpi has been violated // it should be called each time a partial frame is caught - bool update_and_check(const stream_profile& profile, const timeval& timestamp); + bool update_and_check_kpi(const stream_profile& profile, const timeval& timestamp); private: // container used to store the latest timestamps of the partial frames, per profile @@ -361,7 +361,7 @@ namespace librealsense int _max_fd = 0; // specifies the maximal pipe number the polling process will monitor std::vector _fds; // list the file descriptors to be monitored during frames polling buffers_mgr _buf_dispatch; // Holder for partial (MD only) frames that shall be preserved between 'select' calls when polling v4l buffers - kpi_checker _kpi_checker; // used to check the frames drops kpi + frame_drop_monitor _frame_drop_monitor; // used to check the frames drops kpi private: int _fd = 0; // prevent unintentional abuse in derived class