You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
5.6 KiB
231 lines
5.6 KiB
// License: Apache 2.0. See LICENSE file in root directory.
|
|
// Copyright(c) 2021 Intel Corporation. All Rights Reserved.
|
|
|
|
#include "core/depth-frame.h"
|
|
#include "composite-frame.h"
|
|
#include "core/stream-profile-interface.h"
|
|
#include "archive.h"
|
|
#include "metadata-parser.h"
|
|
#include "core/enum-helpers.h"
|
|
|
|
#include <rsutils/string/from.h>
|
|
|
|
|
|
namespace librealsense {
|
|
|
|
|
|
std::ostream & operator<<( std::ostream & s, const frame_interface & f )
|
|
{
|
|
if( !&f )
|
|
{
|
|
s << "[null]";
|
|
}
|
|
else
|
|
{
|
|
auto composite = dynamic_cast<const composite_frame *>(&f);
|
|
if( composite )
|
|
{
|
|
s << "[";
|
|
for( int i = 0; i < composite->get_embedded_frames_count(); i++ )
|
|
{
|
|
s << *composite->get_frame( i );
|
|
}
|
|
s << "]";
|
|
}
|
|
else
|
|
{
|
|
s << "[" << get_abbr_string( f.get_stream()->get_stream_type() );
|
|
s << f.get_stream()->get_unique_id();
|
|
s << " " << f.get_header();
|
|
s << "]";
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
std::ostream & operator<<( std::ostream & os, frame_header const & header )
|
|
{
|
|
os << "#" << header.frame_number;
|
|
os << " @" << rsutils::string::from( header.timestamp );
|
|
if( header.timestamp_domain != RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK )
|
|
os << "/" << rs2_timestamp_domain_to_string( header.timestamp_domain );
|
|
return os;
|
|
}
|
|
|
|
|
|
std::ostream & operator<<( std::ostream & os, frame_holder const & f )
|
|
{
|
|
return os << *f.frame;
|
|
}
|
|
|
|
|
|
frame::frame( frame && r )
|
|
: ref_count( r.ref_count.exchange( 0 ) )
|
|
, owner( r.owner )
|
|
, on_release()
|
|
, _kept( r._kept.exchange( false ) )
|
|
{
|
|
*this = std::move( r );
|
|
if( owner )
|
|
metadata_parsers = owner->get_md_parsers();
|
|
}
|
|
|
|
frame & frame::operator=( frame && r )
|
|
{
|
|
data = std::move( r.data );
|
|
owner = r.owner;
|
|
ref_count = r.ref_count.exchange( 0 );
|
|
_kept = r._kept.exchange( false );
|
|
on_release = std::move( r.on_release );
|
|
additional_data = std::move( r.additional_data );
|
|
r.owner.reset();
|
|
if( owner )
|
|
metadata_parsers = owner->get_md_parsers();
|
|
if( r.metadata_parsers )
|
|
metadata_parsers = std::move( r.metadata_parsers );
|
|
return *this;
|
|
}
|
|
archive_interface * frame::get_owner() const
|
|
{
|
|
return owner.get();
|
|
}
|
|
|
|
std::shared_ptr< sensor_interface > frame::get_sensor() const
|
|
{
|
|
auto res = sensor.lock();
|
|
if( ! res )
|
|
{
|
|
auto archive = get_owner();
|
|
if( archive )
|
|
return archive->get_sensor();
|
|
}
|
|
return res;
|
|
}
|
|
void frame::set_sensor( std::shared_ptr< sensor_interface > s )
|
|
{
|
|
sensor = s;
|
|
}
|
|
|
|
void frame::release()
|
|
{
|
|
if( ref_count.fetch_sub( 1 ) == 1 && owner )
|
|
{
|
|
unpublish();
|
|
on_release();
|
|
owner->unpublish_frame( this );
|
|
}
|
|
}
|
|
|
|
void frame::keep()
|
|
{
|
|
if( ! _kept.exchange( true ))
|
|
{
|
|
if (owner)
|
|
owner->keep_frame( this );
|
|
}
|
|
}
|
|
|
|
frame_interface * frame::publish( std::shared_ptr< archive_interface > new_owner )
|
|
{
|
|
owner = new_owner;
|
|
_kept = false;
|
|
return owner->publish_frame( this );
|
|
}
|
|
|
|
bool frame::find_metadata( rs2_frame_metadata_value frame_metadata, rs2_metadata_type * p_value ) const
|
|
{
|
|
if( ! metadata_parsers )
|
|
return false;
|
|
auto parsers = metadata_parsers->equal_range( frame_metadata );
|
|
|
|
bool value_retrieved = false;
|
|
for( auto it = parsers.first; it != parsers.second; ++it )
|
|
if( it->second->find( *this, p_value ) )
|
|
value_retrieved = true;
|
|
|
|
return value_retrieved;
|
|
}
|
|
|
|
int frame::get_frame_data_size() const
|
|
{
|
|
return (int)data.size();
|
|
}
|
|
|
|
const uint8_t * frame::get_frame_data() const
|
|
{
|
|
const uint8_t * frame_data = data.data();
|
|
|
|
if( on_release.get_data() )
|
|
{
|
|
frame_data = static_cast< const uint8_t * >( on_release.get_data() );
|
|
}
|
|
|
|
return frame_data;
|
|
}
|
|
|
|
rs2_timestamp_domain frame::get_frame_timestamp_domain() const
|
|
{
|
|
return additional_data.timestamp_domain;
|
|
}
|
|
|
|
rs2_time_t frame::get_frame_timestamp() const
|
|
{
|
|
return additional_data.timestamp;
|
|
}
|
|
|
|
unsigned long long frame::get_frame_number() const
|
|
{
|
|
return additional_data.frame_number;
|
|
}
|
|
|
|
double frame::calc_actual_fps() const
|
|
{
|
|
auto const dt = ( additional_data.timestamp - additional_data.last_timestamp );
|
|
if( dt > 0. && additional_data.frame_number > additional_data.last_frame_number )
|
|
{
|
|
auto const n_frames = additional_data.frame_number - additional_data.last_frame_number;
|
|
return 1000. * n_frames / dt;
|
|
}
|
|
|
|
return 0.; // Unknown actual FPS
|
|
}
|
|
|
|
rs2_time_t frame::get_frame_system_time() const
|
|
{
|
|
return additional_data.system_time;
|
|
}
|
|
|
|
float depth_frame::get_distance( int x, int y ) const
|
|
{
|
|
// If this frame does not itself contain Z16 depth data,
|
|
// fall back to the original frame it was created from
|
|
if( _original && get_stream()->get_format() != RS2_FORMAT_Z16 )
|
|
return ( (depth_frame *)_original.frame )->get_distance( x, y );
|
|
|
|
uint64_t pixel = 0;
|
|
switch( get_bpp() / 8 ) // bits per pixel
|
|
{
|
|
case 1:
|
|
pixel = get_frame_data()[y * get_width() + x];
|
|
break;
|
|
case 2:
|
|
pixel = reinterpret_cast< const uint16_t * >( get_frame_data() )[y * get_width() + x];
|
|
break;
|
|
case 4:
|
|
pixel = reinterpret_cast< const uint32_t * >( get_frame_data() )[y * get_width() + x];
|
|
break;
|
|
case 8:
|
|
pixel = reinterpret_cast< const uint64_t * >( get_frame_data() )[y * get_width() + x];
|
|
break;
|
|
default:
|
|
throw std::runtime_error( rsutils::string::from()
|
|
<< "Unrecognized depth format " << int( get_bpp() / 8 ) << " bytes per pixel" );
|
|
}
|
|
|
|
return pixel * get_units();
|
|
}
|
|
|
|
|
|
} // namespace librealsense
|