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

basic dds metadata tests (just the beginning) #11665

Merged
merged 35 commits into from
Apr 17, 2023
Merged

Conversation

maloel
Copy link
Collaborator

@maloel maloel commented Apr 10, 2023

  • moved the syncer out of context.cpp and into realdds
    • this presented a problem, as there is no frame_holder outside of librealsense
    • I considered making it sync a device::image like it was before but that would have brought back the profile storage thing and wasn't as translatable to a different framework like for testing; decided against it
    • finally settled on a simple unique_ptr approach with a deleter for on-release that's now passed to the syncer
  • fixed a couple of syncer bugs, plus a bug in context which did not pick up frame metadata correctly
  • added some more missing functionality in pyrealdds, for testing
  • exposed syncer in pyrealdds (though no tests in this review are yet using it)
  • added initial (just the beginning) of no-metadata and with-metadata tests
    • these are the first tests that actually transfer images over dds, I believe

By the way:

  • move dds-trinsics out of dds-defines
  • dds_time is now more compact with a better pyrealdds repr
  • added timestamp to topics::device::image
  • improved shorten_json_string
  • json uses strings for keys, so passing in const char * is a "waste" in that strlen and an alloc is then used to build a string
    • instead, if we already have a string, better to pass it in -- so rsutils::json:: functions have been updated to accept strings
    • dds metadata was using rs2_frame_metadata_to_string which returns a const char * -- so, instead, we now directly call librealsense::get_string( metadata ) which was changed to return a string reference and use array indexing -- should now be a lot faster
  • changed dds.wait_for_devices to be context notification based
  • improve test.remote; introduce test.closure for easier test writing; revised test-librs-connections
  • fixed some warnings and several flushing issues evident in Linux
  • changed the GHA linux DDS tests to run in RSUSB and not run any other-than-dds tests

Many of these are better looked at by commit rather than going over all the changes together.

Still to do:

@maloel maloel requested a review from OhadMeir April 10, 2023 11:22
src/to-string.cpp Outdated Show resolved Hide resolved
}
std::vector< std::string > arr( RS2_FRAME_METADATA_COUNT );
#define CASE( X ) STRARR( arr, FRAME_METADATA, X );
CASE( FRAME_COUNTER )
Copy link
Contributor

Choose a reason for hiding this comment

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

Its a matter of style but I prefer not to define and undefine CASE, and probably doing so for all other types as well.
You can change CASE( FRAME_COUNTER ) to STRARR( arr, FRAME_METADATA, FRAME_COUNTER ) and you can do it easily for all the cases here at once in VS using vertical editing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Replied on call :)

void enqueue_frame( key_type, frame_holder && );
void enqueue_metadata( key_type, metadata_type && );

dds_metadata_syncer & on_frame_release( on_frame_release_callback cb )
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that on_xxx functions should return a value.
They are intended to set an aspect of the syncer behavior, nothing about them or their name implies returning something, let alone this syncer object.

Using this to chain function calls is not clear syntax, especially when passing lambda as input parameters. It is more readable to call syncer_object.on_xxx(...) multiple times expressing the object name.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I guess it's a matter of preference: I see no difference between these and operator=, for example. And the practice is well-in-use if you're used to pybind, for another example, or simply want to construct an object in multiple steps while still keeping it unnamed.
In this case:

                _stream_name_to_syncer[dds_stream->name()]
                    .on_frame_release( frame_releaser )
                    .on_frame_ready(
                        [this]( syncer_type::frame_holder && fh, json && md ) { ... } );

Is now:

                auto & syncer = _stream_name_to_syncer[dds_stream->name()];
                syncer.on_frame_release( frame_releaser );
                syncer.on_frame_ready(
                    [this]( syncer_type::frame_holder && fh, json && md ) { ... } );

@@ -187,19 +188,21 @@ namespace librealsense
assert( _device_watcher->is_stopped() );

#ifdef BUILD_WITH_DDS
if( rsutils::json::get< bool >( settings, "dds-discovery", true ) )
if( rsutils::json::get< bool >( settings, std::string( "dds-discovery", 13 ), true ) )
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you have to explicitly use the string size? It is inconvenient and error prone

Looks like it should work without the explicit size (using constructor number 5, not 4)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's optional, but I dislike using strlen for constants

Copy link
Contributor

@OhadMeir OhadMeir Apr 16, 2023

Choose a reason for hiding this comment

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

What if you miscount?
Will the json find the right string while searching for dds-discover or dds-discovery (extra char can be of any value) or would it throw?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's a constant. It's like getting a constant value wrong.
This is why we have a CR and testing :)


// Expected metadata for all depth images
if( rsutils::json::has( md_header, "depth-units" ) )
f->additional_data.depth_units = rsutils::json::get< float >( md_header, "depth-units" );
rsutils::json::get_ex( md_header, std::string( "depth-units", 11 ), &f->additional_data.depth_units );
Copy link
Contributor

Choose a reason for hiding this comment

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

Will throw for color frames

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

get_ex returns a bool on failure, and checks if it's there first. It can still throw, but not if it's not there.

void dds_metadata_syncer::enqueue_frame( key_type id, frame_holder && frame )
{
std::lock_guard< std::mutex > lock( _queues_lock );
while( _frame_queue.size() >= max_frame_queue_size )
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that with your changes max_frame_queue_size should be 1.
If no metadata is received, we want to delay the frame for maximum of one other frame. Here it can be delayed for 2 frames.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What changes are you referring to, that we can change the limit? I'm not objecting (though I'm hesitant to change this PR - I prefer waiting until after I have the unit-tests in), just curious.

Copy link
Contributor

Choose a reason for hiding this comment

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

Changes like checking the queue size here and not in search_for_match. We can leave for now, until the unit-tests will be completed. Just need to make sure not to delay the frame for too long

key_frame & synced = _frame_queue.front();
auto & fh = synced.second;

metadata_type md = std::move( _metadata_queue.front().second );
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need md and moving twice?
Can pop the queue after _on_frame_ready

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You'll see in my next PR that we need to push/pop before any callbacks, since stuff can happen during the callbacks.

context = rs.context( '{"dds-domain":123,"dds-participant-name":"librs"}' )
# The DDS devices take time to be recognized and we just created the context; we
# should not see them yet!
test.check( len( context.query_devices( only_sw_devices )) != 2 )
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that we need this check. You don't know the timing and discovery might have happened, especially if working in shared memory.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought you'd want it based on the original comments.
I agree, but the chances that it'll fail are slim.
Anyway, I commented out the line so it's still explained and there...

Copy link
Contributor

@OhadMeir OhadMeir left a comment

Choose a reason for hiding this comment

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

Should add some more metadata tests - image after metadata, etc... but will be in future PRs

@maloel maloel merged commit 4359306 into IntelRealSense:dds Apr 17, 2023
@maloel maloel deleted the dds branch April 17, 2023 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants