ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
MKVReader.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
10 #include <json/json.h>
11 #include <k4a/k4a.h>
12 #include <k4arecord/playback.h>
13 #include <k4arecord/record.h>
14 #include <turbojpeg.h>
15 
16 #include <iostream>
17 
20 
21 namespace cloudViewer {
22 namespace io {
23 
24 using namespace cloudViewer;
25 
26 MKVReader::MKVReader() : handle_(nullptr), transformation_(nullptr) {}
27 
28 bool MKVReader::IsOpened() { return handle_ != nullptr; }
29 
30 std::string MKVReader::GetTagInMetadata(const std::string &tag_name) {
31  char res_buffer[256];
32  size_t res_size = 256;
33 
34  k4a_buffer_result_t result = k4a_plugin::k4a_playback_get_tag(
35  handle_, tag_name.c_str(), res_buffer, &res_size);
36  if (K4A_BUFFER_RESULT_SUCCEEDED == result) {
37  return res_buffer;
38  } else if (K4A_BUFFER_RESULT_TOO_SMALL == result) {
39  utility::LogError("{} tag's content is too long.", tag_name);
40  } else {
41  utility::LogError("{} tag does not exist.", tag_name);
42  }
43 }
44 
45 bool MKVReader::Open(const std::string &filename) {
46  if (IsOpened()) {
47  Close();
48  }
49 
50  if (K4A_RESULT_SUCCEEDED !=
51  k4a_plugin::k4a_playback_open(filename.c_str(), &handle_)) {
52  utility::LogWarning("Unable to open file {}", filename);
53  return false;
54  }
55 
56  metadata_.ConvertFromJsonValue(GetMetadataJson());
57  is_eof_ = false;
58 
59  return true;
60 }
61 
63 
64 Json::Value MKVReader::GetMetadataJson() {
65  static const std::unordered_map<std::string, std::pair<int, int>>
66  resolution_to_width_height({{"720P", std::make_pair(1280, 720)},
67  {"1080P", std::make_pair(1920, 1080)},
68  {"1440P", std::make_pair(2560, 1440)},
69  {"1536P", std::make_pair(2048, 1536)},
70  {"2160P", std::make_pair(3840, 2160)},
71  {"3072P", std::make_pair(4096, 3072)}});
72 
73  if (!IsOpened()) {
74  utility::LogError("Null file handler. Please call Open().");
75  }
76 
77  Json::Value value;
78 
79  k4a_calibration_t calibration;
80  if (K4A_RESULT_SUCCEEDED !=
81  k4a_plugin::k4a_playback_get_calibration(handle_, &calibration)) {
82  utility::LogError("Failed to get calibration");
83  }
84 
85  camera::PinholeCameraIntrinsic pinhole_camera;
86  auto color_camera_calibration = calibration.color_camera_calibration;
87  auto param = color_camera_calibration.intrinsics.parameters.param;
88  pinhole_camera.SetIntrinsics(color_camera_calibration.resolution_width,
89  color_camera_calibration.resolution_height,
90  param.fx, param.fy, param.cx, param.cy);
91  pinhole_camera.ConvertToJsonValue(value);
92 
93  value["serial_number"] = GetTagInMetadata("K4A_DEVICE_SERIAL_NUMBER");
94  value["depth_mode"] = GetTagInMetadata("K4A_DEPTH_MODE");
95  value["color_mode"] = GetTagInMetadata("K4A_COLOR_MODE");
96 
97  value["stream_length_usec"] =
99  auto color_mode = value["color_mode"].asString();
100  size_t pos = color_mode.find('_');
101  if (pos == std::string::npos) {
102  utility::LogError("Unknown color format {}", color_mode);
103  }
104  std::string resolution =
105  std::string(color_mode.begin() + pos + 1, color_mode.end());
106  if (resolution_to_width_height.count(resolution) == 0) {
107  utility::LogError("Unknown resolution format {}", resolution);
108  }
109 
110  auto width_height = resolution_to_width_height.at(resolution);
111  value["width"] = width_height.first;
112  value["height"] = width_height.second;
113 
114  // For internal usages
115  transformation_ = k4a_plugin::k4a_transformation_create(&calibration);
116 
117  return value;
118 }
119 
120 bool MKVReader::SeekTimestamp(size_t timestamp) {
121  if (!IsOpened()) {
122  utility::LogWarning("Null file handler. Please call Open().");
123  return false;
124  }
125 
126  if (timestamp >= metadata_.stream_length_usec_) {
127  utility::LogWarning("Timestamp {} exceeds maximum {} (us).", timestamp,
128  metadata_.stream_length_usec_);
129  return false;
130  }
131 
132  if (K4A_RESULT_SUCCEEDED !=
133  k4a_plugin::k4a_playback_seek_timestamp(handle_, timestamp,
134  K4A_PLAYBACK_SEEK_BEGIN)) {
135  utility::LogWarning("Unable to go to timestamp {}", timestamp);
136  return false;
137  }
138  return true;
139 }
140 
141 std::shared_ptr<geometry::RGBDImage> MKVReader::NextFrame() {
142  if (!IsOpened()) {
143  utility::LogError("Null file handler. Please call Open().");
144  }
145 
146  k4a_capture_t k4a_capture;
147  k4a_stream_result_t res =
148  k4a_plugin::k4a_playback_get_next_capture(handle_, &k4a_capture);
149  if (K4A_STREAM_RESULT_EOF == res) {
150  utility::LogInfo("EOF reached");
151  is_eof_ = true;
152  return nullptr;
153  } else if (K4A_STREAM_RESULT_FAILED == res) {
154  utility::LogInfo("Empty frame encountered, skip");
155  return nullptr;
156  }
157 
158  auto rgbd =
159  AzureKinectSensor::DecompressCapture(k4a_capture, transformation_);
160  k4a_plugin::k4a_capture_release(k4a_capture);
161 
162  return rgbd;
163 }
164 } // namespace io
165 } // namespace cloudViewer
std::string filename
core::Tensor result
Definition: VtkUtils.cpp:76
Contains the pinhole camera intrinsic parameters.
bool ConvertToJsonValue(Json::Value &value) const override
void SetIntrinsics(int width, int height, double fx, double fy, double cx, double cy)
Set camera intrinsic parameters.
static std::shared_ptr< geometry::RGBDImage > DecompressCapture(_k4a_capture_t *capture, _k4a_transformation_t *transformation)
uint64_t stream_length_usec_
Length of the video (usec).
Definition: MKVMetadata.h:40
bool ConvertFromJsonValue(const Json::Value &value) override
Definition: MKVMetadata.cpp:30
std::shared_ptr< geometry::RGBDImage > NextFrame()
Get next frame from the mkv playback and returns the RGBD object.
Definition: MKVReader.cpp:141
bool IsOpened()
Check If the mkv file is opened.
Definition: MKVReader.cpp:28
bool Open(const std::string &filename)
Definition: MKVReader.cpp:45
bool SeekTimestamp(size_t timestamp)
Seek to the timestamp (in us).
Definition: MKVReader.cpp:120
void Close()
Close the opened mkv playback.
Definition: MKVReader.cpp:62
MKVReader()
Default Constructor.
Definition: MKVReader.cpp:26
#define LogWarning(...)
Definition: Logging.h:72
#define LogInfo(...)
Definition: Logging.h:81
#define LogError(...)
Definition: Logging.h:60
CLOUDVIEWER_HOST_DEVICE Pair< First, Second > make_pair(const First &_first, const Second &_second)
Definition: SlabTraits.h:49
void k4a_capture_release(k4a_capture_t capture_handle)
Definition: K4aPlugin.cpp:396
k4a_result_t k4a_playback_get_calibration(k4a_playback_t playback_handle, k4a_calibration_t *calibration)
Definition: K4aPlugin.cpp:270
k4a_buffer_result_t k4a_playback_get_tag(k4a_playback_t playback_handle, const char *name, char *value, size_t *value_size)
Definition: K4aPlugin.cpp:288
void k4a_playback_close(k4a_playback_t playback_handle)
Definition: K4aPlugin.cpp:342
k4a_transformation_t k4a_transformation_create(const k4a_calibration_t *calibration)
Definition: K4aPlugin.cpp:789
k4a_result_t k4a_playback_open(const char *path, k4a_playback_t *playback_handle)
Definition: K4aPlugin.cpp:254
uint64_t k4a_playback_get_last_timestamp_usec(k4a_playback_t playback_handle)
Definition: K4aPlugin.cpp:337
k4a_result_t k4a_playback_seek_timestamp(k4a_playback_t playback_handle, int64_t offset_usec, k4a_playback_seek_origin_t origin)
Definition: K4aPlugin.cpp:332
k4a_stream_result_t k4a_playback_get_next_capture(k4a_playback_t playback_handle, k4a_capture_t *capture_handle)
Definition: K4aPlugin.cpp:302
Generic file read and write utility for python interface.