282 lines
9.6 KiB
C++
282 lines
9.6 KiB
C++
// License: Apache 2.0. See LICENSE file in root directory.
|
|
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.
|
|
|
|
#ifndef LIBREALSENSE_RS2_RECORD_PLAYBACK_HPP
|
|
#define LIBREALSENSE_RS2_RECORD_PLAYBACK_HPP
|
|
|
|
#include "rs_types.hpp"
|
|
#include "rs_device.hpp"
|
|
|
|
namespace rs2
|
|
{
|
|
template<class T>
|
|
class status_changed_callback : public rs2_playback_status_changed_callback
|
|
{
|
|
T on_status_changed_function;
|
|
public:
|
|
explicit status_changed_callback(T on_status_changed) : on_status_changed_function(on_status_changed) {}
|
|
|
|
void on_playback_status_changed(rs2_playback_status status) override
|
|
{
|
|
on_status_changed_function(status);
|
|
}
|
|
|
|
void release() override { delete this; }
|
|
};
|
|
|
|
class playback : public device
|
|
{
|
|
public:
|
|
playback(device d) : playback(d.get()) {}
|
|
|
|
/**
|
|
* Pauses the playback
|
|
* Calling pause() in "Paused" status does nothing
|
|
* If pause() is called while playback status is "Playing" or "Stopped", the playback will not play until resume() is called
|
|
*/
|
|
void pause()
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_device_pause(_dev.get(), &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Un-pauses the playback
|
|
* Calling resume() while playback status is "Playing" or "Stopped" does nothing
|
|
*/
|
|
void resume()
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_device_resume(_dev.get(), &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Retrieves the name of the playback file
|
|
* \return Name of the playback file
|
|
*/
|
|
std::string file_name() const
|
|
{
|
|
return m_file; //cached in construction
|
|
}
|
|
|
|
/**
|
|
* Retrieves the current position of the playback in the file in terms of time. Units are expressed in nanoseconds
|
|
* \return Current position of the playback in the file in terms of time. Units are expressed in nanoseconds
|
|
*/
|
|
uint64_t get_position() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
uint64_t pos = rs2_playback_get_position(_dev.get(), &e);
|
|
error::handle(e);
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the total duration of the file
|
|
* \return Total duration of the file
|
|
*/
|
|
std::chrono::nanoseconds get_duration() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
std::chrono::nanoseconds duration(rs2_playback_get_duration(_dev.get(), &e));
|
|
error::handle(e);
|
|
return duration;
|
|
}
|
|
|
|
/**
|
|
* Sets the playback to a specified time point of the played data
|
|
* \param[in] time The time point to which playback should seek, expressed in units of nanoseconds (zero value = start)
|
|
*/
|
|
void seek(std::chrono::nanoseconds time)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_seek(_dev.get(), time.count(), &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Indicates if playback is in real time mode or non real time
|
|
* \return True iff playback is in real time mode
|
|
*/
|
|
bool is_real_time() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
bool real_time = rs2_playback_device_is_real_time(_dev.get(), &e) != 0;
|
|
error::handle(e);
|
|
return real_time;
|
|
}
|
|
|
|
/**
|
|
* Set the playback to work in real time or non real time
|
|
*
|
|
* In real time mode, playback will play the same way the file was recorded.
|
|
* In real time mode if the application takes too long to handle the callback, frames may be dropped.
|
|
* In non real time mode, playback will wait for each callback to finish handling the data before
|
|
* reading the next frame. In this mode no frames will be dropped, and the application controls the
|
|
* frame rate of the playback (according to the callback handler duration).
|
|
* \param[in] real_time Indicates if real time is requested, 0 means false, otherwise true
|
|
* \return True on successfully setting the requested mode
|
|
*/
|
|
void set_real_time(bool real_time) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_device_set_real_time(_dev.get(), (real_time ? 1 : 0), &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Set the playing speed
|
|
* \param[in] speed Indicates a multiplication of the speed to play (e.g: 1 = normal, 0.5 twice as slow)
|
|
*/
|
|
void set_playback_speed(float speed) const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_device_set_playback_speed(_dev.get(), speed, &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Start passing frames into user provided callback
|
|
* \param[in] callback Stream callback, can be any callable object accepting rs2::frame
|
|
*/
|
|
|
|
/**
|
|
* Register to receive callback from playback device upon its status changes
|
|
*
|
|
* Callbacks are invoked from the reading thread, and as such any heavy processing in the callback handler will affect
|
|
* the reading thread and may cause frame drops\ high latency
|
|
* \param[in] callback A callback handler that will be invoked when the playback status changes, can be any callable object accepting rs2_playback_status
|
|
*/
|
|
template <typename T>
|
|
void set_status_changed_callback(T callback)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_device_set_status_changed_callback(_dev.get(), new status_changed_callback<T>(std::move(callback)), &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Returns the current state of the playback device
|
|
* \return Current state of the playback
|
|
*/
|
|
rs2_playback_status current_status() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_status sts = rs2_playback_device_get_current_status(_dev.get(), &e);
|
|
error::handle(e);
|
|
return sts;
|
|
}
|
|
|
|
/**
|
|
* Stops the playback, effectively stopping all streaming playback sensors, and resetting the playback.
|
|
*
|
|
*/
|
|
void stop()
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_playback_device_stop(_dev.get(), &e);
|
|
error::handle(e);
|
|
}
|
|
protected:
|
|
friend context;
|
|
explicit playback(std::shared_ptr<rs2_device> dev) : device(dev)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if(rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_PLAYBACK, &e) == 0 && !e)
|
|
{
|
|
_dev.reset();
|
|
}
|
|
error::handle(e);
|
|
|
|
if(_dev)
|
|
{
|
|
e = nullptr;
|
|
m_file = rs2_playback_device_get_file_path(_dev.get(), &e);
|
|
error::handle(e);
|
|
}
|
|
}
|
|
private:
|
|
std::string m_file;
|
|
};
|
|
class recorder : public device
|
|
{
|
|
public:
|
|
recorder(device d) : recorder(d.get()) {}
|
|
|
|
/**
|
|
* Creates a recording device to record the given device and save it to the given file as rosbag format
|
|
* \param[in] file The desired path to which the recorder should save the data
|
|
* \param[in] device The device to record
|
|
*/
|
|
recorder(const std::string& file, rs2::device dev)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
_dev = std::shared_ptr<rs2_device>(
|
|
rs2_create_record_device(dev.get().get(), file.c_str(), &e),
|
|
rs2_delete_device);
|
|
rs2::error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Creates a recording device to record the given device and save it to the given file as rosbag format
|
|
* \param[in] file The desired path to which the recorder should save the data
|
|
* \param[in] device The device to record
|
|
* \param[in] compression_enabled Indicates if compression is enabled
|
|
*/
|
|
recorder(const std::string& file, rs2::device dev, bool compression_enabled)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
_dev = std::shared_ptr<rs2_device>(
|
|
rs2_create_record_device_ex(dev.get().get(), file.c_str(), compression_enabled, &e),
|
|
rs2_delete_device);
|
|
rs2::error::handle(e);
|
|
}
|
|
|
|
|
|
/**
|
|
* Pause the recording device without stopping the actual device from streaming.
|
|
*/
|
|
void pause()
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_record_device_pause(_dev.get(), &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Unpauses the recording device, making it resume recording.
|
|
*/
|
|
void resume()
|
|
{
|
|
rs2_error* e = nullptr;
|
|
rs2_record_device_resume(_dev.get(), &e);
|
|
error::handle(e);
|
|
}
|
|
|
|
/**
|
|
* Gets the name of the file to which the recorder is writing
|
|
* \return The name of the file to which the recorder is writing
|
|
*/
|
|
std::string filename() const
|
|
{
|
|
rs2_error* e = nullptr;
|
|
std::string filename = rs2_record_device_filename(_dev.get(), &e);
|
|
error::handle(e);
|
|
return filename;
|
|
}
|
|
protected:
|
|
explicit recorder(std::shared_ptr<rs2_device> dev) : device(dev)
|
|
{
|
|
rs2_error* e = nullptr;
|
|
if (rs2_is_device_extendable_to(_dev.get(), RS2_EXTENSION_RECORD, &e) == 0 && !e)
|
|
{
|
|
_dev.reset();
|
|
}
|
|
error::handle(e);
|
|
}
|
|
};
|
|
}
|
|
#endif // LIBREALSENSE_RS2_RECORD_PLAYBACK_HPP
|