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.
1185 lines
39 KiB
1185 lines
39 KiB
// License: Apache 2.0. See LICENSE file in root directory.
|
|
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
|
|
|
|
#ifndef LIBREALSENSE_RS2_FRAME_HPP
|
|
#define LIBREALSENSE_RS2_FRAME_HPP
|
|
|
|
#include "rs_types.hpp"
|
|
|
|
namespace rs2
|
|
{
|
|
class frame_source;
|
|
class frame_queue;
|
|
class syncer;
|
|
class processing_block;
|
|
class pointcloud;
|
|
class sensor;
|
|
class frame;
|
|
class pipeline_profile;
|
|
class points;
|
|
class video_stream_profile;
|
|
|
|
class stream_profile
|
|
{
|
|
public:
|
|
/**
|
|
* Class to store the profile of stream
|
|
*/
|
|
stream_profile() : _profile(nullptr) {}
|
|
|
|
/**
|
|
* Return the specific stream index
|
|
* \return int - stream index
|
|
*/
|
|
int stream_index() const { return _index; }
|
|
/**
|
|
* Return the stream type
|
|
* \return rs2_stream - stream type
|
|
*/
|
|
rs2_stream stream_type() const { return _type; }
|
|
/**
|
|
* Return the stream format
|
|
* \return rs2_format - stream format
|
|
*/
|
|
rs2_format format() const { return _format; }
|
|
/**
|
|
* Return the stream frame per second
|
|
* \return int - frame rate
|
|
*/
|
|
int fps() const { return _framerate; }
|
|
/**
|
|
* Return the assigned unique index when the stream was created
|
|
* \return int - unique id
|
|
*/
|
|
int unique_id() const { return _uid; }
|
|
|
|
/**
|
|
* Clone the current profile and change the type, index and format to input parameters
|
|
* \param[in] type - will change the stream type from the cloned profile.
|
|
* \param[in] index - will change the stream index from the cloned profile.
|
|
* \param[in] format - will change the stream format from the cloned profile.
|
|
* \return stream_profile - return the cloned stream profile.
|
|
*/
|
|
stream_profile clone(rs2_stream type, int index, rs2_format format) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto ref = rs2_clone_stream_profile(_profile, type, index, format, &e);
|
|
error::handle(e);
|
|
stream_profile res(ref);
|
|
res._clone = std::shared_ptr<rs2_stream_profile>(ref, [](rs2_stream_profile* r) { rs2_delete_stream_profile(r); });
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* Comparison operator, compare if two stream profiles are the same
|
|
* \param[in] rhs - stream profile to compare with.
|
|
* \return bool - true or false.
|
|
*/
|
|
bool operator==(const stream_profile& rhs)
|
|
{
|
|
return stream_index() == rhs.stream_index() &&
|
|
stream_type() == rhs.stream_type() &&
|
|
format() == rhs.format() &&
|
|
fps() == rhs.fps();
|
|
}
|
|
|
|
/**
|
|
* Template function, checking if the instance belongs to specific class type
|
|
* \return bool - true or false.
|
|
*/
|
|
template<class T>
|
|
bool is() const
|
|
{
|
|
T extension(*this);
|
|
return extension;
|
|
}
|
|
|
|
/**
|
|
* Template function, casting the instance as another class type
|
|
* \return class instance - pointer or null.
|
|
*/
|
|
template<class T>
|
|
T as() const
|
|
{
|
|
T extension(*this);
|
|
return extension;
|
|
}
|
|
|
|
/**
|
|
* Return the string of stream name
|
|
* \return string - stream name.
|
|
*/
|
|
std::string stream_name() const
|
|
{
|
|
std::stringstream ss;
|
|
ss << rs2_stream_to_string(stream_type());
|
|
if (stream_index() != 0) ss << " " << stream_index();
|
|
return ss.str();
|
|
}
|
|
|
|
/**
|
|
* Checks if stream profile is marked/assigned as default, meaning that the profile will be selected when the user requests stream configuration using wildcards (RS2_DEPTH, -1,-1,...
|
|
* \return bool - true or false.
|
|
*/
|
|
bool is_default() const { return _default; }
|
|
|
|
/**
|
|
* Checks if the profile is valid
|
|
* \return bool - true or false.
|
|
*/
|
|
operator bool() const { return _profile != nullptr; }
|
|
|
|
/**
|
|
* Get back the internal stream profile instance
|
|
* \return rs2_stream_profile* - internal implementation of the profile class
|
|
*/
|
|
const rs2_stream_profile* get() const { return _profile; }
|
|
|
|
/**
|
|
Operator implement, return the internal stream profile instance.
|
|
* \return rs2_stream_profile* - internal instance to communicate with real implementation.
|
|
*/
|
|
/**
|
|
* Get the extrinsic transformation between two profiles (representing physical sensors)
|
|
* \param[in] stream_profile to - the stream profile (another sensor) to be based to return the extrinsic
|
|
* \return rs2_stream_profile* - internal instance to communicate with real implementation.
|
|
*/
|
|
rs2_extrinsics get_extrinsics_to(const stream_profile& to) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_extrinsics res;
|
|
rs2_get_extrinsics(get(), to.get(), &res, &e);
|
|
error::handle(e);
|
|
return res;
|
|
}
|
|
/**
|
|
* Assign extrinsic transformation parameters to a specific profile (sensor). The extrinsic information is generally available as part of the camera calibration, and librealsense is responsible for retrieving and assigning these parameters where appropriate.
|
|
* This specific function is intended for synthetic/mock-up (software) devices for which the parameters are produced and injected by the user.
|
|
* \param[in] stream_profile to - which stream profile to be registered with the extrinsic.
|
|
* \param[in] rs2_extrinsics extrinsics - the extrinsics to be registered.
|
|
*/
|
|
void register_extrinsics_to(const stream_profile& to, rs2_extrinsics extrinsics)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_register_extrinsics(get(), to.get(), extrinsics, &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
bool is_cloned() { return bool(_clone); }
|
|
explicit stream_profile(const rs2_stream_profile* profile) : _profile(profile)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_get_stream_profile_data(_profile, &_type, &_format, &_index, &_uid, &_framerate, &e);
|
|
error::handle(e);
|
|
|
|
_default = !!(rs2_is_stream_profile_default(_profile, &e));
|
|
error::handle(e);
|
|
|
|
}
|
|
operator const rs2_stream_profile*() { return _profile; }
|
|
explicit operator std::shared_ptr<rs2_stream_profile>() { return _clone; }
|
|
|
|
protected:
|
|
friend class rs2::sensor;
|
|
friend class rs2::frame;
|
|
friend class rs2::pipeline_profile;
|
|
friend class rs2::video_stream_profile;
|
|
|
|
const rs2_stream_profile* _profile;
|
|
std::shared_ptr<rs2_stream_profile> _clone;
|
|
|
|
int _index = 0;
|
|
int _uid = 0;
|
|
int _framerate = 0;
|
|
rs2_format _format = RS2_FORMAT_ANY;
|
|
rs2_stream _type = RS2_STREAM_ANY;
|
|
|
|
bool _default = false;
|
|
};
|
|
|
|
class video_stream_profile : public stream_profile
|
|
{
|
|
public:
|
|
video_stream_profile() : stream_profile() {}
|
|
|
|
/**
|
|
* Stream profile instance which contains additional video attributes
|
|
* \param[in] stream_profile sp - assign exisiting stream_profile to this instance.
|
|
*/
|
|
explicit video_stream_profile(const stream_profile& sp)
|
|
: stream_profile(sp)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if ((rs2_stream_profile_is(sp.get(), RS2_EXTENSION_VIDEO_PROFILE, &e) == 0 && !e))
|
|
{
|
|
_profile = nullptr;
|
|
}
|
|
error::handle(e);
|
|
|
|
if (_profile)
|
|
{
|
|
rs2_get_video_stream_resolution(_profile, &_width, &_height, &e);
|
|
error::handle(e);
|
|
}
|
|
}
|
|
|
|
int width() const
|
|
{
|
|
return _width;
|
|
}
|
|
|
|
int height() const
|
|
{
|
|
return _height;
|
|
}
|
|
/**
|
|
* Get stream profile instrinsics attributes
|
|
* \return rs2_intrinsics - stream intrinsics.
|
|
*/
|
|
rs2_intrinsics get_intrinsics() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_intrinsics intr;
|
|
rs2_get_video_stream_intrinsics(_profile, &intr, &e);
|
|
error::handle(e);
|
|
return intr;
|
|
}
|
|
|
|
bool operator==(const video_stream_profile& other) const
|
|
{
|
|
return (((stream_profile&)*this)==other &&
|
|
width() == other.width() &&
|
|
height() == other.height());
|
|
}
|
|
|
|
using stream_profile::clone;
|
|
|
|
/**
|
|
* Clone current profile and change the type, index and format to input parameters
|
|
* \param[in] type - will change the stream type from the cloned profile.
|
|
* \param[in] index - will change the stream index from the cloned profile.
|
|
* \param[in] format - will change the stream format from the cloned profile.
|
|
* \param[in] width - will change the width of the profile
|
|
* \param[in] height - will change the height of the profile
|
|
* \param[in] intr - will change the intrinsics of the profile
|
|
* \return stream_profile - return the cloned stream profile.
|
|
*/
|
|
stream_profile clone(rs2_stream type, int index, rs2_format format, int width, int height, const rs2_intrinsics& intr) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto ref = rs2_clone_video_stream_profile(_profile, type, index, format, width, height, &intr, &e);
|
|
error::handle(e);
|
|
stream_profile res(ref);
|
|
res._clone = std::shared_ptr<rs2_stream_profile>(ref, [](rs2_stream_profile* r) { rs2_delete_stream_profile(r); });
|
|
|
|
return res;
|
|
}
|
|
private:
|
|
int _width = 0;
|
|
int _height = 0;
|
|
};
|
|
|
|
|
|
class motion_stream_profile : public stream_profile
|
|
{
|
|
public:
|
|
/**
|
|
* Stream profile instance which contains IMU-specific intrinsics.
|
|
* \param[in] stream_profile sp - assign exisiting stream_profile to this instance.
|
|
*/
|
|
explicit motion_stream_profile(const stream_profile& sp)
|
|
: stream_profile(sp)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if ((rs2_stream_profile_is(sp.get(), RS2_EXTENSION_MOTION_PROFILE, &e) == 0 && !e))
|
|
{
|
|
_profile = nullptr;
|
|
}
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Returns scale/bias/covariances of a the motion sensors
|
|
* \return rs2_motion_device_intrtinsic - stream motion intrinsics
|
|
*/
|
|
rs2_motion_device_intrinsic get_motion_intrinsics() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_motion_device_intrinsic intrin;
|
|
rs2_get_motion_intrinsics(_profile, &intrin, &e);
|
|
error::handle(e);
|
|
return intrin;
|
|
}
|
|
};
|
|
|
|
class pose_stream_profile : public stream_profile
|
|
{
|
|
public:
|
|
/**
|
|
* Stream profile instance with an explicit pose extension type.
|
|
* \param[in] stream_profile sp - assign exisiting stream_profile to this instance.
|
|
*/
|
|
explicit pose_stream_profile(const stream_profile& sp)
|
|
: stream_profile(sp)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if ((rs2_stream_profile_is(sp.get(), RS2_EXTENSION_POSE_PROFILE, &e) == 0 && !e))
|
|
{
|
|
_profile = nullptr;
|
|
}
|
|
error::handle(e);
|
|
}
|
|
};
|
|
|
|
/**
|
|
Interface for frame filtering functionality
|
|
*/
|
|
class filter_interface
|
|
{
|
|
public:
|
|
virtual rs2::frame process(rs2::frame frame) const = 0;
|
|
virtual ~filter_interface() = default;
|
|
};
|
|
|
|
class frame
|
|
{
|
|
public:
|
|
/**
|
|
* Base class for multiple frame extensions
|
|
*/
|
|
frame() : frame_ref(nullptr) {}
|
|
/**
|
|
* Base class for multiple frame extensions with internal frame handle
|
|
* \param[in] rs2_frame frame_ref - internal frame instance
|
|
*/
|
|
frame(rs2_frame* ref) : frame_ref(ref)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (ref)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_number(ref, &e);
|
|
if (!e)
|
|
frame_number = r;
|
|
auto s = rs2_get_frame_stream_profile(ref, &e);
|
|
if (!e)
|
|
profile = stream_profile(s);
|
|
}
|
|
else
|
|
{
|
|
frame_number = 0;
|
|
profile = stream_profile();
|
|
}
|
|
#endif
|
|
}
|
|
/**
|
|
* Change the internal frame handle to the one in parameter, then put the other frame internal frame handle to nullptr
|
|
* \param[in] frame other - another frame instance to be pointed to
|
|
*/
|
|
frame(frame&& other) noexcept : frame_ref(other.frame_ref)
|
|
{
|
|
other.frame_ref = nullptr;
|
|
#ifdef _DEBUG
|
|
frame_number = other.frame_number;
|
|
profile = other.profile;
|
|
#endif
|
|
}
|
|
/**
|
|
* Change the internal frame handle to the one in parameter, the function exchange the internal frame handle.
|
|
* \param[in] frame other - another frame instance to be pointed to
|
|
*/
|
|
frame& operator=(frame other)
|
|
{
|
|
swap(other);
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Set the internal frame handle to the one in parameter, the function create additional reference if internal reference exist.
|
|
* \param[in] frame other - another frame instance to be pointed to
|
|
*/
|
|
frame(const frame& other)
|
|
: frame_ref(other.frame_ref)
|
|
{
|
|
if (frame_ref) add_ref();
|
|
#ifdef _DEBUG
|
|
frame_number = other.frame_number;
|
|
profile = other.profile;
|
|
#endif
|
|
}
|
|
/**
|
|
* Swap the internal frame handle with the one in parameter
|
|
* \param[in] frame other - another frame instance to be swaped
|
|
*/
|
|
void swap(frame& other)
|
|
{
|
|
std::swap(frame_ref, other.frame_ref);
|
|
|
|
#ifdef _DEBUG
|
|
std::swap(frame_number, other.frame_number);
|
|
std::swap(profile, other.profile);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* releases the frame handle
|
|
*/
|
|
~frame()
|
|
{
|
|
if (frame_ref)
|
|
{
|
|
rs2_release_frame(frame_ref);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* keep the frame, otherwise if no refernce to the frame, the frame will be released.
|
|
*/
|
|
void keep() { rs2_keep_frame(frame_ref); }
|
|
|
|
/**
|
|
* Parenthesis operator check if internal frame handle is valid.
|
|
* \return bool - true or false.
|
|
*/
|
|
operator bool() const { return frame_ref != nullptr; }
|
|
|
|
rs2_sensor* get_sensor()
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_sensor(frame_ref, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* retrieve the time at which the frame was captured
|
|
* During the frame's lifetime it receives timestamps both at the device and host levels.
|
|
* The different timestamps are gathered and managed under the frame's Metadata attributes.
|
|
* Chronologically the list of timestamps comprises of:
|
|
* SENSOR_TIMESTAMP - Device clock. For video sensors designates the middle of exposure. Requires metadata support.
|
|
* FRAME_TIMESTAMP - Device clock. Stamped at the beginning of frame readout and transfer. Requires metadata support.
|
|
* BACKEND_TIMESTAMP - Host (EPOCH) clock in Kernel space. Frame transfer from USB Controller to the USB Driver.
|
|
* TIME_OF_ARRIVAL - Host (EPOCH) clock in User space. Frame transfer from the USB Driver to Librealsense.
|
|
*
|
|
* During runtime the SDK dynamically selects the most correct representaion, based on both device and host capabilities:
|
|
* In case the frame metadata is not configured:
|
|
* - The function call provides the TIME_OF_ARRIVAL stamp.
|
|
* In case the metadata is available the function returns:
|
|
* - `HW Timestamp` (FRAME_TIMESTAMP), or
|
|
* - `Global Timestamp` Host-corrected derivative of `HW Timestamp` required for multi-sensor/device synchronization
|
|
* - The user can select between the unmodified and the host-calculated Hardware Timestamp by toggling
|
|
* the `RS2_OPTION_GLOBAL_TIME_ENABLED` option.
|
|
* To query which of the three alternatives is active use `get_frame_timestamp_domain()` function call
|
|
* \return the timestamp of the frame, in milliseconds according to the elaborated flow
|
|
*/
|
|
double get_timestamp() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_timestamp(frame_ref, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/** retrieve the timestamp domain
|
|
* \return timestamp domain (clock name) for timestamp values
|
|
*/
|
|
rs2_timestamp_domain get_frame_timestamp_domain() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_timestamp_domain(frame_ref, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/** retrieve the current value of a single frame_metadata
|
|
* \param[in] frame_metadata the frame_metadata whose value should be retrieved
|
|
* \return the value of the frame_metadata
|
|
*/
|
|
rs2_metadata_type get_frame_metadata(rs2_frame_metadata_value frame_metadata) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_metadata(frame_ref, frame_metadata, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/** determine if the device allows a specific metadata to be queried
|
|
* \param[in] frame_metadata the frame_metadata to check for support
|
|
* \return true if the frame_metadata can be queried
|
|
*/
|
|
bool supports_frame_metadata(rs2_frame_metadata_value frame_metadata) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_supports_frame_metadata(frame_ref, frame_metadata, &e);
|
|
error::handle(e);
|
|
return r != 0;
|
|
}
|
|
|
|
/**
|
|
* retrieve frame number (from frame handle)
|
|
* \return the frame number of the frame, in milliseconds since the device was started
|
|
*/
|
|
unsigned long long get_frame_number() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_number(frame_ref, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* retrieve data size from frame handle
|
|
* \return the number of bytes in frame
|
|
*/
|
|
const int get_data_size() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_data_size(frame_ref, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* retrieve data from frame handle
|
|
* \return the pointer to the start of the frame data
|
|
*/
|
|
const void* get_data() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_data(frame_ref, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* retrieve stream profile from frame handle
|
|
* \return stream_profile - the pointer to the stream profile
|
|
*/
|
|
stream_profile get_profile() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto s = rs2_get_frame_stream_profile(frame_ref, &e);
|
|
error::handle(e);
|
|
return stream_profile(s);
|
|
}
|
|
|
|
/**
|
|
* Template function, checking if current instance is the type of another class
|
|
* \return bool - true or false.
|
|
*/
|
|
template<class T>
|
|
bool is() const
|
|
{
|
|
T extension(*this);
|
|
return extension;
|
|
}
|
|
/**
|
|
* Template function, cast current instance as the type of another class
|
|
* \return class instance.
|
|
*/
|
|
template<class T>
|
|
T as() const
|
|
{
|
|
T extension(*this);
|
|
return extension;
|
|
}
|
|
|
|
/**
|
|
* Retrieve back the internal frame handle
|
|
* \return rs2_frame - internal frame handle.
|
|
*/
|
|
rs2_frame* get() const { return frame_ref; }
|
|
explicit operator rs2_frame*() { return frame_ref; }
|
|
|
|
frame apply_filter(filter_interface& filter)
|
|
{
|
|
return filter.process(*this);
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* add additional reference to a frame without duplicating frame data
|
|
* \param[out] result new frame reference, release by destructor
|
|
* \return true if cloning was successful
|
|
*/
|
|
void add_ref() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_frame_add_ref(frame_ref, &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
if (frame_ref)
|
|
{
|
|
rs2_release_frame(frame_ref);
|
|
}
|
|
frame_ref = nullptr;
|
|
}
|
|
|
|
private:
|
|
friend class rs2::frame_source;
|
|
friend class rs2::frame_queue;
|
|
friend class rs2::syncer;
|
|
friend class rs2::processing_block;
|
|
friend class rs2::pointcloud;
|
|
friend class rs2::points;
|
|
|
|
rs2_frame* frame_ref;
|
|
|
|
#ifdef _DEBUG
|
|
stream_profile profile;
|
|
unsigned long long frame_number = 0;
|
|
#endif
|
|
};
|
|
|
|
class video_frame : public frame
|
|
{
|
|
public:
|
|
/**
|
|
* Extends the frame class with additional video related attributes and functions
|
|
* \param[in] frame - existing frame instance
|
|
*/
|
|
video_frame(const frame& f)
|
|
: frame(f)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (!f || (rs2_is_frame_extendable_to(f.get(), RS2_EXTENSION_VIDEO_FRAME, &e) == 0 && !e))
|
|
{
|
|
reset();
|
|
}
|
|
error::handle(e);
|
|
}
|
|
|
|
|
|
/**
|
|
* returns image width in pixels
|
|
* \return frame width in pixels
|
|
*/
|
|
int get_width() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_width(get(), &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* returns image height in pixels
|
|
* \return frame height in pixels
|
|
*/
|
|
int get_height() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_height(get(), &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* retrieve frame stride, meaning the actual line width in memory in bytes (not the logical image width)
|
|
* \return stride in bytes
|
|
*/
|
|
int get_stride_in_bytes() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_stride_in_bytes(get(), &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* retrieve bits per pixel
|
|
* \return number of bits per one pixel
|
|
*/
|
|
int get_bits_per_pixel() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto r = rs2_get_frame_bits_per_pixel(get(), &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* retrieve bytes per pixel
|
|
* \return number of bytes per one pixel
|
|
*/
|
|
int get_bytes_per_pixel() const { return get_bits_per_pixel() / 8; }
|
|
|
|
/**
|
|
* Extract the dimensions on the specific target
|
|
* \param[in] frame Left or right camera frame of specified size based on the target type
|
|
* \param[in] calib_type Calibration target type
|
|
* \param[in] target_dims_size Target dimension array size. 4 for RS2_CALIB_TARGET_RECT_GAUSSIAN_DOT_VERTICES and 8 for RS2_CALIB_TARGET_POS_GAUSSIAN_DOT_VERTICES
|
|
* \param[out] target_dims The array to hold the result target dimensions calculated.
|
|
For type RS2_CALIB_TARGET_RECT_GAUSSIAN_DOT_VERTICES and RS2_CALIB_TARGET_ROI_RECT_GAUSSIAN_DOT_VERTICES, the four rectangle side sizes in pixels with the order of top, bottom, left, and right
|
|
For type RS2_CALIB_TARGET_POS_GAUSSIAN_DOT_VERTICES, the four vertices coordinates in pixels with the order of top, bottom, left, and right
|
|
* \param[out] error If non-null, receives any error that occurs during this call, otherwise, errors are ignored
|
|
*/
|
|
bool extract_target_dimensions(rs2_calib_target_type calib_type, float* target_dims, unsigned int target_dims_size) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_extract_target_dimensions(get(), calib_type, target_dims, target_dims_size, &e);
|
|
error::handle(e);
|
|
return (e == nullptr);
|
|
}
|
|
};
|
|
|
|
struct vertex {
|
|
float x, y, z;
|
|
operator const float*() const { return &x; }
|
|
};
|
|
struct texture_coordinate {
|
|
float u, v;
|
|
operator const float*() const { return &u; }
|
|
};
|
|
|
|
class points : public frame
|
|
{
|
|
public:
|
|
/**
|
|
* Extends the frame class with additional point cloud related attributes and functions
|
|
*/
|
|
points() : frame(), _size(0) {}
|
|
|
|
/**
|
|
* Extends the frame class with additional point cloud related attributes and functions
|
|
* \param[in] frame - existing frame instance
|
|
*/
|
|
points(const frame& f)
|
|
: frame(f), _size(0)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (!f || (rs2_is_frame_extendable_to(f.get(), RS2_EXTENSION_POINTS, &e) == 0 && !e))
|
|
{
|
|
reset();
|
|
}
|
|
error::handle(e);
|
|
|
|
if (get())
|
|
{
|
|
_size = rs2_get_frame_points_count(get(), &e);
|
|
error::handle(e);
|
|
}
|
|
}
|
|
/**
|
|
* Retrieve the vertices of the point cloud
|
|
* \param[in] vertex* - pointer of vertex sturcture
|
|
*/
|
|
const vertex* get_vertices() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto res = rs2_get_frame_vertices(get(), &e);
|
|
error::handle(e);
|
|
return (const vertex*)res;
|
|
}
|
|
|
|
/**
|
|
* Export the point cloud to a PLY file
|
|
* \param[in] string fname - file name of the PLY to be saved
|
|
* \param[in] video_frame texture - the texture for the PLY.
|
|
*/
|
|
void export_to_ply(const std::string& fname, video_frame texture)
|
|
{
|
|
rs2_frame* ptr = nullptr;
|
|
std::swap(texture.frame_ref, ptr);
|
|
rs2_error* e = nullptr;
|
|
rs2_export_to_ply(get(), fname.c_str(), ptr, &e);
|
|
error::handle(e);
|
|
}
|
|
/**
|
|
* Retrieve the texture coordinates (uv map) for the point cloud
|
|
* \return texture_coordinate* - pointer of texture coordinates.
|
|
*/
|
|
const texture_coordinate* get_texture_coordinates() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto res = rs2_get_frame_texture_coordinates(get(), &e);
|
|
error::handle(e);
|
|
return (const texture_coordinate*)res;
|
|
}
|
|
|
|
size_t size() const
|
|
{
|
|
return _size;
|
|
}
|
|
|
|
private:
|
|
size_t _size;
|
|
};
|
|
|
|
class depth_frame : public video_frame
|
|
{
|
|
public:
|
|
/**
|
|
* Extends the video_frame class with additional depth related attributes and functions
|
|
* \param[in] frame - existing frame instance
|
|
*/
|
|
depth_frame(const frame& f)
|
|
: video_frame(f)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (!f || (rs2_is_frame_extendable_to(f.get(), RS2_EXTENSION_DEPTH_FRAME, &e) == 0 && !e))
|
|
{
|
|
reset();
|
|
}
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Provide the depth in meters at the given pixel
|
|
* \param[in] int x - pixel's x coordinate.
|
|
* \param[in] int y - pixel's y coordinate.
|
|
* \return float - depth in metric units at given pixel
|
|
*/
|
|
float get_distance(int x, int y) const
|
|
{
|
|
rs2_error * e = nullptr;
|
|
auto r = rs2_depth_frame_get_distance(get(), x, y, &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* Provide the scaling factor to use when converting from get_data() units to meters
|
|
* \return float - depth, in meters, per 1 unit stored in the frame data
|
|
*/
|
|
float get_units() const
|
|
{
|
|
rs2_error * e = nullptr;
|
|
auto r = rs2_depth_frame_get_units( get(), &e );
|
|
error::handle( e );
|
|
return r;
|
|
}
|
|
};
|
|
|
|
class disparity_frame : public depth_frame
|
|
{
|
|
public:
|
|
/**
|
|
* Extend depth_frame class with additional disparity related attributes/functions
|
|
* \param[in] frame - existing frame instance
|
|
*/
|
|
disparity_frame(const frame& f)
|
|
: depth_frame(f)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (!f || (rs2_is_frame_extendable_to(f.get(), RS2_EXTENSION_DISPARITY_FRAME, &e) == 0 && !e))
|
|
{
|
|
reset();
|
|
}
|
|
error::handle(e);
|
|
}
|
|
/**
|
|
* Retrieve the distance between the two IR sensors.
|
|
* \return float - baseline.
|
|
*/
|
|
float get_baseline(void) const
|
|
{
|
|
rs2_error * e = nullptr;
|
|
auto r = rs2_depth_stereo_frame_get_baseline(get(), &e);
|
|
error::handle(e);
|
|
return r;
|
|
}
|
|
};
|
|
|
|
class motion_frame : public frame
|
|
{
|
|
public:
|
|
/**
|
|
* Extends the frame class with additional motion related attributes and functions
|
|
* \param[in] frame - existing frame instance
|
|
*/
|
|
motion_frame(const frame& f)
|
|
: frame(f)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (!f || (rs2_is_frame_extendable_to(f.get(), RS2_EXTENSION_MOTION_FRAME, &e) == 0 && !e))
|
|
{
|
|
reset();
|
|
}
|
|
error::handle(e);
|
|
}
|
|
/**
|
|
* Retrieve the motion data from IMU sensor
|
|
* \return rs2_vector - 3D vector in Euclidean coordinate space.
|
|
*/
|
|
rs2_vector get_motion_data() const
|
|
{
|
|
auto data = reinterpret_cast<const float*>(get_data());
|
|
return rs2_vector{ data[0], data[1], data[2] };
|
|
}
|
|
};
|
|
|
|
class pose_frame : public frame
|
|
{
|
|
public:
|
|
/**
|
|
* Extends the frame class with additional pose related attributes and functions
|
|
* \param[in] frame - existing frame instance
|
|
*/
|
|
pose_frame(const frame& f)
|
|
: frame(f)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (!f || (rs2_is_frame_extendable_to(f.get(), RS2_EXTENSION_POSE_FRAME, &e) == 0 && !e))
|
|
{
|
|
reset();
|
|
}
|
|
error::handle(e);
|
|
}
|
|
/**
|
|
* Retrieve the pose data from T2xx position tracking sensor
|
|
* \return rs2_pose - orientation and velocity data.
|
|
*/
|
|
rs2_pose get_pose_data() const
|
|
{
|
|
rs2_pose pose_data;
|
|
rs2_error* e = nullptr;
|
|
rs2_pose_frame_get_pose_data(get(), &pose_data, &e);
|
|
error::handle(e);
|
|
return pose_data;
|
|
}
|
|
};
|
|
|
|
class frameset : public frame
|
|
{
|
|
public:
|
|
/**
|
|
* Extends the frame class with additional frameset related attributes and functions
|
|
*/
|
|
frameset() :_size(0) {};
|
|
/**
|
|
* Extends the frame class with additional frameset related attributes and functions
|
|
* \param[in] frame - existing frame instance
|
|
*/
|
|
frameset(const frame& f)
|
|
: frame(f), _size(0)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (!f || (rs2_is_frame_extendable_to(f.get(), RS2_EXTENSION_COMPOSITE_FRAME, &e) == 0 && !e))
|
|
{
|
|
reset();
|
|
// TODO - consider explicit constructor to move resultion to compile time
|
|
}
|
|
error::handle(e);
|
|
|
|
if (get())
|
|
{
|
|
_size = rs2_embedded_frames_count(get(), &e);
|
|
error::handle(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retrieve the first frame of a specific stream and optionally with a specific format. If no frame is found, return an empty frame instance.
|
|
* \param[in] rs2_stream s - frame to be retrieved from this stream type.
|
|
* \param[in] rs2_format f - frame to be retrieved from this format type.
|
|
* \return frame - first found frame with s stream type.
|
|
*/
|
|
frame first_or_default(rs2_stream s, rs2_format f = RS2_FORMAT_ANY) const
|
|
{
|
|
frame result;
|
|
foreach_rs([&result, s, f](frame frm) {
|
|
if (!result && frm.get_profile().stream_type() == s && (f == RS2_FORMAT_ANY || f == frm.get_profile().format()))
|
|
{
|
|
result = std::move(frm);
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
/**
|
|
* Retrieve the first frame of a specific stream type and optionally with a specific format. If no frame is found, an error will be thrown.
|
|
* \param[in] rs2_stream s - frame to be retrieved from this stream type.
|
|
* \param[in] rs2_format f - frame to be retrieved from this format type.
|
|
* \return frame - first found frame with s stream type.
|
|
*/
|
|
frame first(rs2_stream s, rs2_format f = RS2_FORMAT_ANY) const
|
|
{
|
|
auto frm = first_or_default(s, f);
|
|
if (!frm) throw error("Frame of requested stream type was not found!");
|
|
return frm;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the first depth frame, if no frame is found, return an empty frame instance.
|
|
* \return depth_frame - first found depth frame.
|
|
*/
|
|
depth_frame get_depth_frame() const
|
|
{
|
|
auto f = first_or_default(RS2_STREAM_DEPTH, RS2_FORMAT_Z16);
|
|
return f.as<depth_frame>();
|
|
}
|
|
/**
|
|
* Retrieve the first color frame, if no frame is found, search for the color frame from IR stream. If one still can't be found, return an empty frame instance.
|
|
* \return video_frame - first found color frame.
|
|
*/
|
|
video_frame get_color_frame() const
|
|
{
|
|
auto f = first_or_default(RS2_STREAM_COLOR);
|
|
|
|
if (!f)
|
|
{
|
|
auto ir = first_or_default(RS2_STREAM_INFRARED);
|
|
if (ir && ir.get_profile().format() == RS2_FORMAT_RGB8)
|
|
f = ir;
|
|
}
|
|
return f;
|
|
}
|
|
/**
|
|
* Retrieve the first infrared frame, if no frame is found, return an empty frame instance.
|
|
* \param[in] size_t index
|
|
* \return video_frame - first found infrared frame.
|
|
*/
|
|
video_frame get_infrared_frame(const size_t index = 0) const
|
|
{
|
|
frame f;
|
|
if (!index)
|
|
{
|
|
f = first_or_default(RS2_STREAM_INFRARED);
|
|
}
|
|
else
|
|
{
|
|
foreach_rs([&f, index](const frame& frm) {
|
|
if (frm.get_profile().stream_type() == RS2_STREAM_INFRARED &&
|
|
frm.get_profile().stream_index() == index) f = frm;
|
|
});
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the fisheye monochrome video frame
|
|
* \param[in] size_t index
|
|
* \return video_frame - the fisheye frame denoted by index.
|
|
*/
|
|
video_frame get_fisheye_frame(const size_t index = 0) const
|
|
{
|
|
frame f;
|
|
if (!index)
|
|
{
|
|
f = first_or_default(RS2_STREAM_FISHEYE);
|
|
}
|
|
else
|
|
{
|
|
foreach_rs([&f, index](const frame& frm) {
|
|
if (frm.get_profile().stream_type() == RS2_STREAM_FISHEYE &&
|
|
frm.get_profile().stream_index() == index) f = frm;
|
|
});
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/**
|
|
* Retrieve the pose frame
|
|
* \param[in] size_t index
|
|
* \return pose_frame - the sensor's positional data
|
|
*/
|
|
pose_frame get_pose_frame(const size_t index = 0) const
|
|
{
|
|
frame f;
|
|
if (!index)
|
|
{
|
|
f = first_or_default(RS2_STREAM_POSE);
|
|
}
|
|
else
|
|
{
|
|
foreach_rs([&f, index](const frame& frm) {
|
|
if (frm.get_profile().stream_type() == RS2_STREAM_POSE &&
|
|
frm.get_profile().stream_index() == index) f = frm;
|
|
});
|
|
}
|
|
return f.as<pose_frame>();
|
|
}
|
|
|
|
/**
|
|
* Return the size of the frameset
|
|
* \return size_t - frameset size.
|
|
*/
|
|
size_t size() const
|
|
{
|
|
return _size;
|
|
}
|
|
|
|
/**
|
|
* Template function, extract internal frame handles from the frameset and invoke the action function
|
|
* \param[in] action - instance with () operator implemented will be invoke after frame extraction.
|
|
*/
|
|
template<class T>
|
|
void foreach_rs(T action) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
auto count = size();
|
|
for (size_t i = 0; i < count; i++)
|
|
{
|
|
auto fref = rs2_extract_frame(get(), (int)i, &e);
|
|
error::handle(e);
|
|
|
|
action(frame(fref));
|
|
}
|
|
}
|
|
/**
|
|
* Bracket operator retrieves back the frame from frameset using arrary notation
|
|
* \param[in] index - index of array to retrieve data back.
|
|
* \return frame - retrieved frame.
|
|
*/
|
|
frame operator[](size_t index) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (index < size())
|
|
{
|
|
auto fref = rs2_extract_frame(get(), (int)index, &e);
|
|
error::handle(e);
|
|
return frame(fref);
|
|
}
|
|
|
|
throw error("Requested index is out of range!");
|
|
}
|
|
|
|
class iterator
|
|
{
|
|
public:
|
|
// inheriting from std::iterator template is deprecated in C++17, this is the new way to define an iterator
|
|
// go to https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/ for more info
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using value_type = frame;
|
|
using difference_type = std::ptrdiff_t;
|
|
using pointer = frame*;
|
|
using reference = frame&;
|
|
|
|
iterator(const frameset* owner, size_t index = 0) : _index(index), _owner(owner) {}
|
|
iterator& operator++() { ++_index; return *this; }
|
|
bool operator==(const iterator& other) const { return _index == other._index; }
|
|
bool operator!=(const iterator& other) const { return !(*this == other); }
|
|
|
|
frame operator*() { return (*_owner)[_index]; }
|
|
private:
|
|
size_t _index = 0;
|
|
const frameset* _owner;
|
|
};
|
|
|
|
iterator begin() const { return iterator(this); }
|
|
iterator end() const { return iterator(this, size()); }
|
|
private:
|
|
size_t _size;
|
|
};
|
|
|
|
template<class T>
|
|
class frame_callback : public rs2_frame_callback
|
|
{
|
|
T on_frame_function;
|
|
public:
|
|
explicit frame_callback(T on_frame) : on_frame_function(on_frame) {}
|
|
|
|
void on_frame(rs2_frame* fref) override
|
|
{
|
|
on_frame_function(frame{ fref });
|
|
}
|
|
|
|
void release() override { delete this; }
|
|
};
|
|
}
|
|
#endif // LIBREALSENSE_RS2_FRAME_HPP
|