diff --git a/CMake/realsense.def b/CMake/realsense.def index 6bd22933dd..6a95e4b9a0 100644 --- a/CMake/realsense.def +++ b/CMake/realsense.def @@ -233,6 +233,7 @@ EXPORTS rs2_config_enable_all_stream rs2_config_enable_device rs2_config_enable_device_from_file + rs2_config_enable_device_from_file_repeat_option rs2_config_enable_record_to_file rs2_config_disable_stream rs2_config_disable_indexed_stream diff --git a/include/librealsense2/h/rs_pipeline.h b/include/librealsense2/h/rs_pipeline.h index 7cd56c9101..7569d0f5b7 100644 --- a/include/librealsense2/h/rs_pipeline.h +++ b/include/librealsense2/h/rs_pipeline.h @@ -236,6 +236,7 @@ extern "C" { * The device available streams are as recorded to the file, and \c resolve() considers only this device and configuration * as available. * This request cannot be used if enable_record_to_file() is called for the current config, and vise versa + * By default, playback is repeated once the file ends. To control this, see 'rs2_config_enable_device_from_file_repeat_option'. * * \param[in] config A pointer to an instance of a config * \param[in] file_name The playback file of the device @@ -243,6 +244,20 @@ extern "C" { */ void rs2_config_enable_device_from_file(rs2_config* config, const char* file, rs2_error ** error); + /** + * Select a recorded device from a file, to be used by the pipeline through playback. + * The device available streams are as recorded to the file, and \c resolve() considers only this device and configuration + * as available. + * This request cannot be used if enable_record_to_file() is called for the current config, and vise versa + * + * \param[in] config A pointer to an instance of a config + * \param[in] file_name The playback file of the device + * \param[in] repeat_playback if true, when file ends the playback starts again, in an infinite loop; + if false, when file ends playback does not start again, and should by stopped manually by the user. + * \param[out] error if non-null, receives any error that occurs during this call, otherwise, errors are ignored + */ + void rs2_config_enable_device_from_file_repeat_option(rs2_config* config, const char* file, int repeat_playback, rs2_error ** error); + /** * Requires that the resolved device would be recorded to file * This request cannot be used if enable_device_from_file() is called for the current config, and vise versa diff --git a/include/librealsense2/hpp/rs_pipeline.hpp b/include/librealsense2/hpp/rs_pipeline.hpp index 6ac4223945..9a10f6a9a6 100644 --- a/include/librealsense2/hpp/rs_pipeline.hpp +++ b/include/librealsense2/hpp/rs_pipeline.hpp @@ -221,10 +221,10 @@ namespace rs2 * * \param[in] file_name The playback file of the device */ - void enable_device_from_file(const std::string& file_name) + void enable_device_from_file(const std::string& file_name, bool repeat_playback = true) { rs2_error* e = nullptr; - rs2_config_enable_device_from_file(_config.get(), file_name.c_str(), &e); + rs2_config_enable_device_from_file_repeat_option(_config.get(), file_name.c_str(), repeat_playback, &e); error::handle(e); } diff --git a/src/pipeline.cpp b/src/pipeline.cpp index bc7b849f94..f9511c8342 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -109,7 +109,7 @@ namespace librealsense _device_request.serial = serial; } - void pipeline_config::enable_device_from_file(const std::string& file) + void pipeline_config::enable_device_from_file(const std::string& file, bool repeat_playback = true) { std::lock_guard lock(_mtx); if (!_device_request.record_output.empty()) @@ -118,6 +118,7 @@ namespace librealsense } _resolved_profile.reset(); _device_request.filename = file; + _playback_loop = repeat_playback; } void pipeline_config::enable_record_to_file(const std::string& file) @@ -379,6 +380,10 @@ namespace librealsense return default_profiles; } + bool pipeline_config::get_repeat_playback() { + return _playback_loop; + } + /* .______ __ .______ _______ __ __ .__ __. _______ | _ \ | | | _ \ | ____|| | | | | \ | | | ____| @@ -510,7 +515,7 @@ namespace librealsense { //If the pipeline holds a playback device, and it reached the end of file (stopped) //Then we restart it - if (_active_profile) + if (_active_profile && _prev_conf->get_repeat_playback()) { _active_profile->_multistream.open(); _active_profile->_multistream.start(syncer_callback); diff --git a/src/pipeline.h b/src/pipeline.h index dcceed37dc..cfb3abd5e3 100644 --- a/src/pipeline.h +++ b/src/pipeline.h @@ -83,12 +83,13 @@ namespace librealsense void enable_stream(rs2_stream stream, int index, int width, int height, rs2_format format, int framerate); void enable_all_stream(); void enable_device(const std::string& serial); - void enable_device_from_file(const std::string& file); + void enable_device_from_file(const std::string& file, bool repeat_playback); void enable_record_to_file(const std::string& file); void disable_stream(rs2_stream stream, int index = -1); void disable_all_streams(); std::shared_ptr resolve(std::shared_ptr pipe, const std::chrono::milliseconds& timeout = std::chrono::milliseconds(0)); bool can_resolve(std::shared_ptr pipe); + bool get_repeat_playback(); //Non top level API std::shared_ptr get_cached_resolved_profile(); @@ -103,6 +104,7 @@ namespace librealsense _enable_all_streams = other._enable_all_streams; _stream_requests = other._stream_requests; _resolved_profile = nullptr; + _playback_loop = other._playback_loop; } private: struct device_request @@ -120,6 +122,7 @@ namespace librealsense std::mutex _mtx; bool _enable_all_streams = false; std::shared_ptr _resolved_profile; + bool _playback_loop; }; } diff --git a/src/rs.cpp b/src/rs.cpp index ce643ddabb..e88283d593 100644 --- a/src/rs.cpp +++ b/src/rs.cpp @@ -1471,12 +1471,21 @@ void rs2_config_enable_device(rs2_config* config, const char* serial, rs2_error } HANDLE_EXCEPTIONS_AND_RETURN(, config, serial) +void rs2_config_enable_device_from_file_repeat_option(rs2_config* config, const char* file, int repeat_playback, rs2_error ** error) BEGIN_API_CALL +{ + VALIDATE_NOT_NULL(config); + VALIDATE_NOT_NULL(file); + + config->config->enable_device_from_file(file, repeat_playback); +} +HANDLE_EXCEPTIONS_AND_RETURN(, config, file) + void rs2_config_enable_device_from_file(rs2_config* config, const char* file, rs2_error ** error) BEGIN_API_CALL { VALIDATE_NOT_NULL(config); VALIDATE_NOT_NULL(file); - config->config->enable_device_from_file(file); + config->config->enable_device_from_file(file, true); } HANDLE_EXCEPTIONS_AND_RETURN(, config, file) diff --git a/wrappers/python/python.cpp b/wrappers/python/python.cpp index 89c3ddad45..2bef9eed43 100644 --- a/wrappers/python/python.cpp +++ b/wrappers/python/python.cpp @@ -689,7 +689,7 @@ PYBIND11_MODULE(NAME, m) { .def("enable_stream", (void (rs2::config::*)(rs2_stream, int, rs2_format, int)) &rs2::config::enable_stream, "stream_type"_a, "stream_index"_a, "format"_a, "framerate"_a = 0) .def("enable_all_streams", &rs2::config::enable_all_streams) .def("enable_device", &rs2::config::enable_device, "serial"_a) - .def("enable_device_from_file", &rs2::config::enable_device_from_file, "file_name"_a) + .def("enable_device_from_file", &rs2::config::enable_device_from_file, "file_name"_a, "repeat_playback"_a = true) .def("enable_record_to_file", &rs2::config::enable_record_to_file, "file_name"_a) .def("disable_stream", &rs2::config::disable_stream, "stream"_a, "index"_a = -1) .def("disable_all_streams", &rs2::config::disable_all_streams)