Convert all playback timestamps to use device time (#592)
* Convert all playback timestamps to use device time * Add some extra documentation comments around seek_timestamp * Rename last_timestamp_ns field to last_file_timestamp_ns
This commit is contained in:
Родитель
0f82028001
Коммит
3b299f14bd
|
@ -51,8 +51,7 @@ static void print_capture_info(recording_t *file)
|
|||
{
|
||||
if (images[i] != NULL)
|
||||
{
|
||||
uint64_t timestamp = k4a_image_get_device_timestamp_usec(images[i]) +
|
||||
(uint64_t)file->record_config.start_timestamp_offset_usec;
|
||||
uint64_t timestamp = k4a_image_get_device_timestamp_usec(images[i]);
|
||||
printf(" %7ju usec", timestamp);
|
||||
k4a_image_release(images[i]);
|
||||
images[i] = NULL;
|
||||
|
@ -162,11 +161,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
if (files[i].capture != NULL)
|
||||
{
|
||||
// All recording files start at timestamp 0, however the first timestamp off the camera is usually
|
||||
// non-zero. We need to add the recording "start offset" back to the recording timestamp to recover
|
||||
// the original timestamp from the device, and synchronize the files.
|
||||
uint64_t timestamp = first_capture_timestamp(files[i].capture) +
|
||||
files[i].record_config.start_timestamp_offset_usec;
|
||||
uint64_t timestamp = first_capture_timestamp(files[i].capture);
|
||||
if (timestamp < min_timestamp)
|
||||
{
|
||||
min_timestamp = timestamp;
|
||||
|
|
|
@ -273,7 +273,7 @@ static int playback(char *input_path, int timestamp = 1000, std::string output_f
|
|||
}
|
||||
printf("Seeking to timestamp: %d/%d (ms)\n",
|
||||
timestamp,
|
||||
(int)(k4a_playback_get_last_timestamp_usec(playback) / 1000));
|
||||
(int)(k4a_playback_get_recording_length_usec(playback) / 1000));
|
||||
|
||||
stream_result = k4a_playback_get_next_capture(playback, &capture);
|
||||
if (stream_result != K4A_STREAM_RESULT_SUCCEEDED || capture == NULL)
|
||||
|
|
|
@ -121,7 +121,7 @@ typedef struct _k4a_playback_context_t
|
|||
uint64_t attachments_offset;
|
||||
uint64_t tags_offset;
|
||||
|
||||
uint64_t last_timestamp_ns;
|
||||
uint64_t last_file_timestamp_ns; // Relative to start of file.
|
||||
|
||||
// Stats
|
||||
uint64_t seek_count, load_count, cache_hits;
|
||||
|
|
|
@ -376,10 +376,11 @@ K4ARECORD_EXPORT k4a_stream_result_t k4a_playback_get_previous_imu_sample(k4a_pl
|
|||
* Handle obtained by k4a_playback_open().
|
||||
*
|
||||
* \param offset_usec
|
||||
* The timestamp offset to seek to relative to \p origin
|
||||
* The timestamp offset to seek to, relative to \p origin
|
||||
*
|
||||
* \param origin
|
||||
* Specifies if the seek operation should be done relative to the beginning or end of the recording.
|
||||
* Specifies how the given timestamp should be interpreted. Seek can be done relative to the beginning or end of the
|
||||
* recording, or using an absolute device timestamp.
|
||||
*
|
||||
* \returns
|
||||
* ::K4A_RESULT_SUCCEEDED if the seek operation was successful, or ::K4A_RESULT_FAILED if an error occured. The current
|
||||
|
@ -388,6 +389,10 @@ K4ARECORD_EXPORT k4a_stream_result_t k4a_playback_get_previous_imu_sample(k4a_pl
|
|||
* \relates k4a_playback_t
|
||||
*
|
||||
* \remarks
|
||||
* The first device timestamp in a recording is usually non-zero. The recording file starts at the device timestamp
|
||||
* defined by start_timestamp_offset_usec, which is accessible via k4a_playback_get_record_configuration().
|
||||
*
|
||||
* \remarks
|
||||
* The first call to k4a_playback_get_next_capture() after k4a_playback_seek_timestamp() will return the first capture
|
||||
* containing an image timestamp greater than or equal to the seek time.
|
||||
*
|
||||
|
@ -415,18 +420,19 @@ K4ARECORD_EXPORT k4a_result_t k4a_playback_seek_timestamp(k4a_playback_t playbac
|
|||
int64_t offset_usec,
|
||||
k4a_playback_seek_origin_t origin);
|
||||
|
||||
/** Gets the last timestamp in a recording.
|
||||
/** Returns the length of the recording in microseconds.
|
||||
*
|
||||
* \param playback_handle
|
||||
* Handle obtained by k4a_playback_open().
|
||||
*
|
||||
* \returns
|
||||
* The timestamp of the last capture image or IMU sample in microseconds.
|
||||
* The recording length, calculated as the difference between the first and last timestamp in the file.
|
||||
*
|
||||
* \relates k4a_playback_t
|
||||
*
|
||||
* \remarks
|
||||
* Recordings start at timestamp 0, and end at the timestamp returned by k4a_playback_get_last_timestamp_usec().
|
||||
* The recording length may be longer than an individual track if, for example, the IMU continues to run after the last
|
||||
* color image is recorded.
|
||||
*
|
||||
* \xmlonly
|
||||
* <requirements>
|
||||
|
@ -436,7 +442,34 @@ K4ARECORD_EXPORT k4a_result_t k4a_playback_seek_timestamp(k4a_playback_t playbac
|
|||
* </requirements>
|
||||
* \endxmlonly
|
||||
*/
|
||||
K4ARECORD_EXPORT uint64_t k4a_playback_get_last_timestamp_usec(k4a_playback_t playback_handle);
|
||||
K4ARECORD_EXPORT uint64_t k4a_playback_get_recording_length_usec(k4a_playback_t playback_handle);
|
||||
|
||||
/** Gets the last timestamp in a recording, relative to the start of the recording.
|
||||
*
|
||||
* \param playback_handle
|
||||
* Handle obtained by k4a_playback_open().
|
||||
*
|
||||
* \returns
|
||||
* The file timestamp of the last capture image or IMU sample in microseconds.
|
||||
*
|
||||
* \relates k4a_playback_t
|
||||
*
|
||||
* \remarks
|
||||
* This function returns a file timestamp, not an absolute device timestamp, meaning it is relative to the start of the
|
||||
* recording. This function is equivalent to the length of the recording.
|
||||
*
|
||||
* \deprecated
|
||||
* Deprecated starting in 1.2.0. Please use k4a_playback_get_recording_length_usec().
|
||||
*
|
||||
* \xmlonly
|
||||
* <requirements>
|
||||
* <requirement name="Header">playback.h (include k4arecord/playback.h)</requirement>
|
||||
* <requirement name="Library">k4arecord.lib</requirement>
|
||||
* <requirement name="DLL">k4arecord.dll</requirement>
|
||||
* </requirements>
|
||||
* \endxmlonly
|
||||
*/
|
||||
K4ARECORD_DEPRECATED_EXPORT uint64_t k4a_playback_get_last_timestamp_usec(k4a_playback_t playback_handle);
|
||||
|
||||
/** Closes a recording playback handle.
|
||||
*
|
||||
|
|
|
@ -288,11 +288,11 @@ public:
|
|||
|
||||
/** Get the last valid timestamp in the recording
|
||||
*
|
||||
* \sa k4a_playback_get_last_timestamp_usec
|
||||
* \sa k4a_playback_get_recording_length_usec
|
||||
*/
|
||||
std::chrono::microseconds get_last_timestamp() const noexcept
|
||||
std::chrono::microseconds get_recording_length() const noexcept
|
||||
{
|
||||
return std::chrono::microseconds(k4a_playback_get_last_timestamp_usec(m_handle));
|
||||
return std::chrono::microseconds(k4a_playback_get_recording_length_usec(m_handle));
|
||||
}
|
||||
|
||||
/** Set the image format that color captures will be converted to. By default the conversion format will be the same
|
||||
|
|
|
@ -80,8 +80,9 @@ typedef enum
|
|||
*/
|
||||
typedef enum
|
||||
{
|
||||
K4A_PLAYBACK_SEEK_BEGIN, /**< Seek relative to the beginning of a recording. */
|
||||
K4A_PLAYBACK_SEEK_END /**< Seek relative to the end of a recording. */
|
||||
K4A_PLAYBACK_SEEK_BEGIN, /**< Seek relative to the beginning of a recording. */
|
||||
K4A_PLAYBACK_SEEK_END, /**< Seek relative to the end of a recording. */
|
||||
K4A_PLAYBACK_SEEK_DEVICE_TIME /**< Seek to an absolute device timestamp. */
|
||||
} k4a_playback_seek_origin_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -229,7 +229,7 @@ k4a_result_t parse_mkv(k4a_playback_context_t *context)
|
|||
RETURN_IF_ERROR(populate_cluster_cache(context));
|
||||
|
||||
// Find the last timestamp in the file
|
||||
context->last_timestamp_ns = 0;
|
||||
context->last_file_timestamp_ns = 0;
|
||||
cluster_info_t *cluster_info = find_cluster(context, UINT64_MAX);
|
||||
if (cluster_info == NULL)
|
||||
{
|
||||
|
@ -251,9 +251,9 @@ k4a_result_t parse_mkv(k4a_playback_context_t *context)
|
|||
{
|
||||
simple_block->SetParent(*last_cluster);
|
||||
uint64_t block_timestamp_ns = simple_block->GlobalTimecode();
|
||||
if (block_timestamp_ns > context->last_timestamp_ns)
|
||||
if (block_timestamp_ns > context->last_file_timestamp_ns)
|
||||
{
|
||||
context->last_timestamp_ns = block_timestamp_ns;
|
||||
context->last_file_timestamp_ns = block_timestamp_ns;
|
||||
}
|
||||
}
|
||||
else if (check_element_type(e, &block_group))
|
||||
|
@ -281,13 +281,13 @@ k4a_result_t parse_mkv(k4a_playback_context_t *context)
|
|||
block_timestamp_ns += block_duration_ns - 1;
|
||||
}
|
||||
}
|
||||
if (block_timestamp_ns > context->last_timestamp_ns)
|
||||
if (block_timestamp_ns > context->last_file_timestamp_ns)
|
||||
{
|
||||
context->last_timestamp_ns = block_timestamp_ns;
|
||||
context->last_file_timestamp_ns = block_timestamp_ns;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_TRACE("Found last timestamp: %llu", context->last_timestamp_ns);
|
||||
LOG_TRACE("Found last file timestamp: %llu", context->last_file_timestamp_ns);
|
||||
|
||||
return K4A_RESULT_SUCCEEDED;
|
||||
}
|
||||
|
@ -1750,7 +1750,9 @@ k4a_result_t convert_block_to_image(k4a_playback_context_t *context,
|
|||
&free_vector_buffer,
|
||||
buffer,
|
||||
image_out));
|
||||
k4a_image_set_device_timestamp_usec(*image_out, in_block->timestamp_ns / 1000);
|
||||
uint64_t device_timestamp_usec = in_block->timestamp_ns / 1000 +
|
||||
(uint64_t)context->record_config.start_timestamp_offset_usec;
|
||||
k4a_image_set_device_timestamp_usec(*image_out, device_timestamp_usec);
|
||||
}
|
||||
|
||||
if (K4A_FAILED(result) && buffer != NULL)
|
||||
|
@ -2041,6 +2043,11 @@ k4a_stream_result_t get_imu_sample(k4a_playback_context_t *context, k4a_imu_samp
|
|||
else
|
||||
{
|
||||
// The timestamp we're looking for is within the found block.
|
||||
// IMU timestamps within the sample buffer are device timestamps, not relative to start of file.
|
||||
// The seek timestamp needs to be converted to a device timestamp when comparing.
|
||||
uint64_t seek_device_timestamp_ns = context->seek_timestamp_ns +
|
||||
((uint64_t)context->record_config.start_timestamp_offset_usec *
|
||||
1000);
|
||||
context->imu_sample_index = -1;
|
||||
for (size_t i = 0; i < sample_count; i++)
|
||||
{
|
||||
|
@ -2051,7 +2058,7 @@ k4a_stream_result_t get_imu_sample(k4a_playback_context_t *context, k4a_imu_samp
|
|||
*imu_sample = { 0 };
|
||||
return K4A_STREAM_RESULT_FAILED;
|
||||
}
|
||||
else if (sample->acc_timestamp_ns >= context->seek_timestamp_ns)
|
||||
else if (sample->acc_timestamp_ns >= seek_device_timestamp_ns)
|
||||
{
|
||||
context->imu_sample_index = next ? (int)i : (int)i - 1;
|
||||
break;
|
||||
|
|
|
@ -297,7 +297,16 @@ k4a_result_t k4a_playback_seek_timestamp(k4a_playback_t playback_handle,
|
|||
k4a_playback_context_t *context = k4a_playback_t_get_context(playback_handle);
|
||||
RETURN_VALUE_IF_ARG(K4A_RESULT_FAILED, context == NULL);
|
||||
RETURN_VALUE_IF_ARG(K4A_RESULT_FAILED, context->segment == nullptr);
|
||||
RETURN_VALUE_IF_ARG(K4A_RESULT_FAILED, origin != K4A_PLAYBACK_SEEK_BEGIN && origin != K4A_PLAYBACK_SEEK_END);
|
||||
RETURN_VALUE_IF_ARG(K4A_RESULT_FAILED,
|
||||
origin != K4A_PLAYBACK_SEEK_BEGIN && origin != K4A_PLAYBACK_SEEK_END &&
|
||||
origin != K4A_PLAYBACK_SEEK_DEVICE_TIME);
|
||||
|
||||
// If seeking to a device timestamp, calculate the offset relative to the start of file.
|
||||
if (origin == K4A_PLAYBACK_SEEK_DEVICE_TIME)
|
||||
{
|
||||
origin = K4A_PLAYBACK_SEEK_BEGIN;
|
||||
offset_usec -= (int64_t)context->record_config.start_timestamp_offset_usec;
|
||||
}
|
||||
|
||||
// Clamp the offset timestamp so the seek direction is correct reletive to the specified origin.
|
||||
if (origin == K4A_PLAYBACK_SEEK_BEGIN && offset_usec < 0)
|
||||
|
@ -313,14 +322,14 @@ k4a_result_t k4a_playback_seek_timestamp(k4a_playback_t playback_handle,
|
|||
if (origin == K4A_PLAYBACK_SEEK_END)
|
||||
{
|
||||
uint64_t offset_ns = (uint64_t)(-offset_usec * 1000);
|
||||
if (offset_ns > context->last_timestamp_ns)
|
||||
if (offset_ns > context->last_file_timestamp_ns)
|
||||
{
|
||||
// If the target timestamp is negative, clamp to 0 so we don't underflow.
|
||||
target_time_ns = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_time_ns = context->last_timestamp_ns + 1 - offset_ns;
|
||||
target_time_ns = context->last_file_timestamp_ns + 1 - offset_ns;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -348,13 +357,22 @@ k4a_result_t k4a_playback_seek_timestamp(k4a_playback_t playback_handle,
|
|||
return K4A_RESULT_SUCCEEDED;
|
||||
}
|
||||
|
||||
uint64_t k4a_playback_get_recording_length_usec(k4a_playback_t playback_handle)
|
||||
{
|
||||
RETURN_VALUE_IF_HANDLE_INVALID(0, k4a_playback_t, playback_handle);
|
||||
|
||||
k4a_playback_context_t *context = k4a_playback_t_get_context(playback_handle);
|
||||
RETURN_VALUE_IF_ARG(0, context == NULL);
|
||||
return context->last_file_timestamp_ns / 1000;
|
||||
}
|
||||
|
||||
uint64_t k4a_playback_get_last_timestamp_usec(k4a_playback_t playback_handle)
|
||||
{
|
||||
RETURN_VALUE_IF_HANDLE_INVALID(0, k4a_playback_t, playback_handle);
|
||||
|
||||
k4a_playback_context_t *context = k4a_playback_t_get_context(playback_handle);
|
||||
RETURN_VALUE_IF_ARG(0, context == NULL);
|
||||
return context->last_timestamp_ns / 1000;
|
||||
return context->last_file_timestamp_ns / 1000;
|
||||
}
|
||||
|
||||
void k4a_playback_close(const k4a_playback_t playback_handle)
|
||||
|
|
|
@ -543,6 +543,13 @@ k4a_result_t k4a_record_write_imu_sample(const k4a_record_t recording_handle, k4
|
|||
k4a_record_context_t *context = k4a_record_t_get_context(recording_handle);
|
||||
RETURN_VALUE_IF_ARG(K4A_RESULT_FAILED, context == NULL);
|
||||
|
||||
if (!context->imu_track)
|
||||
{
|
||||
LOG_ERROR("The IMU track needs to be added with k4a_record_add_imu_track() before IMU samples can be written.",
|
||||
0);
|
||||
return K4A_RESULT_FAILED;
|
||||
}
|
||||
|
||||
if (!context->header_written)
|
||||
{
|
||||
LOG_ERROR("The recording header needs to be written before any imu samples.", 0);
|
||||
|
|
|
@ -110,6 +110,28 @@ TEST_F(playback_perf, test_open)
|
|||
}
|
||||
}
|
||||
|
||||
if (config.imu_track_enabled)
|
||||
{
|
||||
k4a_imu_sample_t imu_sample = { 0 };
|
||||
k4a_stream_result_t playback_result = k4a_playback_get_next_imu_sample(handle, &imu_sample);
|
||||
ASSERT_NE(playback_result, K4A_STREAM_RESULT_FAILED);
|
||||
if (playback_result == K4A_STREAM_RESULT_EOF)
|
||||
{
|
||||
std::cout << "No IMU data in recording." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << std::endl;
|
||||
std::cout << "First IMU sample:" << std::endl;
|
||||
std::cout << " Accel Timestamp: " << imu_sample.acc_timestamp_usec << " usec" << std::endl;
|
||||
std::cout << " Accel Data: (" << imu_sample.acc_sample.xyz.x << ", " << imu_sample.acc_sample.xyz.y
|
||||
<< ", " << imu_sample.acc_sample.xyz.z << ")" << std::endl;
|
||||
std::cout << " Gyro Timestamp: " << imu_sample.gyro_timestamp_usec << " usec" << std::endl;
|
||||
std::cout << " Gyro Data: (" << imu_sample.gyro_sample.xyz.x << ", " << imu_sample.gyro_sample.xyz.y
|
||||
<< ", " << imu_sample.gyro_sample.xyz.z << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
k4a_playback_close(handle);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ TEST_F(playback_ut, open_large_file)
|
|||
k4a_stream_result_t stream_result = K4A_STREAM_RESULT_FAILED;
|
||||
uint64_t timestamps[3] = { 0, 1000, 1000 };
|
||||
uint64_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(config.camera_fps);
|
||||
int i = 0;
|
||||
size_t i = 0;
|
||||
for (; i < 50; i++)
|
||||
{
|
||||
stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
|
@ -130,7 +130,7 @@ TEST_F(playback_ut, open_large_file)
|
|||
timestamps[1] += timestamp_delta;
|
||||
timestamps[2] += timestamp_delta;
|
||||
}
|
||||
for (; i < 100; i++)
|
||||
for (; i < test_frame_count; i++)
|
||||
{
|
||||
stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
|
@ -180,7 +180,7 @@ TEST_F(playback_ut, open_delay_offset_file)
|
|||
uint64_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(config.camera_fps);
|
||||
|
||||
// Read forward
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
|
@ -199,7 +199,7 @@ TEST_F(playback_ut, open_delay_offset_file)
|
|||
ASSERT_EQ(capture, (k4a_capture_t)NULL);
|
||||
|
||||
// Read backward
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
timestamps[0] -= timestamp_delta;
|
||||
timestamps[1] -= timestamp_delta;
|
||||
|
@ -241,6 +241,16 @@ TEST_F(playback_ut, open_subordinate_delay_file)
|
|||
ASSERT_EQ(config.depth_delay_off_color_usec, 0);
|
||||
ASSERT_EQ(config.wired_sync_mode, K4A_WIRED_SYNC_MODE_SUBORDINATE);
|
||||
ASSERT_EQ(config.subordinate_delay_off_master_usec, (uint32_t)10000);
|
||||
ASSERT_EQ(config.start_timestamp_offset_usec, (uint32_t)10000);
|
||||
|
||||
uint64_t timestamps[3] = { 10000, 10000, 10000 };
|
||||
|
||||
k4a_capture_t capture = NULL;
|
||||
k4a_stream_result_t stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(
|
||||
validate_test_capture(capture, timestamps, config.color_format, config.color_resolution, config.depth_mode));
|
||||
k4a_capture_release(capture);
|
||||
|
||||
k4a_playback_close(handle);
|
||||
}
|
||||
|
@ -295,7 +305,7 @@ TEST_F(playback_ut, playback_seek_test)
|
|||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_imu_sample(imu_sample, imu_timestamp));
|
||||
|
||||
int64_t recording_length = (int64_t)k4a_playback_get_last_timestamp_usec(handle) + 1;
|
||||
int64_t recording_length = (int64_t)k4a_playback_get_recording_length_usec(handle) + 1;
|
||||
std::pair<int64_t, k4a_playback_seek_origin_t> start_seek_combinations[] = { // Beginning
|
||||
{ 0, K4A_PLAYBACK_SEEK_BEGIN },
|
||||
{ -recording_length,
|
||||
|
@ -535,9 +545,7 @@ TEST_F(playback_ut, open_skipped_frames_file)
|
|||
|
||||
k4a_capture_t capture = NULL;
|
||||
k4a_stream_result_t stream_result = K4A_STREAM_RESULT_FAILED;
|
||||
uint64_t timestamps[3] = { 1000000 - config.start_timestamp_offset_usec,
|
||||
1001000 - config.start_timestamp_offset_usec,
|
||||
1001000 - config.start_timestamp_offset_usec };
|
||||
uint64_t timestamps[3] = { 1000000, 1001000, 1001000 };
|
||||
uint64_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(config.camera_fps);
|
||||
|
||||
// Test initial state
|
||||
|
@ -570,7 +578,7 @@ TEST_F(playback_ut, open_skipped_frames_file)
|
|||
|
||||
// Test seek past beginning
|
||||
result = k4a_playback_seek_timestamp(handle,
|
||||
-(int64_t)k4a_playback_get_last_timestamp_usec(handle) - 10,
|
||||
-(int64_t)k4a_playback_get_recording_length_usec(handle) - 10,
|
||||
K4A_PLAYBACK_SEEK_END);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
|
@ -601,7 +609,7 @@ TEST_F(playback_ut, open_skipped_frames_file)
|
|||
|
||||
// Test seek to end, relative to start
|
||||
result = k4a_playback_seek_timestamp(handle,
|
||||
(int64_t)k4a_playback_get_last_timestamp_usec(handle) + 1,
|
||||
(int64_t)k4a_playback_get_recording_length_usec(handle) + 1,
|
||||
K4A_PLAYBACK_SEEK_BEGIN);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
|
@ -620,7 +628,7 @@ TEST_F(playback_ut, open_skipped_frames_file)
|
|||
timestamps[0] -= timestamp_delta * 50;
|
||||
timestamps[1] -= timestamp_delta * 50;
|
||||
timestamps[2] -= timestamp_delta * 50;
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)timestamps[0], K4A_PLAYBACK_SEEK_BEGIN);
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)timestamps[0], K4A_PLAYBACK_SEEK_DEVICE_TIME);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
|
@ -631,7 +639,7 @@ TEST_F(playback_ut, open_skipped_frames_file)
|
|||
k4a_capture_release(capture);
|
||||
|
||||
// Test seek to middle of the recording, then read backward
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)timestamps[0], K4A_PLAYBACK_SEEK_BEGIN);
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)timestamps[0], K4A_PLAYBACK_SEEK_DEVICE_TIME);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
timestamps[0] -= timestamp_delta;
|
||||
|
@ -646,7 +654,7 @@ TEST_F(playback_ut, open_skipped_frames_file)
|
|||
k4a_capture_release(capture);
|
||||
|
||||
// Read the rest of the file
|
||||
for (int i = 49; i < 100; i++)
|
||||
for (size_t i = 49; i < test_frame_count; i++)
|
||||
{
|
||||
timestamps[0] += timestamp_delta;
|
||||
timestamps[1] += timestamp_delta;
|
||||
|
@ -721,11 +729,11 @@ TEST_F(playback_ut, open_imu_playback_file)
|
|||
k4a_imu_sample_t imu_sample = { 0 };
|
||||
k4a_stream_result_t stream_result = K4A_STREAM_RESULT_FAILED;
|
||||
uint64_t imu_timestamp = 1150;
|
||||
uint64_t last_timestamp = k4a_playback_get_last_timestamp_usec(handle);
|
||||
ASSERT_EQ(last_timestamp, 3333150);
|
||||
uint64_t recording_length = k4a_playback_get_recording_length_usec(handle);
|
||||
ASSERT_EQ(recording_length, 3333150);
|
||||
|
||||
// Read forward
|
||||
while (imu_timestamp <= last_timestamp)
|
||||
while (imu_timestamp <= recording_length)
|
||||
{
|
||||
stream_result = k4a_playback_get_next_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
|
@ -749,7 +757,7 @@ TEST_F(playback_ut, open_imu_playback_file)
|
|||
ASSERT_TRUE(validate_null_imu_sample(imu_sample));
|
||||
|
||||
// Test seeking to first 100 samples (covers edge cases around block boundaries)
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
// Seek to before sample
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)imu_timestamp - 100, K4A_PLAYBACK_SEEK_BEGIN);
|
||||
|
@ -781,6 +789,204 @@ TEST_F(playback_ut, open_imu_playback_file)
|
|||
k4a_playback_close(handle);
|
||||
}
|
||||
|
||||
TEST_F(playback_ut, open_start_offset_file)
|
||||
{
|
||||
k4a_playback_t handle = NULL;
|
||||
k4a_result_t result = k4a_playback_open("record_test_offset.mkv", &handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
// Read recording configuration
|
||||
k4a_record_configuration_t config;
|
||||
result = k4a_playback_get_record_configuration(handle, &config);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
ASSERT_EQ(config.color_format, K4A_IMAGE_FORMAT_COLOR_MJPG);
|
||||
ASSERT_EQ(config.color_resolution, K4A_COLOR_RESOLUTION_1080P);
|
||||
ASSERT_EQ(config.depth_mode, K4A_DEPTH_MODE_NFOV_UNBINNED);
|
||||
ASSERT_EQ(config.camera_fps, K4A_FRAMES_PER_SECOND_30);
|
||||
ASSERT_TRUE(config.color_track_enabled);
|
||||
ASSERT_TRUE(config.depth_track_enabled);
|
||||
ASSERT_TRUE(config.ir_track_enabled);
|
||||
ASSERT_TRUE(config.imu_track_enabled);
|
||||
ASSERT_EQ(config.depth_delay_off_color_usec, 0);
|
||||
ASSERT_EQ(config.wired_sync_mode, K4A_WIRED_SYNC_MODE_STANDALONE);
|
||||
ASSERT_EQ(config.subordinate_delay_off_master_usec, (uint32_t)0);
|
||||
ASSERT_EQ(config.start_timestamp_offset_usec, (uint32_t)1000000);
|
||||
|
||||
k4a_capture_t capture = NULL;
|
||||
k4a_imu_sample_t imu_sample = { 0 };
|
||||
k4a_stream_result_t stream_result = K4A_STREAM_RESULT_FAILED;
|
||||
uint64_t timestamps[3] = { 1000000, 1000000, 1000000 };
|
||||
uint64_t imu_timestamp = 1001150;
|
||||
uint64_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(config.camera_fps);
|
||||
uint64_t last_timestamp = k4a_playback_get_recording_length_usec(handle) +
|
||||
(uint64_t)config.start_timestamp_offset_usec;
|
||||
ASSERT_EQ(last_timestamp, (uint64_t)config.start_timestamp_offset_usec + 3333150);
|
||||
|
||||
// Read capture forward
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_test_capture(capture,
|
||||
timestamps,
|
||||
config.color_format,
|
||||
config.color_resolution,
|
||||
config.depth_mode));
|
||||
k4a_capture_release(capture);
|
||||
timestamps[0] += timestamp_delta;
|
||||
timestamps[1] += timestamp_delta;
|
||||
timestamps[2] += timestamp_delta;
|
||||
}
|
||||
stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_EOF);
|
||||
ASSERT_EQ(capture, (k4a_capture_t)NULL);
|
||||
|
||||
// Read capture backward
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
timestamps[0] -= timestamp_delta;
|
||||
timestamps[1] -= timestamp_delta;
|
||||
timestamps[2] -= timestamp_delta;
|
||||
stream_result = k4a_playback_get_previous_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_test_capture(capture,
|
||||
timestamps,
|
||||
config.color_format,
|
||||
config.color_resolution,
|
||||
config.depth_mode));
|
||||
k4a_capture_release(capture);
|
||||
}
|
||||
stream_result = k4a_playback_get_previous_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_EOF);
|
||||
ASSERT_EQ(capture, (k4a_capture_t)NULL);
|
||||
|
||||
// Read IMU forward
|
||||
while (imu_timestamp <= last_timestamp)
|
||||
{
|
||||
stream_result = k4a_playback_get_next_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_imu_sample(imu_sample, imu_timestamp));
|
||||
imu_timestamp += 1000;
|
||||
}
|
||||
stream_result = k4a_playback_get_next_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_EOF);
|
||||
ASSERT_TRUE(validate_null_imu_sample(imu_sample));
|
||||
|
||||
// Read IMU backward
|
||||
while (imu_timestamp > 1001150)
|
||||
{
|
||||
imu_timestamp -= 1000;
|
||||
stream_result = k4a_playback_get_previous_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_imu_sample(imu_sample, imu_timestamp));
|
||||
}
|
||||
stream_result = k4a_playback_get_previous_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_EOF);
|
||||
ASSERT_TRUE(validate_null_imu_sample(imu_sample));
|
||||
|
||||
// Test seeking to first 100 samples (covers edge cases around block boundaries)
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
// Seek to before sample
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)imu_timestamp - 100, K4A_PLAYBACK_SEEK_DEVICE_TIME);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
stream_result = k4a_playback_get_next_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_imu_sample(imu_sample, imu_timestamp));
|
||||
|
||||
// Seek exactly to sample
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)imu_timestamp, K4A_PLAYBACK_SEEK_DEVICE_TIME);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
stream_result = k4a_playback_get_next_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_imu_sample(imu_sample, imu_timestamp));
|
||||
|
||||
// Seek to after sample
|
||||
result = k4a_playback_seek_timestamp(handle, (int64_t)imu_timestamp + 100, K4A_PLAYBACK_SEEK_DEVICE_TIME);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
stream_result = k4a_playback_get_previous_imu_sample(handle, &imu_sample);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(validate_imu_sample(imu_sample, imu_timestamp));
|
||||
|
||||
imu_timestamp += 1000;
|
||||
}
|
||||
|
||||
k4a_playback_close(handle);
|
||||
}
|
||||
|
||||
TEST_F(playback_ut, open_color_only_file)
|
||||
{
|
||||
k4a_playback_t handle = NULL;
|
||||
k4a_result_t result = k4a_playback_open("record_test_color_only.mkv", &handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
// Read recording configuration
|
||||
k4a_record_configuration_t config;
|
||||
result = k4a_playback_get_record_configuration(handle, &config);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
ASSERT_EQ(config.color_format, K4A_IMAGE_FORMAT_COLOR_MJPG);
|
||||
ASSERT_EQ(config.color_resolution, K4A_COLOR_RESOLUTION_1080P);
|
||||
ASSERT_EQ(config.depth_mode, K4A_DEPTH_MODE_OFF);
|
||||
ASSERT_EQ(config.camera_fps, K4A_FRAMES_PER_SECOND_30);
|
||||
ASSERT_TRUE(config.color_track_enabled);
|
||||
ASSERT_FALSE(config.depth_track_enabled);
|
||||
ASSERT_FALSE(config.ir_track_enabled);
|
||||
ASSERT_FALSE(config.imu_track_enabled);
|
||||
ASSERT_EQ(config.depth_delay_off_color_usec, 0);
|
||||
ASSERT_EQ(config.wired_sync_mode, K4A_WIRED_SYNC_MODE_STANDALONE);
|
||||
ASSERT_EQ(config.subordinate_delay_off_master_usec, (uint32_t)0);
|
||||
ASSERT_EQ(config.start_timestamp_offset_usec, (uint32_t)0);
|
||||
|
||||
uint64_t timestamps[3] = { 0, 0, 0 };
|
||||
|
||||
k4a_capture_t capture = NULL;
|
||||
k4a_stream_result_t stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(
|
||||
validate_test_capture(capture, timestamps, config.color_format, config.color_resolution, config.depth_mode));
|
||||
k4a_capture_release(capture);
|
||||
|
||||
k4a_playback_close(handle);
|
||||
}
|
||||
|
||||
TEST_F(playback_ut, open_depth_only_file)
|
||||
{
|
||||
k4a_playback_t handle = NULL;
|
||||
k4a_result_t result = k4a_playback_open("record_test_depth_only.mkv", &handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
// Read recording configuration
|
||||
k4a_record_configuration_t config;
|
||||
result = k4a_playback_get_record_configuration(handle, &config);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
ASSERT_EQ(config.color_format, K4A_IMAGE_FORMAT_CUSTOM);
|
||||
ASSERT_EQ(config.color_resolution, K4A_COLOR_RESOLUTION_OFF);
|
||||
ASSERT_EQ(config.depth_mode, K4A_DEPTH_MODE_NFOV_UNBINNED);
|
||||
ASSERT_EQ(config.camera_fps, K4A_FRAMES_PER_SECOND_30);
|
||||
ASSERT_FALSE(config.color_track_enabled);
|
||||
ASSERT_TRUE(config.depth_track_enabled);
|
||||
ASSERT_TRUE(config.ir_track_enabled);
|
||||
ASSERT_FALSE(config.imu_track_enabled);
|
||||
ASSERT_EQ(config.depth_delay_off_color_usec, 0);
|
||||
ASSERT_EQ(config.wired_sync_mode, K4A_WIRED_SYNC_MODE_STANDALONE);
|
||||
ASSERT_EQ(config.subordinate_delay_off_master_usec, (uint32_t)0);
|
||||
ASSERT_EQ(config.start_timestamp_offset_usec, (uint32_t)0);
|
||||
|
||||
uint64_t timestamps[3] = { 0, 0, 0 };
|
||||
|
||||
k4a_capture_t capture = NULL;
|
||||
k4a_stream_result_t stream_result = k4a_playback_get_next_capture(handle, &capture);
|
||||
ASSERT_EQ(stream_result, K4A_STREAM_RESULT_SUCCEEDED);
|
||||
ASSERT_TRUE(
|
||||
validate_test_capture(capture, timestamps, config.color_format, config.color_resolution, config.depth_mode));
|
||||
k4a_capture_release(capture);
|
||||
|
||||
k4a_playback_close(handle);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
k4a_unittest_init();
|
||||
|
|
|
@ -29,6 +29,12 @@ void SampleRecordings::SetUp()
|
|||
record_config_sub.wired_sync_mode = K4A_WIRED_SYNC_MODE_SUBORDINATE;
|
||||
record_config_sub.subordinate_delay_off_master_usec = 10000; // 10ms
|
||||
|
||||
k4a_device_configuration_t record_config_color_only = record_config_full;
|
||||
record_config_color_only.depth_mode = K4A_DEPTH_MODE_OFF;
|
||||
|
||||
k4a_device_configuration_t record_config_depth_only = record_config_full;
|
||||
record_config_depth_only.color_resolution = K4A_COLOR_RESOLUTION_OFF;
|
||||
|
||||
{
|
||||
k4a_record_t handle = NULL;
|
||||
k4a_result_t result = k4a_record_create("record_test_empty.mkv", NULL, record_config_empty, &handle);
|
||||
|
@ -57,7 +63,7 @@ void SampleRecordings::SetUp()
|
|||
uint64_t imu_timestamp = 1150;
|
||||
uint32_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(record_config_full.camera_fps);
|
||||
k4a_capture_t capture = NULL;
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
capture = create_test_capture(timestamps,
|
||||
record_config_full.color_format,
|
||||
|
@ -100,7 +106,7 @@ void SampleRecordings::SetUp()
|
|||
(uint64_t)record_config_delay.depth_delay_off_color_usec };
|
||||
uint32_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(record_config_delay.camera_fps);
|
||||
k4a_capture_t capture = NULL;
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
capture = create_test_capture(timestamps,
|
||||
record_config_delay.color_format,
|
||||
|
@ -120,7 +126,7 @@ void SampleRecordings::SetUp()
|
|||
|
||||
k4a_record_close(handle);
|
||||
}
|
||||
{
|
||||
{ // Create a recording file with a subordinate delay off master
|
||||
k4a_record_t handle = NULL;
|
||||
k4a_result_t result = k4a_record_create("record_test_sub.mkv", NULL, record_config_sub, &handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
@ -128,7 +134,9 @@ void SampleRecordings::SetUp()
|
|||
result = k4a_record_write_header(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
uint64_t timestamps[3] = { 0, 0, 0 };
|
||||
uint64_t timestamps[3] = { record_config_sub.subordinate_delay_off_master_usec,
|
||||
record_config_sub.subordinate_delay_off_master_usec,
|
||||
record_config_sub.subordinate_delay_off_master_usec };
|
||||
k4a_capture_t capture = create_test_capture(timestamps,
|
||||
record_config_sub.color_format,
|
||||
record_config_sub.color_resolution,
|
||||
|
@ -158,7 +166,7 @@ void SampleRecordings::SetUp()
|
|||
|
||||
uint64_t timestamps[3] = { 1000000, 1001000, 1001000 }; // Start recording at 1s
|
||||
uint32_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(record_config_full.camera_fps);
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
// Create a known pattern of dropped / missing frames that can be tested against
|
||||
// The pattern is repeated every 4 captures until the end of the file.
|
||||
|
@ -208,6 +216,95 @@ void SampleRecordings::SetUp()
|
|||
result = k4a_record_flush(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
k4a_record_close(handle);
|
||||
}
|
||||
{ // Create a recording file with a start offset and all tracks enabled
|
||||
k4a_record_t handle = NULL;
|
||||
k4a_result_t result = k4a_record_create("record_test_offset.mkv", NULL, record_config_full, &handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
result = k4a_record_add_imu_track(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
result = k4a_record_write_header(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
uint64_t timestamps[3] = { 1000000, 1000000, 1000000 };
|
||||
uint64_t imu_timestamp = 1001150;
|
||||
uint32_t timestamp_delta = 1000000 / k4a_convert_fps_to_uint(record_config_delay.camera_fps);
|
||||
k4a_capture_t capture = NULL;
|
||||
for (size_t i = 0; i < test_frame_count; i++)
|
||||
{
|
||||
capture = create_test_capture(timestamps,
|
||||
record_config_delay.color_format,
|
||||
record_config_delay.color_resolution,
|
||||
record_config_delay.depth_mode);
|
||||
result = k4a_record_write_capture(handle, capture);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
k4a_capture_release(capture);
|
||||
|
||||
timestamps[0] += timestamp_delta;
|
||||
timestamps[1] += timestamp_delta;
|
||||
timestamps[2] += timestamp_delta;
|
||||
|
||||
while (imu_timestamp < timestamps[0])
|
||||
{
|
||||
k4a_imu_sample_t imu_sample = create_test_imu_sample(imu_timestamp);
|
||||
result = k4a_record_write_imu_sample(handle, imu_sample);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
// Write IMU samples at ~1000 samples per second (this is an arbitrary rate for testing)
|
||||
imu_timestamp += 1000; // 1ms
|
||||
}
|
||||
}
|
||||
|
||||
result = k4a_record_flush(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
k4a_record_close(handle);
|
||||
}
|
||||
{ // Create a recording file with only the color camera enabled
|
||||
k4a_record_t handle = NULL;
|
||||
k4a_result_t result = k4a_record_create("record_test_color_only.mkv", NULL, record_config_color_only, &handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
result = k4a_record_write_header(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
uint64_t timestamps[3] = { 0, 0, 0 };
|
||||
k4a_capture_t capture = create_test_capture(timestamps,
|
||||
record_config_color_only.color_format,
|
||||
record_config_color_only.color_resolution,
|
||||
record_config_color_only.depth_mode);
|
||||
result = k4a_record_write_capture(handle, capture);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
k4a_capture_release(capture);
|
||||
|
||||
result = k4a_record_flush(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
k4a_record_close(handle);
|
||||
}
|
||||
{ // Create a recording file with only the depth camera enabled
|
||||
k4a_record_t handle = NULL;
|
||||
k4a_result_t result = k4a_record_create("record_test_depth_only.mkv", NULL, record_config_depth_only, &handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
result = k4a_record_write_header(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
uint64_t timestamps[3] = { 0, 0, 0 };
|
||||
k4a_capture_t capture = create_test_capture(timestamps,
|
||||
record_config_depth_only.color_format,
|
||||
record_config_depth_only.color_resolution,
|
||||
record_config_depth_only.depth_mode);
|
||||
result = k4a_record_write_capture(handle, capture);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
k4a_capture_release(capture);
|
||||
|
||||
result = k4a_record_flush(handle);
|
||||
ASSERT_EQ(result, K4A_RESULT_SUCCEEDED);
|
||||
|
||||
k4a_record_close(handle);
|
||||
}
|
||||
}
|
||||
|
@ -219,4 +316,7 @@ void SampleRecordings::TearDown()
|
|||
ASSERT_EQ(std::remove("record_test_delay.mkv"), 0);
|
||||
ASSERT_EQ(std::remove("record_test_skips.mkv"), 0);
|
||||
ASSERT_EQ(std::remove("record_test_sub.mkv"), 0);
|
||||
ASSERT_EQ(std::remove("record_test_offset.mkv"), 0);
|
||||
ASSERT_EQ(std::remove("record_test_color_only.mkv"), 0);
|
||||
ASSERT_EQ(std::remove("record_test_depth_only.mkv"), 0);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,13 @@ static const char *const fps_names[] = { "K4A_FRAMES_PER_SECOND_5",
|
|||
"K4A_FRAMES_PER_SECOND_15",
|
||||
"K4A_FRAMES_PER_SECOND_30" };
|
||||
|
||||
// Testing values
|
||||
static const uint32_t test_depth_width = 640;
|
||||
static const uint32_t test_depth_height = 576;
|
||||
static const uint32_t test_camera_fps = 30;
|
||||
static const uint32_t test_timestamp_delta_usec = 33333;
|
||||
static const size_t test_frame_count = 100;
|
||||
|
||||
k4a_capture_t create_test_capture(uint64_t timestamp_us[3],
|
||||
k4a_image_format_t color_format,
|
||||
k4a_color_resolution_t resolution,
|
||||
|
@ -33,6 +40,7 @@ bool validate_test_capture(k4a_capture_t capture,
|
|||
k4a_image_format_t color_format,
|
||||
k4a_color_resolution_t resolution,
|
||||
k4a_depth_mode_t mode);
|
||||
|
||||
k4a_image_t
|
||||
create_test_image(uint64_t timestamp_us, k4a_image_format_t format, uint32_t width, uint32_t height, uint32_t stride);
|
||||
bool validate_test_image(k4a_image_t image,
|
||||
|
@ -41,6 +49,7 @@ bool validate_test_image(k4a_image_t image,
|
|||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t stride);
|
||||
|
||||
k4a_imu_sample_t create_test_imu_sample(uint64_t timestamp_us);
|
||||
bool validate_imu_sample(k4a_imu_sample_t &imu_sample, uint64_t timestamp_us);
|
||||
bool validate_null_imu_sample(k4a_imu_sample_t &imu_sample);
|
||||
|
|
|
@ -112,8 +112,7 @@ K4ARecordingDockControl::K4ARecordingDockControl(std::string &&path, k4a::playba
|
|||
|
||||
m_subordinateDelayOffMasterUsec = m_recordConfiguration.subordinate_delay_off_master_usec;
|
||||
m_startTimestampOffsetUsec = m_recordConfiguration.start_timestamp_offset_usec;
|
||||
m_playbackThreadState.TimestampOffset = std::chrono::microseconds(m_startTimestampOffsetUsec);
|
||||
m_recordingLengthUsec = static_cast<uint64_t>(recording.get_last_timestamp().count());
|
||||
m_recordingLengthUsec = static_cast<uint64_t>(recording.get_recording_length().count());
|
||||
|
||||
// Device info
|
||||
//
|
||||
|
@ -361,12 +360,6 @@ bool K4ARecordingDockControl::PlaybackThreadFn(PlaybackThreadState *state)
|
|||
break;
|
||||
}
|
||||
|
||||
// Update the timestamps on the IMU samples using the timing data embedded in the recording
|
||||
// so we show comparable timestamps when playing back synchronized recordings
|
||||
//
|
||||
nextImuSample.acc_timestamp_usec += static_cast<uint64_t>(state->TimestampOffset.count());
|
||||
nextImuSample.gyro_timestamp_usec += static_cast<uint64_t>(state->TimestampOffset.count());
|
||||
|
||||
state->ImuDataSource.NotifyObservers(nextImuSample);
|
||||
}
|
||||
}
|
||||
|
@ -392,7 +385,7 @@ bool K4ARecordingDockControl::PlaybackThreadFn(PlaybackThreadState *state)
|
|||
{
|
||||
if (image)
|
||||
{
|
||||
image.set_timestamp(image.get_device_timestamp() + state->TimestampOffset);
|
||||
image.set_timestamp(image.get_device_timestamp());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ private:
|
|||
// Constant state (expected to be set once, accessible without synchronization)
|
||||
//
|
||||
std::chrono::microseconds TimePerFrame;
|
||||
std::chrono::microseconds TimestampOffset = std::chrono::microseconds(0);
|
||||
|
||||
// Recording state
|
||||
//
|
||||
|
|
Загрузка…
Ссылка в новой задаче