-
Couldn't load subscription status.
- Fork 4.9k
Updated frame validator #4788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updated frame validator #4788
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,90 +3,106 @@ | |
|
|
||
| #include "frame-validator.h" | ||
|
|
||
| #define INVALID_PIXELS_THRESHOLD 0.1 | ||
|
|
||
| namespace librealsense | ||
| { | ||
| void frame_validator::on_frame(rs2_frame * f) | ||
| { | ||
| if (propagate((frame_interface*)f)) | ||
| if (!_stopped && propagate((frame_interface*)f)) | ||
| { | ||
| _user_callback->on_frame(f); | ||
| _sensor->set_frames_callback(_user_callback); | ||
| if(is_user_requseted_frame((frame_interface*)f)) | ||
| _user_callback->on_frame(f); | ||
| } | ||
| } | ||
|
|
||
| void frame_validator::release() | ||
| { | ||
|
|
||
| } | ||
| {} | ||
|
|
||
| frame_validator::frame_validator(std::shared_ptr<sensor_interface> sensor, frame_callback_ptr user_callback, stream_profiles current_requests) : | ||
| frame_validator::frame_validator(std::shared_ptr<sensor_interface> sensor, frame_callback_ptr user_callback, stream_profiles current_requests, stream_profiles validator_requests) : | ||
| _sensor(sensor), | ||
| _user_callback(user_callback), | ||
| _current_requests(current_requests) | ||
| { | ||
|
|
||
| } | ||
| _user_requests(current_requests), | ||
| _validator_requests(validator_requests), | ||
| _stopped(false), | ||
| _validated(false) | ||
| {} | ||
|
|
||
| frame_validator::~frame_validator() | ||
| { | ||
|
|
||
| } | ||
| {} | ||
|
|
||
| bool frame_validator::propagate(frame_interface* frame) | ||
| { | ||
| auto vf = dynamic_cast<video_frame*>(frame); | ||
| if (vf == nullptr) { | ||
| if(_validated) | ||
| return true; | ||
| } | ||
|
|
||
| auto vf = dynamic_cast<video_frame*>(frame); | ||
| if (vf == nullptr) | ||
| throw std::runtime_error(to_string() << "non video stream arrived to frame_validator"); | ||
|
|
||
| auto stream = vf->get_stream(); | ||
| if (stream->get_stream_type() != RS2_STREAM_DEPTH) | ||
|
|
||
| //all streams except ir will be droped untill the validation on ir, | ||
| //after the validation all streams will be passeded to user callback directly | ||
| if (stream->get_stream_type() != RS2_STREAM_INFRARED) | ||
| return false; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If for some reason Ir frames do not arrive for a considerable amount of time but others do - is it possible to generate a log, like after 100 consecutive "return false" ? |
||
|
|
||
| //start to validate only from the second frame | ||
| if(frame_num++ < 2) | ||
|
||
| return false; | ||
|
|
||
| auto w = vf->get_width(); | ||
| auto h = vf->get_height(); | ||
| auto bpp = vf->get_bpp() / 8; | ||
| auto data = reinterpret_cast<const uint16_t*>(vf->get_frame_data()); | ||
|
|
||
| bool non_empty_pixel_found = false; | ||
| auto data = static_cast<const void*>(vf->get_frame_data()); | ||
|
|
||
| auto invalid_pixels = 0; | ||
|
|
||
| int y_begin = h * 0.5 - h * 0.05; | ||
| int y_end = h * 0.5 + h * 0.05; | ||
| int x_begin = w * 0.5 - w * 0.05; | ||
| int x_end = w * 0.5 + w * 0.05; | ||
| for (int y = y_begin; y < y_end; y++) | ||
| for (int y = 0; y < h*w; y++) | ||
| { | ||
| for (int x = x_begin; x < x_end; x++) | ||
| if (((byte*)data)[y] == 0) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is IR stream 8-bit only, no 12 bit formats? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes 8 bit |
||
| { | ||
| auto index = x + y * w; | ||
| if (data[index] != 0) | ||
| { | ||
| non_empty_pixel_found = true; | ||
| break; | ||
| } | ||
| invalid_pixels++; | ||
| } | ||
| } | ||
|
|
||
| if (non_empty_pixel_found) | ||
| if ((float)invalid_pixels/(w*h) < INVALID_PIXELS_THRESHOLD) | ||
| { | ||
| _validated = true; | ||
| return true; | ||
| } | ||
| else | ||
| { | ||
| LOG_ERROR("frame_source received an empty depth frame, restarting the sensor..."); | ||
|
|
||
| LOG_ERROR("frame_source received corrupted depth frame ("<<(float)invalid_pixels/(w*h)<<"% invalid pixels), restarting the sensor..."); | ||
|
||
| auto s = _sensor; | ||
| auto cr = _current_requests; | ||
| auto vr = _validator_requests; | ||
| auto uc = _user_callback; | ||
| _reset_thread = std::thread([s, cr, uc]() | ||
| _stopped = true; | ||
| _reset_thread = std::thread([s, vr, uc]() | ||
| { | ||
| try { | ||
| std::this_thread::sleep_for(std::chrono::milliseconds(500)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment for maintainers |
||
| s->stop(); | ||
| s->close(); | ||
| s->open(cr); | ||
| std::this_thread::sleep_for(std::chrono::milliseconds(500)); | ||
| s->open(vr); | ||
| s->start(uc); | ||
| } | ||
| catch (...) {} | ||
| catch (...) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If an exception is raised during the |
||
| {} | ||
| }); | ||
| _reset_thread.detach(); | ||
| //std::this_thread::sleep_for(std::chrono::milliseconds(1000)); | ||
| } | ||
| return false; | ||
|
|
||
| } | ||
|
|
||
| bool frame_validator::is_user_requseted_frame(frame_interface* frame) | ||
| { | ||
| return std::find_if(_user_requests.begin(), _user_requests.end(), [&](std::shared_ptr<stream_profile_interface> sp) | ||
| { | ||
| return is_stream_profiles_equals(frame->get_stream().get(), sp.get()); | ||
| }) != _user_requests.end(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,23 +4,66 @@ | |
| #pragma once | ||
|
|
||
| #include "sensor.h" | ||
|
|
||
| #include "stream.h" | ||
| #include "option.h" | ||
| namespace librealsense | ||
| { | ||
| const int RS2_OPTION_DEPTH_INVALIDATION_ENABLE = static_cast<rs2_option>(RS2_OPTION_COUNT + 9); /**< depth invalidation enabled*/ | ||
|
|
||
| class depth_invalidation_option: public ptr_option<bool> | ||
| { | ||
| public: | ||
| depth_invalidation_option(bool min, bool max, bool step, bool def, bool* value, const std::string& desc): | ||
| ptr_option<bool>(min, max, step, def, value, desc), | ||
| _streaming(false){} | ||
|
|
||
| void set_streaming(bool streaming) | ||
| { | ||
| _streaming = streaming; | ||
| } | ||
|
|
||
| bool is_enabled() const override | ||
| { | ||
| return !_streaming; | ||
| } | ||
|
|
||
| private: | ||
| bool _streaming; | ||
| }; | ||
|
|
||
| class frame_validator : public rs2_frame_callback | ||
| { | ||
| public: | ||
| explicit frame_validator(std::shared_ptr<sensor_interface> sensor, frame_callback_ptr user_callback, stream_profiles current_requests); | ||
| explicit frame_validator(std::shared_ptr<sensor_interface> sensor, frame_callback_ptr user_callback, stream_profiles user_requests, stream_profiles validator_requests); | ||
| virtual ~frame_validator(); | ||
|
|
||
| void on_frame(rs2_frame * f) override; | ||
| void release() override; | ||
|
|
||
| static bool is_stream_profiles_equals(stream_profile_interface* l, stream_profile_interface* r) | ||
| { | ||
| auto vl = dynamic_cast<video_stream_profile_interface*>(l); | ||
| auto vr = dynamic_cast<video_stream_profile_interface*>(r); | ||
|
|
||
| if (!vl || !vr) | ||
| return false; | ||
|
|
||
| return l->get_framerate() == r->get_framerate() && | ||
| vl->get_width() == vr->get_width() && | ||
| vl->get_height() == vr->get_height(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stream format? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I try to find IR stream that corresponding to depth/confidence if the user asked depth/confidence and not ir ,so the format will not be the same only resolution and frame rate. |
||
| } | ||
|
|
||
| private: | ||
| bool propagate(frame_interface* frame); | ||
| bool is_user_requseted_frame(frame_interface* frame); | ||
|
|
||
| std::thread _reset_thread; | ||
| std::atomic<bool> _stopped; | ||
| std::atomic<bool> _validated; | ||
| int frame_num = 0; | ||
| frame_callback_ptr _user_callback; | ||
| stream_profiles _current_requests; | ||
| stream_profiles _user_requests; | ||
| stream_profiles _validator_requests; | ||
| std::shared_ptr<sensor_interface> _sensor; | ||
| }; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requested