/** \file record.hpp * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. * Kinect For Azure SDK - C++ wrapper. */ #ifndef K4A_RECORD_HPP #define K4A_RECORD_HPP #include #include namespace k4a { /** \class record record.hpp * Wrapper for \ref k4a_record_t * * Wraps a handle for a record object * * \sa k4a_record_t */ class record { public: /** Creates a k4a::record from a k4a_record_t * Takes ownership of the handle, i.e. you should not call * k4a_record_close on the handle after giving it to the * k4a::record; the k4a::record will take care of that. */ record(k4a_record_t handle = nullptr) noexcept : m_handle(handle) {} /** Moves another k4a::record into a new k4a::record */ record(record &&other) noexcept : m_handle(other.m_handle) { other.m_handle = nullptr; } record(const record &) = delete; ~record() { // NOTE: flush is called internally when closing record close(); } record &operator=(const record &) = delete; /** Moves another k4a::record into this k4a::record; other is set to invalid */ record &operator=(record &&other) noexcept { if (this != &other) { close(); m_handle = other.m_handle; other.m_handle = nullptr; } return *this; } /** Returns true if the k4a::record is valid, false otherwise */ explicit operator bool() const noexcept { return is_valid(); } /** Returns true if the k4a::record is valid, false otherwise */ bool is_valid() const noexcept { return m_handle != nullptr; } /** Closes a K4A recording. * * \sa k4a_record_close */ void close() noexcept { if (is_valid()) { k4a_record_close(m_handle); m_handle = nullptr; } } /** Flushes all pending recording data to disk * * \sa k4a_record_flush */ void flush() { if (m_handle) { k4a_result_t result = k4a_record_flush(m_handle); if (K4A_FAILED(result)) { throw error("Failed to flush!"); } } } /** Adds a tag to the recording * Throws error on failure * * \sa k4a_record_add_tag */ void add_tag(const char *name, const char *value) { k4a_result_t result = k4a_record_add_tag(m_handle, name, value); if (K4A_FAILED(result)) { throw error("Failed to add tag!"); } } /** Adds the track header for recording IMU * Throws error on failure * * \sa k4a_record_add_imu_track */ void add_imu_track() { k4a_result_t result = k4a_record_add_imu_track(m_handle); if (K4A_FAILED(result)) { throw error("Failed to add imu_track!"); } } /** Adds an attachment to the recording * Throws error on failure * * \sa k4a_record_add_attachment */ void add_attachment(const char *attachment_name, const uint8_t *buffer, size_t buffer_size) { k4a_result_t result = k4a_record_add_attachment(m_handle, attachment_name, buffer, buffer_size); if (K4A_FAILED(result)) { throw error("Failed to add attachment!"); } } /** Adds custom video tracks to the recording * Throws error on failure * * \sa k4a_record_add_custom_video_track */ void add_custom_video_track(const char *track_name, const char *codec_id, const uint8_t *codec_context, size_t codec_context_size, const k4a_record_video_settings_t *track_settings) { k4a_result_t result = k4a_record_add_custom_video_track(m_handle, track_name, codec_id, codec_context, codec_context_size, track_settings); if (K4A_FAILED(result)) { throw error("Failed to add custom video track!"); } } /** Adds custom subtitle tracks to the recording * Throws error on failure * * \sa k4a_record_add_custom_subtitle_track */ void add_custom_subtitle_track(const char *track_name, const char *codec_id, const uint8_t *codec_context, size_t codec_context_size, const k4a_record_subtitle_settings_t *track_settings) { k4a_result_t result = k4a_record_add_custom_subtitle_track(m_handle, track_name, codec_id, codec_context, codec_context_size, track_settings); if (K4A_FAILED(result)) { throw error("Failed to add custom subtitle track!"); } } /** Writes the recording header and metadata to file * Throws error on failure * * \sa k4a_record_write_header */ void write_header() { k4a_result_t result = k4a_record_write_header(m_handle); if (K4A_FAILED(result)) { throw error("Failed to write header!"); } } /** Writes a camera capture to file * Throws error on failure * * \sa k4a_record_write_capture */ void write_capture(const capture &capture) { k4a_result_t result = k4a_record_write_capture(m_handle, capture.handle()); if (K4A_FAILED(result)) { throw error("Failed to write capture!"); } } /** Writes an imu sample to file * Throws error on failure * * \sa k4a_record_write_imu_sample */ void write_imu_sample(const k4a_imu_sample_t &imu_sample) { k4a_result_t result = k4a_record_write_imu_sample(m_handle, imu_sample); if (K4A_FAILED(result)) { throw error("Failed to write imu sample!"); } } /** Writes data for a custom track to file * Throws error on failure * * \sa k4a_record_write_custom_track_data */ void write_custom_track_data(const char *track_name, const std::chrono::microseconds device_timestamp_usec, uint8_t *custom_data, size_t custom_data_size) { k4a_result_t result = k4a_record_write_custom_track_data(m_handle, track_name, internal::clamp_cast( device_timestamp_usec.count()), custom_data, custom_data_size); if (K4A_FAILED(result)) { throw error("Failed to write custom track data!"); } } /** Opens a new recording file for writing * Throws error on failure * * \sa k4a_record_create */ static record create(const char *path, const device &device, const k4a_device_configuration_t &device_configuration) { k4a_record_t handle = nullptr; k4a_result_t result = k4a_record_create(path, device.handle(), device_configuration, &handle); if (K4A_FAILED(result)) { throw error("Failed to create recorder!"); } return record(handle); } private: k4a_record_t m_handle; }; } // namespace k4a #endif