15 const char*
CONFIG_QUERY =
"SELECT value FROM rs_config WHERE section = ? AND key = ?";
16 const char*
CONFIG_CREATE =
"CREATE TABLE rs_config(section NUMBER, key TEXT, value TEXT)";
17 const char*
CONFIG_INSERT =
"INSERT OR REPLACE INTO rs_config(section, key, value) VALUES(?, ?, ?)";
23 const char*
SECTIONS_CREATE =
"CREATE TABLE rs_sections(key NUMBER PRIMARY KEY, name TEXT)";
29 const char*
CALLS_CREATE =
"CREATE TABLE rs_calls(section NUMBER, type NUMBER, timestamp NUMBER, entity_id NUMBER, txt TEXT, param1 NUMBER, param2 NUMBER, param3 NUMBER, param4 NUMBER, param5 NUMBER, param6 NUMBER, had_errors NUMBER, param7 NUMBER, param8 NUMBER, param9 NUMBER, param10 NUMBER, param11 NUMBER, param12 NUMBER)";
30 const char*
CALLS_INSERT =
"INSERT INTO rs_calls(section, type, timestamp, entity_id, txt, param1, param2, param3, param4, param5, param6, had_errors, param7, param8, param9, param10, param11, param12) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?,?)";
33 const char*
DEVICE_INFO_CREATE =
"CREATE TABLE rs_device_info(section NUMBER, type NUMBER, id TEXT, uid TEXT, pid NUMBER, vid NUMBER, mi NUMBER)";
35 const char*
DEVICE_INFO_INSERT =
"INSERT INTO rs_device_info(section, type, id, uid, pid, vid, mi) VALUES(?, ?, ?, ?, ?, ?, ?)";
37 const char*
BLOBS_CREATE =
"CREATE TABLE rs_blobs(section NUMBER, data BLOB)";
38 const char*
BLOBS_INSERT =
"INSERT INTO rs_blobs(section, data) VALUES(?, ?)";
41 const char*
PROFILES_CREATE =
"CREATE TABLE rs_profile(section NUMBER, width NUMBER, height NUMBER, fps NUMBER, fourcc NUMBER)";
42 const char*
PROFILES_INSERT =
"INSERT INTO rs_profile(section, width, height, fps, fourcc) VALUES(?, ? ,? ,? ,?)";
59 s << msg <<
" call type: " << int(t) <<
" entity " << entity_id;
86 for (
auto i = 0;
i < 4;
i++)
88 auto dist = abs(xu.bytes[
i] - yu.bytes[
i]);
94 vector<uint8_t> compression_algorithm::decode(
const vector<uint8_t>&
input)
const 96 vector<uint8_t> results;
97 for (
size_t i = 0;
i < input.size() - 5;
i += 5)
104 curr_block.block = *
reinterpret_cast<const uint32_t*
>(input.data() +
i);
105 auto len = input[
i + 4];
106 for (
auto j = 0;
j <
len * 4;
j++)
108 results.push_back(curr_block.bytes[
j % 4]);
116 vector<uint8_t> results;
121 curr_block.block = *
reinterpret_cast<const uint32_t*
>(
data);
123 for (
size_t i = 0;
i <
size;
i += 4)
125 auto block = *
reinterpret_cast<const uint32_t*
>(data +
i);
126 if (
dist(block, curr_block.block) <
min_dist && length < max_length)
132 for (
auto j = 0;
j < 4;
j++)
133 results.push_back(curr_block.bytes[
j]);
134 results.push_back(length);
135 curr_block.block = block;
141 for (
auto j = 0;
j < 4;
j++)
142 results.push_back(curr_block.bytes[
j]);
143 results.push_back(length);
148 recording::recording(std::shared_ptr<time_service> ts, std::shared_ptr<playback_device_watcher> watcher)
149 :_ts(ts), _watcher(watcher)
161 _watcher->raise_callback(old, curr);
174 LOG_WARNING(
"Saving recording to file, don't close the application");
192 check_section_unique.
bind(1, section);
193 auto result = check_section_unique();
194 if (
result[0].get_int() > 0)
196 throw runtime_error(
to_string() <<
"Append record - can't save over existing section in file " << filename <<
"!");
202 auto result = max_section_id();
203 section_id =
result[0].get_int() + 1;
208 create_section.
bind(1, section_id);
209 create_section.
bind(2, section);
217 check_section_exists.
bind(1, section);
218 auto result = check_section_exists();
219 if (
result[0].get_int() == 0)
221 throw runtime_error(
to_string() <<
"Append record - Could not find section " << section <<
" in file " << filename <<
"!");
226 find_section_id.
bind(1, section);
227 auto result = find_section_id();
228 section_id =
result[0].get_int();
236 insert.
bind(1, section_id);
244 insert.
bind(1, section_id);
247 insert.
bind(3, datetime.c_str());
254 for (
auto&& cl :
calls)
257 insert.
bind(1, section_id);
258 insert.
bind(2, static_cast<int>(cl.type));
259 insert.
bind(3, cl.timestamp);
260 insert.
bind(4, cl.entity_id);
261 insert.
bind(5, cl.inline_string.c_str());
262 insert.
bind(6, cl.param1);
263 insert.
bind(7, cl.param2);
264 insert.
bind(8, cl.param3);
265 insert.
bind(9, cl.param4);
266 insert.
bind(10, cl.param5);
267 insert.
bind(11, cl.param6);
268 insert.
bind(12, cl.had_error ? 1 : 0);
269 insert.
bind(13, cl.param7);
270 insert.
bind(14, cl.param8);
271 insert.
bind(15, cl.param9);
272 insert.
bind(16, cl.param10);
273 insert.
bind(17, cl.param11);
274 insert.
bind(18, cl.param12);
282 insert.
bind(1, section_id);
285 insert.
bind(4, uvc_info.unique_id.c_str());
286 insert.
bind(5, (
int)uvc_info.pid);
287 insert.
bind(6, (
int)uvc_info.vid);
288 insert.
bind(7, (
int)uvc_info.mi);
295 insert.
bind(1, section_id);
297 string id(usb_info.id.begin(), usb_info.id.end());
298 insert.
bind(3,
id.c_str());
299 insert.
bind(4, usb_info.unique_id.c_str());
300 insert.
bind(5, (
int)usb_info.pid);
301 insert.
bind(6, (
int)usb_info.vid);
302 insert.
bind(7, (
int)usb_info.mi);
309 insert.
bind(1, section_id);
311 insert.
bind(3, hid_info.id.c_str());
312 insert.
bind(4, hid_info.unique_id.c_str());
314 stringstream ss_vid(hid_info.vid);
315 stringstream ss_pid(hid_info.pid);
317 ss_vid >> hex >> vid;
318 ss_pid >> hex >> pid;
320 insert.
bind(5, (
int)pid);
321 insert.
bind(6, (
int)vid);
322 insert.
bind(7, hid_info.device_path.c_str());
329 insert.
bind(1, section_id);
331 insert.
bind(3, hid_info.name.c_str());
339 insert.
bind(1, section_id);
341 insert.
bind(3, hid_info.name.c_str());
349 insert.
bind(1, section_id);
357 for (
auto&& blob :
blobs)
360 insert.
bind(1, section_id);
361 insert.
bind(2, blob);
369 const int ver_size = 3;
370 int section_version[ver_size] = { -1, -1, -1 };
371 int min_version[ver_size] = { -1 ,-1 , -1 };
372 std::sscanf(api_version.c_str(),
"%d.%d.%d", §ion_version[0], §ion_version[1], §ion_version[2]);
373 std::sscanf(min_api_version.c_str(),
"%d.%d.%d", &min_version[0], &min_version[1], &min_version[2]);
374 for (
int i = 0;
i < ver_size;
i++)
376 if(min_version[
i] < 0)
377 throw runtime_error(
to_string() <<
"Minimum provided version is in wrong format, expexted format: 0.0.0, actual string: " << min_api_version);
378 if (section_version[
i] == min_version[
i])
continue;
379 if (section_version[i] > min_version[i])
continue;
380 if (section_version[i] < min_version[i])
return false;
389 throw runtime_error(
"Recording file not found!");
392 auto result = make_shared<recording>(
nullptr, watcher);
398 throw runtime_error(
"Invalid recording, missing config section!");
405 check_section_exists.
bind(1, section);
406 auto result = check_section_exists();
407 if (
result[0].get_int() == 0)
409 throw runtime_error(
to_string() <<
"Could not find section " << section <<
"!");
414 find_section_id.
bind(1, section);
415 auto result = find_section_id();
416 section_id =
result[0].get_int();
421 select_api_version.
bind(1, section_id);
423 auto api_version = select_api_version()[0].
get_string();
425 throw runtime_error(
to_string() <<
"File version is lower than the minimum required version that was defind by the test, file version: " <<
426 api_version <<
" min version: " << min_api_version);
427 LOG_WARNING(
"Loaded recording from API version " << api_version);
431 select_calls.
bind(1, section_id);
435 for (
auto&&
row : select_calls)
457 result->calls.push_back(cl);
462 select_devices.
bind(1, section_id);
463 for (
auto&&
row : select_devices)
468 info.
id =
row[2].get_string();
470 info.
pid =
row[4].get_int();
471 info.
vid =
row[5].get_int();
472 info.
mi =
row[6].get_int();
473 result->usb_device_infos.push_back(info);
479 info.
pid =
row[4].get_int();
480 info.
vid =
row[5].get_int();
481 info.
mi =
row[6].get_int();
482 result->uvc_device_infos.push_back(info);
487 info.
id =
row[2].get_string();
493 result->hid_device_infos.push_back(info);
498 info.
name =
row[2].get_string();
500 result->hid_sensors.push_back(info);
505 info.
name =
row[2].get_string();
508 result->hid_sensor_inputs.push_back(info);
513 select_profiles.
bind(1, section_id);
514 for (
auto&&
row : select_profiles)
521 result->stream_profiles.push_back(p);
525 select_blobs.
bind(1, section_id);
527 for (
auto&&
row : select_blobs)
529 result->blobs.push_back(
row[1].get_blob());
538 vector<uint8_t> holder;
541 auto id =
static_cast<int>(
blobs.size());
542 blobs.push_back(holder);
548 return _ts->get_time();
556 for (
size_t i = 1;
i <=
calls.size();
i++)
563 throw runtime_error(
calls[
idx].inline_string);
567 if (!history_match_validation(
calls[
idx]))
582 throw runtime_error(
"The recording is missing the part you are trying to playback!");
602 for (
size_t i = 1;
i <=
calls.size();
i++)
647 _source_watcher->stop();
679 c.param2 = rec1->
save_blob(compressed.data(),
static_cast<int>(compressed.size()));
680 c.param4 =
static_cast<int>(compressed.size());
690 vector<stream_profile> ps{ profile };
700 _source->stream_on();
709 _source->start_callbacks();
718 _source->stop_callbacks();
727 _source->close(profile);
728 vector<stream_profile> ps{ profile };
737 _source->set_power_state(state);
748 auto res = _source->get_power_state();
761 _source->init_xu(xu);
770 auto sts = _source->set_xu(xu, ctrl, data, len);
785 auto sts = _source->get_xu(xu, ctrl, data, len);
800 auto res = _source->get_xu_range(xu, ctrl, len);
817 auto sts = _source->get_pu(opt, value);
832 auto sts = _source->set_pu(opt, value);
847 auto res = _source->get_pu_range(opt);
864 auto devices = _source->get_profiles();
892 _source->register_profiles(hid_profiles);
902 _source->open(hid_profiles);
921 _source->stop_capture();
930 _source->start_capture([
this, callback](
const sensor_data&
sd)
952 auto res = _source->get_sensors();
964 auto result = _source->get_custom_report_data(custom_sensor_name, report_name, report_field);
968 c.param2 = rec->
save_blob(custom_sensor_name.c_str(), custom_sensor_name.size() + 1);
969 c.param3 = rec->
save_blob(report_name.c_str(), report_name.size() + 1);
970 c.param4 = report_field;
980 auto result = _source->get_device_location();
993 auto result = _source->get_usb_specification();
1006 auto result = _source->send_receive(data, timeout_ms, require_response);
1009 c.
param1 = rec->
save_blob((
void*)data.data(),
static_cast<int>(data.size()));
1011 c.param3 = timeout_ms;
1012 c.param4 = require_response;
1023 auto dev = _source->create_hid_device(info);
1025 auto id = _entity_count.fetch_add(1);
1029 return make_shared<record_hid_device>(
dev,
id,
this);
1037 auto devices = _source->query_hid_devices();
1047 auto dev = _source->create_uvc_device(info);
1049 auto id = _entity_count.fetch_add(1);
1053 return make_shared<record_uvc_device>(
dev, _compression,
id,
this);
1061 auto devices = _source->query_uvc_devices();
1071 auto dev = _source->create_usb_device(info);
1073 auto id = _entity_count.fetch_add(1);
1077 return make_shared<record_usb_device>(
dev,
id,
this);
1085 auto devices = _source->query_usb_devices();
1093 return _source->create_time_service();
1098 return std::make_shared<record_device_watcher>(
this, _source->create_device_watcher(), 0);
1104 : _source(source), _rec(
std::make_shared<platform::
recording>(create_time_service())), _entity_count(1),
1105 _filename(filename),
1115 catch (
const runtime_error&
e)
1117 std::cerr <<
"Recording failed: " << e.what() << std::endl;
1121 std::cerr <<
"Recording failed: - unresolved error" << std::endl;
1129 return make_shared<playback_hid_device>(
_rec,
c.param1);
1134 return _rec->load_hid_device_info_list();
1141 return make_shared<playback_uvc_device>(
_rec,
c.param1);
1146 return _rec->load_uvc_device_info_list();
1153 return make_shared<playback_usb_device>(
_rec,
c.param1);
1158 return _rec->load_usb_device_info_list();
1163 return make_shared<recording_time_service>(*_rec);
1168 return _device_watcher;
1173 _rec(platform::
recording::load(filename, section, _device_watcher, min_api_version))
1175 LOG_DEBUG(
"Starting section " << section);
1182 _callback_thread.join();
1187 _rec->save(_filename.c_str(), _section.c_str(),
false);
1192 : _entity_id(id), _alive(false), _dispatcher(10)
1202 std::lock_guard<std::recursive_mutex>
lock(
_mutex);
1211 std::lock_guard<std::recursive_mutex>
lock(
_mutex);
1228 lock_guard<mutex>
lock(_callback_mutex);
1230 auto it = std::remove_if(
begin(_callbacks),
end(_callbacks),
1231 [&profile](
const pair<stream_profile, frame_callback>& pair)
1236 _callbacks.erase(
it,
end(_callbacks));
1237 _commitments.push_back({
profile, callback });
1242 lock_guard<mutex>
lock(_callback_mutex);
1246 for (
auto&& pair : _commitments)
1247 _callbacks.push_back(pair);
1248 _commitments.clear();
1264 vector<stream_profile>
input{ profile };
1265 if (
input != stored)
1268 lock_guard<mutex>
lock(_callback_mutex);
1269 auto it = std::remove_if(
begin(_callbacks),
end(_callbacks),
1270 [&profile](
const pair<stream_profile, frame_callback>& pair)
1274 _callbacks.erase(
it,
end(_callbacks));
1300 return call_found.
param1 == ctrl;
1303 auto stored_data = _rec->load_blob(
c.param2);
1304 vector<uint8_t> in_data(data, data + len);
1305 if (stored_data != in_data)
1309 return (
c.param3 != 0);
1315 if (
c.param1 != ctrl)
1317 auto stored_data = _rec->load_blob(
c.param2);
1318 if (stored_data.size() !=
len)
1321 return (
c.param3 != 0);
1329 return call_found.
param1 == ctrl;
1332 res.
def = _rec->load_blob(
c.param2);
1333 res.
min = _rec->load_blob(
c.param3);
1334 res.
max = _rec->load_blob(
c.param4);
1335 res.
step = _rec->load_blob(
c.param5);
1344 return call_found.
param1 == opt;
1347 return (
c.param3 != 0);
1356 return (
c.param3 != 0);
1364 return call_found.
param1 == opt;
1367 control_range res(_rec->load_blob(
c.param2), _rec->load_blob(
c.param3), _rec->load_blob(
c.param4), _rec->load_blob(
c.param5));
1390 return c.inline_string;
1408 auto stored_iios =
_rec->load_blob(stored.param1);
1415 auto stored_iios =
_rec->load_blob(stored.param1);
1463 report_field == call_found.
param4;
1466 return _rec->load_blob(
c.param1);
1476 auto sd_data =
_rec->load_blob(c_ptr->param1);
1477 auto sensor_name = c_ptr->inline_string;
1480 sd.
fo.
pixels = (
void*)sd_data.data();
1491 this_thread::sleep_for(chrono::milliseconds(1));
1511 return call_found.
param3 == timeout_ms && (call_found.
param4 > 0) == require_response &&
_rec->load_blob(call_found.
param1) ==
data;
1514 return _rec->load_blob(
c.param2);
1521 auto profile_blob =
_rec->load_blob(frame->
param1);
1532 int next_timeout_ms = 0;
1533 double prev_frame_ts = 0;
1542 for (
auto&& pair : _callbacks)
1544 if(get_profile(c_ptr) == pair.first)
1550 auto p = get_profile(c_ptr);
1553 vector<uint8_t> frame_blob;
1554 vector<uint8_t> metadata_blob;
1556 if (prev_frame_ts > 0 &&
1557 c_ptr->timestamp > prev_frame_ts &&
1558 c_ptr->timestamp - prev_frame_ts <= 300)
1560 prev_frame_ts = c_ptr->timestamp - prev_frame_ts;
1563 prev_frame_ts = c_ptr->timestamp;
1565 if (c_ptr->param3 == 0)
1567 frame_blob = vector<uint8_t>(c_ptr->param4, 0);
1569 else if (c_ptr->param3 == 1)
1571 frame_blob =
_rec->load_blob(c_ptr->param2);
1575 frame_blob = _compression.decode(
_rec->load_blob(c_ptr->param2));
1578 metadata_blob =
_rec->load_blob(c_ptr->param5);
1580 static_cast<uint8_t>(metadata_blob.size()),
1581 frame_blob.data(),metadata_blob.data() };
1584 pair.second(
p, fo, []() {});
1603 this_thread::sleep_for(std::chrono::milliseconds(next_timeout_ms));
static const textual_icon lock
const char * DEVICE_INFO_INSERT
const char * CONFIG_CREATE
GLenum GLenum GLsizei void * row
const char * SECTIONS_INSERT
GLuint64EXT GLuint GLuint GLenum GLenum GLuint GLuint GLenum GLuint GLuint key1
rs2_option
Defines general configuration controls. These can generally be mapped to camera UVC controls...
const char * DEVICE_INFO_CREATE
const char * BLOBS_INSERT
const char * SECTIONS_COUNT_BY_NAME
const char * SECTIONS_COUNT_ALL
GLsizei const GLchar *const * string
std::string get_string(int column=0) const
const char * PROFILES_SELECT_ALL
const char * SECTIONS_SELECT_MAX_ID
bool table_exists(const char *name) const
def info(name, value, persistent=False)
const char * SECTIONS_FIND_BY_NAME
const char * API_VERSION_KEY
const char * CONFIG_INSERT
void bind(int param, int value) const
bool file_exists(const char *filename)
const char * CONFIG_QUERY
void transaction(std::function< void()> transaction) const
std::string datetime_string()
const char * CALLS_INSERT
const char * BLOBS_SELECT_ALL
const char * BLOBS_CREATE
std::vector< std::shared_ptr< stream_profile_interface >> stream_profiles
const char * PROFILES_CREATE
void execute(const char *command) const
const char * SECTIONS_TABLE
void next(auto_any_t cur, type2type< T, C > *)
::realsense_legacy_msgs::metadata_< std::allocator< void > > metadata
GLenum GLenum GLenum input
const char * CALLS_CREATE
const char * CALLS_SELECT_ALL
#define RS2_API_VERSION_STR
GLsizei GLsizei GLchar * source
const char * DEVICE_INFO_SELECT_ALL
GLenum GLuint GLenum GLsizei length
const char * PROFILES_INSERT
const char * CREATED_AT_KEY
const char * SECTIONS_CREATE
const char * CONFIG_TABLE
void copy(void *dst, void const *src, size_t size)
std::string to_string(T value)