Skip to content
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

Add support for post processing filters #11566

Merged
merged 3 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 112 additions & 1 deletion src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
#include <rsutils/os/executable-name.h>
#include <rsutils/deferred.h>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <proc/depth-decompress.h>
#include <proc/decimation-filter.h>
#include <proc/disparity-transform.h>
#include <proc/hdr-merge.h>
#include <proc/hole-filling-filter.h>
#include <proc/sequence-id-filter.h>
#include <proc/spatial-filter.h>
#include <proc/temporal-filter.h>
#include <proc/threshold.h>

// We manage one participant and device-watcher per domain:
// Two contexts with the same domain-id will share the same participant and watcher, while a third context on a
Expand Down Expand Up @@ -979,6 +988,55 @@ namespace librealsense
throw std::runtime_error( "Could not find a stream that supports option " + name );
}

void add_processing_block( std::string filter_name )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file starts to be really long. If I read it correctly, most of it is dds_sensor_proxy class - please consider to add new h and cpp files for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already mentioned in a previous PR (about metadata support) that we intend to split the DDS to a different file, but because the changes we made broke the LibCI we address it first. After changes will be merged we will create a new PR to split this file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

{
auto & current_filters = get_software_recommended_proccesing_blocks();

if( processing_block_exists( current_filters.get_recommended_processing_blocks(), filter_name ) )
return; // Already created by another stream of this sensor

create_processing_block( filter_name );
}

bool processing_block_exists( processing_blocks const & blocks, std::string const & block_name ) const
{
for( auto & block : blocks )
if( block_name.compare( block->get_info( RS2_CAMERA_INFO_NAME ) ) == 0 )
return true;

return false;
}

void create_processing_block( std::string & filter_name )
{
auto & current_filters = get_software_recommended_proccesing_blocks();

if( filter_name.compare( "Depth Huffman Decoder" ) == 0 )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing the "==0" and adding"!" instead. e.g:
if( !filter_name.compare( "Depth Huffman Decoder" ) )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that using ! is less readable, because compare returns 0 when it is true. !compare reads like it does not compare.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your style - ok

current_filters.add_processing_block( std::make_shared< depth_decompression_huffman >() );
else if( filter_name.compare( "Decimation Filter" ) == 0 )
// sensor.cpp sets format option based on sensor type, but the filter does not use it and selects the
// appropriate decimation algorithm based on processed frame profile format.
current_filters.add_processing_block( std::make_shared< decimation_filter >() );
else if( filter_name.compare( "HDR Merge" ) == 0 )
current_filters.add_processing_block( std::make_shared< hdr_merge >() );
else if( filter_name.compare( "Filter By Sequence id" ) == 0 )
current_filters.add_processing_block( std::make_shared< sequence_id_filter >() );
else if( filter_name.compare( "Threshold Filter" ) == 0 )
current_filters.add_processing_block( std::make_shared< threshold >() );
else if( filter_name.compare( "Depth to Disparity" ) == 0 )
current_filters.add_processing_block( std::make_shared< disparity_transform >( true ) );
else if( filter_name.compare( "Disparity to Depth" ) == 0 )
current_filters.add_processing_block( std::make_shared< disparity_transform >( false ) );
else if( filter_name.compare( "Spatial Filter" ) == 0 )
current_filters.add_processing_block( std::make_shared< spatial_filter >() );
else if( filter_name.compare( "Temporal Filter" ) == 0 )
current_filters.add_processing_block( std::make_shared< temporal_filter >() );
else if( filter_name.compare( "Hole Filling Filter" ) == 0 )
current_filters.add_processing_block( std::make_shared< hole_filling_filter >() );
else
throw std::runtime_error( "Unsupported processing block '" + filter_name + "' received" );
}

const std::string & get_name() const { return _name; }

private:
Expand All @@ -991,6 +1049,43 @@ namespace librealsense
std::map< std::string, frame_metadata_syncer< rs2_software_motion_frame > > _stream_name_to_motion_syncer;
};

// For cases when checking if this is< color_sensor > (like realsense-viewer::subdevice_model)
class dds_color_sensor_proxy : public dds_sensor_proxy, public color_sensor
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check is we can add also depth_sensor
Can be on the todo list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider exporting this class to separate h, cpp files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be moved in a future PR. See previous comments

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

{
public:
dds_color_sensor_proxy( std::string const & sensor_name,
software_device * owner,
std::shared_ptr< realdds::dds_device > const & dev )
: dds_sensor_proxy( sensor_name, owner, dev )
{
}
};

// For cases when checking if this is< depth_sensor > (like realsense-viewer::subdevice_model)
class dds_depth_sensor_proxy : public dds_sensor_proxy, public depth_sensor
{
public:
dds_depth_sensor_proxy( std::string const & sensor_name,
software_device * owner,
std::shared_ptr< realdds::dds_device > const & dev )
: dds_sensor_proxy( sensor_name, owner, dev )
{
}

// Needed by abstract interfaces
float get_depth_scale() const override { return get_option( RS2_OPTION_DEPTH_UNITS ).query(); }

void create_snapshot( std::shared_ptr<depth_sensor> & snapshot ) const override
{
snapshot = std::make_shared<depth_sensor_snapshot>( get_depth_scale() );
}

void enable_recording( std::function<void( const depth_sensor & )> recording_function ) override
{
//does not change over time
}
};

// This is the rs2 device; it proxies to an actual DDS device that does all the actual
// work. For example:
// auto dev_list = ctx.query_devices();
Expand Down Expand Up @@ -1129,7 +1224,7 @@ namespace librealsense
if( ! sensor_info.proxy )
{
// This is a new sensor we haven't seen yet
sensor_info.proxy = std::make_shared< dds_sensor_proxy >( stream->sensor_name(), this, _dds_dev );
sensor_info.proxy = create_sensor( stream->sensor_name() );
sensor_info.sensor_index = add_sensor( sensor_info.proxy );
assert( sensor_info.sensor_index == _software_sensors.size() );
_software_sensors.push_back( sensor_info.proxy );
Expand Down Expand Up @@ -1177,6 +1272,12 @@ namespace librealsense
{
sensor_info.proxy->add_option( option );
}

auto & recommended_filters = stream->recommended_filters();
for( auto & filter_name : recommended_filters )
{
sensor_info.proxy->add_processing_block( filter_name );
}
} ); // End foreach_stream lambda


Expand Down Expand Up @@ -1225,6 +1326,16 @@ namespace librealsense
}
// TODO - need to register extrinsics group in dev?
} //End dds_device_proxy constructor

std::shared_ptr< dds_sensor_proxy> create_sensor( const std::string & sensor_name )
{
if( sensor_name.compare( "RGB Camera" ) == 0 )
return std::make_shared< dds_color_sensor_proxy>( sensor_name, this, _dds_dev );
else if( sensor_name.compare( "Stereo Module" ) == 0 )
return std::make_shared< dds_depth_sensor_proxy>( sensor_name, this, _dds_dev );

return std::make_shared< dds_sensor_proxy >( sensor_name, this, _dds_dev );
}
};

class dds_device_info : public device_info
Expand Down
11 changes: 10 additions & 1 deletion src/software-device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,5 +397,14 @@ namespace librealsense
register_option(option, (is_writable? std::make_shared<float_option>(range) :
std::make_shared<readonly_float_option>(range)));
}
}

void software_recommended_proccesing_blocks::add_processing_block( std::shared_ptr< processing_block_interface > const & block )
{
if( ! block )
throw invalid_value_exception( "trying to add an empty software processing block" );

_blocks.push_back( block );
}

} // namespace librealsense

9 changes: 9 additions & 0 deletions src/software-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ namespace librealsense
}
~software_recommended_proccesing_blocks() override {}

void add_processing_block( std::shared_ptr< processing_block_interface > const & block );

private:
processing_blocks _blocks;
};
Expand Down Expand Up @@ -125,6 +127,13 @@ namespace librealsense

std::array< metadata_array_value, RS2_FRAME_METADATA_ACTUAL_COUNT > _metadata_map;

processing_blocks get_recommended_processing_blocks() const override
{
return _pbs.get_recommended_processing_blocks();
}

software_recommended_proccesing_blocks & get_software_recommended_proccesing_blocks() { return _pbs; }

private:
friend class software_device;
stream_profiles _profiles;
Expand Down
6 changes: 2 additions & 4 deletions third-party/realdds/doc/DDS topics.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ On the discovery phase the camera server will send a **device-header** message,
#### device-options format example

"id":"device-options",
"n-options": 2, //Integer, number of device options
"options": //Array of supported options, the size of n-options
"options": //Array of supported options
[
{"description":"Enable/Disable global timestamp","name":"Global Time Enabled","range-default":1.0,"range-max":1.0,"range-min":0.0,"range-step":1.0,"value":1.0},
{"description":"HDR Option","name":"Hdr Enabled","range-default":0.0,"range-max":1.0,"range-min":0.0,"range-step":1.0,"value":0.0}
Expand All @@ -98,8 +97,7 @@ On the discovery phase the camera server will send a **device-header** message,
[640,480,320.14276123046875,238.4058837890625,378.80572509765625,378.80572509765625,4,0.0,0.0,0.0,0.0,0.0]
[1280,720,640.2379150390625,357.3431396484375,631.3428955078125,631.3428955078125,4,0.0,0.0,0.0,0.0,0.0]
]
"n-options":3, //Integer, number of device options
"options": //Array of supported options, the size of n-options
"options": //Array of supported options
[
{"description":"Enable / disable backlight compensation","name":"Backlight Compensation","range-default":0.0,"range-max":1.0,"range-min":0.0,"range-step":1.0,"value":0.0},
{"description":"UVC image brightness","name":"Brightness","range-default":0.0,"range-max":64.0,"range-min":-64.0,"range-step":1.0,"value":0.0},
Expand Down
4 changes: 4 additions & 0 deletions third-party/realdds/include/realdds/dds-stream-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <memory>
#include <string>
#include <vector>


namespace realdds {
Expand All @@ -29,6 +30,7 @@ class dds_stream_base : public std::enable_shared_from_this< dds_stream_base >
int _default_profile_index = 0;
dds_stream_profiles _profiles;
dds_options _options;
std::vector< std::string > _recommended_filters;
bool _metadata_enabled = false;

dds_stream_base( std::string const & stream_name, std::string const & sensor_name );
Expand All @@ -40,12 +42,14 @@ class dds_stream_base : public std::enable_shared_from_this< dds_stream_base >
void enable_metadata(); // Must call before init_profiles
void init_profiles( dds_stream_profiles const & profiles, int default_profile_index = 0 );
void init_options( dds_options const & options );
void set_recommended_filters( std::vector< std::string > && recommended_filters );

std::string const & name() const { return _name; }
std::string const & sensor_name() const { return _sensor_name; }
dds_stream_profiles const & profiles() const { return _profiles; }
int default_profile_index() const { return _default_profile_index; }
dds_options const & options() const { return _options; }
std::vector< std::string > const & recommended_filters() const { return _recommended_filters; }
bool metadata_enabled() const { return _metadata_enabled; }

std::shared_ptr< dds_stream_profile > default_profile() const
Expand Down
24 changes: 19 additions & 5 deletions third-party/realdds/src/dds-device-impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,15 @@ bool dds_device::impl::init()
}
else if( state_type::WAIT_FOR_DEVICE_OPTIONS == state && id == "device-options" )
{
LOG_DEBUG( "... device-options: " << j["n-options"] << " options received" );

for( auto & option_json : j["options"] )
if( rsutils::json::has( j, "options" ) )
{
auto option = dds_option::from_json( option_json, _info.name );
_options.push_back( option );
LOG_DEBUG( "... device-options: " << j["options"].size() << " options received" );

for( auto & option_json : j["options"] )
{
auto option = dds_option::from_json( option_json, _info.name );
_options.push_back( option );
}
}

if( n_streams_expected )
Expand Down Expand Up @@ -410,6 +413,17 @@ bool dds_device::impl::init()
}
}

if( rsutils::json::has( j, "recommended-filters" ) )
{
std::vector< std::string > filter_names;
for( auto & filter : j["recommended-filters"] )
{
filter_names.push_back( filter );
}

stream_it->second->set_recommended_filters( std::move( filter_names ) );
}

if( _streams.size() >= n_streams_expected )
state = state_type::DONE;
else
Expand Down
10 changes: 7 additions & 3 deletions third-party/realdds/src/dds-device-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ static void on_discovery_device_header( size_t const n_streams, const dds_option
device_options.push_back( std::move( opt->to_json() ) );
topics::flexible_msg device_options_message( json {
{ "id", "device-options" },
{ "n-options", options.size() },
{ "options" , device_options }
} );
LOG_DEBUG( "-----> JSON = " << device_options_message.json_data().dump() );
Expand Down Expand Up @@ -100,6 +99,7 @@ static void on_discovery_stream_header( std::shared_ptr< dds_stream_server > con
auto stream_options = nlohmann::json::array();
for( auto & opt : stream->options() )
stream_options.push_back( std::move( opt->to_json() ) );

auto video_stream = std::dynamic_pointer_cast< dds_video_stream_server >( stream );
auto motion_stream = std::dynamic_pointer_cast< dds_motion_stream_server >( stream );
auto intrinsics = nlohmann::json::array();
Expand All @@ -108,12 +108,16 @@ static void on_discovery_stream_header( std::shared_ptr< dds_stream_server > con
intrinsics.push_back( intr.to_json() );
if( motion_stream )
intrinsics.push_back( motion_stream->get_intrinsics().to_json() );

auto stream_filters = nlohmann::json::array();
for( auto & filter : stream->recommended_filters() )
stream_filters.push_back( filter );
topics::flexible_msg stream_options_message( json {
{ "id", "stream-options" },
{ "stream-name", stream->name() },
{ "n-options", stream->options().size() },
{ "options" , stream_options },
{ "intrinsics" , intrinsics }
{ "intrinsics" , intrinsics },
{ "recommended-filters", stream_filters },
} );
LOG_DEBUG( "-----> JSON = " << stream_options_message.json_data().dump() );
LOG_DEBUG( "-----> JSON size = " << stream_options_message.json_data().dump().length() );
Expand Down
11 changes: 11 additions & 0 deletions third-party/realdds/src/dds-stream-base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dds_stream_base::dds_stream_base( std::string const & name,
{
}


void dds_stream_base::enable_metadata()
{
// Ensure no changes after initialization stage
Expand All @@ -24,6 +25,7 @@ void dds_stream_base::enable_metadata()
_metadata_enabled = true;
}


void dds_stream_base::init_profiles( dds_stream_profiles const & profiles, int default_profile_index )
{
if( !_profiles.empty() )
Expand Down Expand Up @@ -57,6 +59,15 @@ void dds_stream_base::init_options( dds_options const & options )
}


void dds_stream_base::set_recommended_filters( std::vector< std::string > && recommended_filters )
{
if( !_recommended_filters.empty() )
DDS_THROW( runtime_error, "stream '" + _name + "' recommended filters are already set" );

_recommended_filters = recommended_filters;
}


void dds_stream_base::check_profile( std::shared_ptr< dds_stream_profile > const & profile ) const
{
if( ! profile )
Expand Down
8 changes: 7 additions & 1 deletion tools/dds/dds-server/lrs-device-controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,9 @@ std::vector< std::shared_ptr< realdds::dds_stream_server > > lrs_device_controll
motion_server->set_intrinsics( std::move( stream_name_to_motion_intrinsics[stream_name] ) );
}

// Get supported options and recommended filters for this stream
realdds::dds_options options;
// Get supported options for this stream
std::vector< std::string > filter_names;
for( auto sensor : _rs_dev.query_sensors() )
{
std::string const sensor_name = sensor.get_info( RS2_CAMERA_INFO_NAME );
Expand Down Expand Up @@ -246,9 +247,14 @@ std::vector< std::shared_ptr< realdds::dds_stream_server > > lrs_device_controll
}
// sensor.stop();
// sensor.close();

auto recommended_filters = sensor.get_recommended_filters();
for( auto const & filter : recommended_filters )
filter_names.push_back( filter.get_info( RS2_CAMERA_INFO_NAME ) );
}
}
server->init_options( options );
server->set_recommended_filters( std::move( filter_names ) );

servers.push_back( server );
}
Expand Down