├── Demo ├── Linux │ └── Camera SDK │ │ └── main.cc └── Windows │ └── Camera SDK │ └── main.cc ├── README.md └── README_zh.md /Demo/Linux/Camera SDK/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef _WIN32 15 | #include 16 | #define ACCESS_FUNC _access 17 | #define F_OK 0 18 | #else 19 | #include 20 | #include 21 | #define ACCESS_FUNC access 22 | #endif 23 | 24 | std::shared_ptr cam = nullptr; 25 | 26 | std::string getCurrentTime() { 27 | const auto now = std::chrono::system_clock::now(); 28 | const std::time_t t = std::chrono::system_clock::to_time_t(now); 29 | std::tm tm{}; 30 | #ifdef WIN32 31 | if (localtime_s(&tm, &t)) 32 | #else 33 | if (localtime_r(&t, &tm)) 34 | #endif 35 | { 36 | } 37 | std::stringstream ss; 38 | ss << std::put_time(&tm, "%Y-%m-%d%H%M%S"); 39 | return ss.str(); 40 | } 41 | 42 | bool fileIsExist(const std::string& file_path) { 43 | return ACCESS_FUNC(file_path.c_str(), F_OK) == 0; 44 | } 45 | 46 | bool endsWithSlash(const std::string& path) { 47 | if (path.empty()) { 48 | return false; 49 | } 50 | return path.back() == '/' || path.back() == '\\'; 51 | } 52 | 53 | void parsePath(const std::string& path, std::string& dir, std::string& filename) { 54 | // 查找最后一个路径分隔符(支持'/'和'\') 55 | size_t lastSlash = path.find_last_of("/\\"); 56 | 57 | if (lastSlash == std::string::npos) { 58 | // 没有找到分隔符,整个字符串作为文件名 59 | dir.clear(); 60 | filename = path; 61 | } 62 | else { 63 | // 分隔符前的部分为路径,包含分隔符 64 | dir = path.substr(0, lastSlash + 1); 65 | // 分隔符后的部分为文件名 66 | filename = path.substr(lastSlash + 1); 67 | } 68 | } 69 | 70 | std::string GetFileName(const std::string& path) { 71 | std::smatch sm; 72 | std::string dir, name; 73 | std::regex_match(path, sm, std::regex("(.+?)([^\\/\\\\]+$)")); 74 | if (sm.size() <= 2) { 75 | return path; 76 | } 77 | return sm[2].str(); 78 | } 79 | 80 | class TestStreamDelegate : public ins_camera::StreamDelegate { 81 | public: 82 | TestStreamDelegate() = default; 83 | 84 | virtual ~TestStreamDelegate() { 85 | StopStream(); 86 | } 87 | 88 | void OnAudioData(const uint8_t* data, size_t size, int64_t timestamp) override { 89 | } 90 | 91 | void OnVideoData(const uint8_t* data, size_t size, int64_t timestamp, uint8_t streamType, int stream_index) override { 92 | if (stream_index == 0 && fp1) { 93 | fwrite(data, size, 1, fp1); 94 | } 95 | if (stream_index == 1 && fp2) { 96 | fwrite(data, size, 1, fp2); 97 | } 98 | } 99 | 100 | void OnGyroData(const std::vector& data) override {} 101 | 102 | void OnExposureData(const ins_camera::ExposureData& data) override {} 103 | 104 | void StopStream() { 105 | if (fp1) { 106 | fclose(fp1); 107 | fp1 = nullptr; 108 | } 109 | 110 | if (fp2) { 111 | fclose(fp2); 112 | fp2 = nullptr; 113 | } 114 | } 115 | 116 | void StartStream() { 117 | StopStream(); 118 | const std::string cur_time = getCurrentTime(); 119 | const std::string stream_1 = std::string("./01_") + cur_time + std::string(".h264"); 120 | const std::string stream_2 = std::string("./02_") + cur_time + std::string(".h264"); 121 | #ifdef WIN32 122 | const errno_t err1 = fopen_s(&fp1, stream_1.c_str(), "wb"); 123 | if (err1 != 0) { 124 | std::cerr << "failed to create file " << std::endl; 125 | } 126 | const errno_t err2 = fopen_s(&fp2, stream_2.c_str(), "wb"); 127 | if (err2 != 0) { 128 | std::cerr << "failed to create file " << std::endl; 129 | } 130 | #else 131 | fp1 = fopen(stream_1.c_str(), "wb"); 132 | fp2 = fopen(stream_2.c_str(), "wb"); 133 | #endif 134 | } 135 | 136 | private: 137 | FILE* fp1 = nullptr; 138 | FILE* fp2 = nullptr; 139 | }; 140 | 141 | void signalHandle(int sig) { 142 | if (sig == SIGINT || sig == SIGTERM) { 143 | std::cout << "signal handler: " << sig << std::endl; 144 | if (cam) { 145 | cam->Close(); 146 | } 147 | } 148 | } 149 | 150 | int main(int argc, char* argv[]) { 151 | (void)(signal(SIGINT, signalHandle)); 152 | (void)(signal(SIGTERM, signalHandle)); 153 | 154 | std::cout << "begin open camera" << std::endl; 155 | ins_camera::SetLogLevel(ins_camera::LogLevel::ERR); 156 | for (int i = 1; i < argc; i++) { 157 | const std::string arg = argv[i]; 158 | if (arg == std::string("--debug")) { 159 | ins_camera::SetLogLevel(ins_camera::LogLevel::VERBOSE); 160 | } 161 | else if (arg == std::string("--log_file")) { 162 | const std::string log_file = argv[++i]; 163 | ins_camera::SetLogPath(log_file); 164 | } 165 | } 166 | 167 | ins_camera::DeviceDiscovery discovery; 168 | auto list = discovery.GetAvailableDevices(); 169 | if (list.empty()) { 170 | std::cerr << "no device found." << std::endl; 171 | return -1; 172 | } 173 | 174 | for (const auto& camera : list) { 175 | std::cout << "serial:" << camera.serial_number << "\t" 176 | << ";camera type:" << camera.camera_name << "\t" 177 | << ";fw version:" << camera.fw_version << "\t" 178 | << std::endl; 179 | } 180 | 181 | cam = std::make_shared(list[0].info); 182 | if (!cam->Open()) { 183 | std::cerr << "failed to open camera" << std::endl; 184 | return -1; 185 | } 186 | 187 | const auto camera_type = list[0].camera_type; 188 | const auto serial_number = list[0].serial_number; 189 | 190 | discovery.FreeDeviceDescriptors(list); 191 | 192 | std::shared_ptr delegate = std::make_shared(); 193 | cam->SetStreamDelegate(delegate); 194 | 195 | std::cout << "Succeed to open camera..." << std::endl; 196 | 197 | std::cout << "Usage:" << std::endl; 198 | std::cout << "1: get file list(only video and photo)" << std::endl; 199 | std::cout << "2: delete file" << std::endl; 200 | std::cout << "3: download file" << std::endl; 201 | std::cout << "4: switch video mode" << std::endl; 202 | std::cout << "5: switch photo mode" << std::endl; 203 | std::cout << "6: start normal video mode recording" << std::endl; 204 | std::cout << "7: stop recording" << std::endl; 205 | std::cout << "8: start timelapse " << std::endl; 206 | std::cout << "9: stop timelapse " << std::endl; 207 | std::cout << "10: start preview live streaming:" << std::endl; 208 | std::cout << "11: stop preview live streaming:" << std::endl; 209 | std::cout << "12: enable In-camera stitching (Compatible with X4 and later camera only)" << std::endl; 210 | std::cout << "13: set EV" << std::endl; 211 | std::cout << "14: set ISO" << std::endl; 212 | std::cout << "15: set shutter" << std::endl; 213 | std::cout << "16: set WB" << std::endl; 214 | std::cout << "17: set expouse mode:" << std::endl; 215 | std::cout << "18: get current capture status " << std::endl; 216 | std::cout << "19: test take photo and download " << std::endl; 217 | std::cout << "20: start recording " << std::endl; 218 | std::cout << "21: get battery info " << std::endl; 219 | std::cout << "22: get storage info " << std::endl; 220 | std::cout << "23: get recording file " << std::endl; 221 | std::cout << "24: Check if the camera is still connected" << std::endl; 222 | std::cout << "25: take photo " << std::endl; 223 | std::cout << "30: batch download list files " << std::endl; 224 | std::cout << "31: delete camera all files " << std::endl; 225 | std::cout << "34: start hdr capture " << std::endl; 226 | std::cout << "33: get file list count " << std::endl; 227 | std::cout << "35: upload Firmware (Compatible with X4 and later camera only)" << std::endl; 228 | std::cout << "36: set active sensor (switch lens)" << std::endl; 229 | std::cout << "37: get media time from camera " << std::endl; 230 | std::cout << "38: Shutdown camera " << std::endl; 231 | std::cout << "39: Get camera log" << std::endl; 232 | std::cout << "0: exit" << std::endl; 233 | 234 | time_t now = time(nullptr); 235 | std::tm tm{}; 236 | time_t time_seconds = now; 237 | #ifdef WIN32 238 | (void)(localtime_s(&tm, &now)); 239 | time_seconds = _mkgmtime(&tm); 240 | #else 241 | localtime_r(&now, &tm); 242 | time_seconds = timegm(&tm); 243 | #endif 244 | 245 | std::cout << "UTC time: " << now << std::endl; 246 | std::cout << "GMT time: " << time_seconds << std::endl; 247 | cam->SyncLocalTimeToCamera(time_seconds); 248 | 249 | /*************************demo for 普通照片72MP和 HDR录制5.7K******************/ 250 | //cam->SetPhotoSize(ins_camera::FUNCTION_MODE_NORMAL_IMAGE, ins_camera::PhotoSize::Size_6912_3456); 251 | //ins_camera::RecordParams record_params_test; 252 | //record_params_test.resolution = ins_camera::VideoResolution::RES_2880_2880P30; 253 | //cam->SetVideoCaptureParams(record_params_test, ins_camera::CameraFunctionMode::FUNCTION_MODE_HDR_VIDEO); 254 | /*************************demo for 普通照片72MP和 HDR录制5.7K******************/ 255 | 256 | ins_camera::CameraFunctionMode FuntionMode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 257 | 258 | int option = 0; 259 | while (true) { 260 | std::cout << "please enter index: "; 261 | std::cin >> option; 262 | if (option < 0 || option > 39) { 263 | std::cout << "Invalid index" << std::endl; 264 | continue; 265 | } 266 | 267 | if (option == 0) { 268 | break; 269 | } 270 | 271 | if (option == 1) { 272 | const auto file_list = cam->GetCameraFilesList(); 273 | for (const auto& file : file_list) { 274 | std::cout << "File: " << file << std::endl; 275 | } 276 | } 277 | 278 | if (option == 2) { 279 | const auto file_list = cam->GetCameraFilesList(); 280 | for (const auto& file : file_list) { 281 | std::cout << "File: " << file << std::endl; 282 | } 283 | 284 | std::string file_to_delete; 285 | std::cout << "please input full file path to delete: "; 286 | std::cin >> file_to_delete; 287 | if (file_to_delete.empty()) { 288 | std::cout << "Invalid argument" << std::endl; 289 | continue; 290 | } 291 | 292 | auto exist = std::find_if(file_list.begin(), file_list.end(), [file_to_delete](const std::string& file) 293 | { 294 | return file_to_delete == file; 295 | }) != file_list.end(); 296 | 297 | if (!exist) { 298 | std::cout << "the file that deleted is not exist " << std::endl; 299 | continue; 300 | } 301 | 302 | const auto ret = cam->DeleteCameraFile(file_to_delete); 303 | if (ret) { 304 | std::cout << "deleted succeed" << std::endl; 305 | } 306 | } 307 | 308 | if (option == 3) { 309 | const auto file_list = cam->GetCameraFilesList(); 310 | for (const auto& file : file_list) { 311 | std::cout << "File: " << file << std::endl; 312 | } 313 | 314 | std::string file_to_download; 315 | std::string file_to_save; 316 | std::cout << "please input full file path to download: "; 317 | std::cin >> file_to_download; 318 | 319 | bool exist = std::find_if(file_list.begin(), file_list.end(), [file_to_download](const std::string& file) 320 | { 321 | return file_to_download == file; 322 | }) != file_list.end(); 323 | 324 | if (!exist) { 325 | std::cout << "the file that deleted is not exist " << std::endl; 326 | continue; 327 | } 328 | 329 | std::cout << "please input full file path to save: "; 330 | std::cin >> file_to_save; 331 | 332 | std::string file_to_save_dir; 333 | std::string file_to_save_file_name; 334 | parsePath(file_to_save, file_to_save_dir, file_to_save_file_name); 335 | if (!fileIsExist(file_to_save_dir)) { 336 | std::cout << "dir is not exist, please create it: " << file_to_save_dir << std::endl; 337 | continue; 338 | } 339 | 340 | if (file_to_save_file_name.empty()) { 341 | std::cout << "please input file name" << std::endl; 342 | continue; 343 | } 344 | 345 | int64_t current_process = -1; 346 | const auto ret = cam->DownloadCameraFile(file_to_download, 347 | file_to_save, [&](int64_t current, int64_t total_size) { 348 | const int64_t process = current * 100 / total_size; 349 | if (process != current_process) { 350 | std::cout << "\r"; 351 | std::cout << "process = " << process << "%"; 352 | std::cout << std::flush; 353 | } 354 | }); 355 | std::cout << std::endl; 356 | if (ret) { 357 | std::cout << "Download " << file_to_download << " succeed!!!" << std::endl; 358 | } 359 | else { 360 | std::cout << "Download " << file_to_download << " failed!!!" << std::endl; 361 | } 362 | } 363 | 364 | if (option == 4) { 365 | std::vector support_mode = { 0,2,3,4,11 }; 366 | std::cout << "normal video [0]" << std::endl; 367 | std::cout << "timeplase video [2]" << std::endl; 368 | std::cout << "hdr video [3]" << std::endl; 369 | std::cout << "timeshift video [4]" << std::endl; 370 | std::cout << "pure video [11]" << std::endl; 371 | int video_mode = 0; 372 | std::cout << "Please enter the video mode: "; 373 | std::cin >> video_mode; 374 | if (std::find(support_mode.begin(), support_mode.end(), video_mode) == support_mode.end()) { 375 | std::cerr << "The input video mode is not supported" << std::endl; 376 | continue; 377 | } 378 | bool ret = cam->SetVideoSubMode(static_cast(video_mode)); 379 | if (ret) { 380 | std::cout << "Change Sub mode Succeed!" << std::endl; 381 | } 382 | else { 383 | std::cout << "Change Sub mode Failed!" << std::endl; 384 | } 385 | } 386 | 387 | if (option == 5) { 388 | std::cout << "normal photo [0]" << std::endl; 389 | std::cout << "HDR photo [1]" << std::endl; 390 | std::cout << "INTERVAL photo [2]" << std::endl; 391 | 392 | int photo_mode = 0; 393 | std::cout << "Please enter the photo mode: "; 394 | std::cin >> photo_mode; 395 | if (photo_mode > 7) { 396 | std::cerr << "The input photo mode is not supported" << std::endl; 397 | continue; 398 | } 399 | bool ret = cam->SetPhotoSubMode(static_cast(photo_mode)); 400 | if (ret) { 401 | std::cout << "Change Sub mode Succeed!" << std::endl; 402 | } 403 | else { 404 | std::cout << "Change Sub mode Failed!" << std::endl; 405 | } 406 | } 407 | 408 | if (option == 6) { 409 | bool ret = cam->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_NORMAL); 410 | if (!ret) { 411 | std::cout << "change sub mode failed!" << std::endl; 412 | continue; 413 | } 414 | 415 | ins_camera::RecordParams record_params; 416 | record_params.resolution = ins_camera::VideoResolution::RES_3840_3840P30; 417 | record_params.bitrate = 1024 * 1024 * 10; 418 | if (!cam->SetVideoCaptureParams(record_params, ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_VIDEO)) { 419 | std::cerr << "failed to set capture settings." << std::endl; 420 | } 421 | else { 422 | ret = cam->StartRecording(); 423 | if (ret) { 424 | std::cerr << "success!" << std::endl; 425 | } 426 | else { 427 | std::cerr << "failed to start recording" << std::endl; 428 | } 429 | } 430 | } 431 | 432 | if (option == 7) { 433 | auto url = cam->StopRecording(); 434 | if (url.Empty()) { 435 | std::cerr << "stop recording failed" << std::endl; 436 | continue; 437 | } 438 | auto& origins = url.OriginUrls(); 439 | std::cout << "stop recording success" << std::endl; 440 | for (auto& origin_url : origins) { 441 | std::cout << "url:" << origin_url << std::endl; 442 | } 443 | } 444 | 445 | if (option == 8) { 446 | bool ret = cam->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_TIMELAPSE); 447 | if (!ret) { 448 | std::cout << "change sub mode failed!" << std::endl; 449 | continue; 450 | } 451 | 452 | // 11K30 RES_5632_5632P30 453 | // 8K RES_3840_3840P30 454 | // 5.7K RES_2880_2880P30 455 | // X4支持11K30, X3不支持 456 | std::vector support_list = { 457 | ins_camera::VideoResolution::RES_5632_5632P30, 458 | ins_camera::VideoResolution::RES_3840_3840P30, 459 | ins_camera::VideoResolution::RES_2880_2880P30 460 | }; 461 | 462 | static int count = 0; 463 | ins_camera::RecordParams record_params; 464 | record_params.resolution = support_list[(count++) % 3]; 465 | if (!cam->SetVideoCaptureParams(record_params, ins_camera::CameraFunctionMode::FUNCTION_MODE_MOBILE_TIMELAPSE)) { 466 | std::cerr << "failed to set capture settings." << std::endl; 467 | break; 468 | } 469 | 470 | //mode 是你相机所支持的模式 471 | ins_camera::TimelapseParam param = { ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO, 10,5000,5 }; 472 | if (!cam->SetTimeLapseOption(param)) { 473 | std::cerr << "failed to set capture settings." << std::endl; 474 | } 475 | else { 476 | ret = cam->StartTimeLapse(param.mode); 477 | if (ret) { 478 | std::cerr << "success!" << std::endl; 479 | } 480 | else { 481 | std::cerr << "failed to start timelapse" << std::endl; 482 | } 483 | } 484 | } 485 | 486 | if (option == 9) { 487 | auto url = cam->StopTimeLapse(ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO); 488 | if (url.Empty()) { 489 | std::cerr << "stop timelapse failed" << std::endl; 490 | continue; 491 | } 492 | 493 | std::cout << "stop timelapse success" << std::endl; 494 | auto& origins = url.OriginUrls(); 495 | for (auto& origin_url : origins) { 496 | std::cout << "url:" << origin_url << std::endl; 497 | } 498 | } 499 | 500 | if (option == 10) { 501 | // 对于X4相机 设置预览流,相机里面固定写死的,设置也不会生效 502 | // 对于X3相机,支持 RES_3840_1920P30 和 RES_1440_720P30 503 | // 开启 using_lrv 为true时。获取到的分辨率时1024x512. 504 | ins_camera::LiveStreamParam param; 505 | param.video_resolution = ins_camera::VideoResolution::RES_3840_1920P30; 506 | param.lrv_video_resulution = ins_camera::VideoResolution::RES_1440_720P30; 507 | param.video_bitrate = 1024 * 1024 / 2; 508 | param.enable_audio = false; 509 | param.using_lrv = false; 510 | 511 | auto stream_delegate = std::dynamic_pointer_cast(delegate); 512 | if (stream_delegate) { 513 | stream_delegate->StartStream(); 514 | } 515 | 516 | if (cam->StartLiveStreaming(param)) { 517 | std::cout << "successfully started live stream" << std::endl; 518 | } 519 | } 520 | 521 | if (option == 11) { 522 | if (cam->StopLiveStreaming()) { 523 | auto stream_delegate = std::dynamic_pointer_cast(delegate); 524 | if (stream_delegate) { 525 | stream_delegate->StopStream(); 526 | } 527 | std::cout << "success!" << std::endl; 528 | } 529 | else { 530 | std::cerr << "failed to stop live." << std::endl; 531 | } 532 | } 533 | 534 | if (option == 12) { 535 | if (camera_type < ins_camera::CameraType::Insta360X4) { 536 | std::cout << "In-camera stitching is only supported on X4/X5" << std::endl; 537 | continue; 538 | } 539 | int enable = 0; 540 | std::cout << "In-camera stitching: Enable (1) / Disable (0)?" << std::endl; 541 | std::cin >> enable; 542 | if (cam->EnableInCameraStitching(enable ? true : false)) { 543 | std::cout << "In-camera stitching function activated successfully." << std::endl; 544 | } 545 | } 546 | 547 | if (option == 13) { 548 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 549 | if (exposure_settings) { 550 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 551 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 552 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 553 | std::cout << "mode : " << static_cast(exposure_settings->ExposureMode()) << std::endl; 554 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 555 | } 556 | 557 | auto exposure_mode = exposure_settings->ExposureMode(); 558 | if (exposure_mode != ins_camera::PhotographyOptions_ExposureMode::AUTO && exposure_mode != ins_camera::PhotographyOptions_ExposureMode::FULL_AUTO) { 559 | std::cout << "please switch exposure mode to AUTO mode or FULL_AUTO mode " << std::endl; 560 | continue; 561 | } 562 | 563 | int bias; 564 | std::cout << "please enter EVBIOS: "; 565 | std::cin >> bias; 566 | 567 | exposure_settings->SetEVBias(bias); 568 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 569 | if (ret) { 570 | exposure_settings = cam->GetExposureSettings(FuntionMode); 571 | std::cout << "success! bias " << exposure_settings->EVBias() << std::endl; 572 | } 573 | } 574 | 575 | if (option == 14) { 576 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 577 | if (exposure_settings) { 578 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 579 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 580 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 581 | std::cout << "mode : " << exposure_settings->ExposureMode() << std::endl; 582 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 583 | } 584 | 585 | // ISO只有在手动模式或者优先挡位才可以设置 586 | auto exposure_mode = exposure_settings->ExposureMode(); 587 | if (exposure_mode != ins_camera::PhotographyOptions_ExposureMode::MANUAL && exposure_mode != ins_camera::PhotographyOptions_ExposureMode::ISO_PRIORITY) { 588 | std::cout << "please switch exposure mode to MANUAL mode or ISO_PRIORITY mode " << std::endl; 589 | continue; 590 | } 591 | 592 | int iso; 593 | std::cout << "please enter ISO: "; 594 | std::cin >> iso; 595 | exposure_settings->SetIso(iso); 596 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 597 | if (ret) { 598 | exposure_settings = cam->GetExposureSettings(FuntionMode); 599 | std::cout << "success! ISO " << exposure_settings->Iso() << std::endl; 600 | } 601 | } 602 | 603 | if (option == 15) { 604 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 605 | if (exposure_settings) { 606 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 607 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 608 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 609 | std::cout << "mode : " << exposure_settings->ExposureMode() << std::endl; 610 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 611 | } 612 | 613 | // 快门只有在手动模式或者优先挡位才可以设置 614 | auto exposure_mode = exposure_settings->ExposureMode(); 615 | if (exposure_mode != ins_camera::PhotographyOptions_ExposureMode::MANUAL && exposure_mode != ins_camera::PhotographyOptions_ExposureMode::SHUTTER_PRIORITY) { 616 | std::cout << "please switch exposure mode to MANUAL mode or SHUTTER_PRIORITY mode " << std::endl; 617 | continue; 618 | } 619 | 620 | double speed; 621 | std::cout << "please enter Shutter: "; 622 | std::cin >> speed; 623 | exposure_settings->SetShutterSpeed(speed); 624 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 625 | if (ret) { 626 | exposure_settings = cam->GetExposureSettings(FuntionMode); 627 | std::cout << "success! shutter " << exposure_settings->ShutterSpeed() << std::endl; 628 | } 629 | } 630 | 631 | if (option == 16) { 632 | const auto white_blance_type = ins_camera::CaptureSettings::SettingsType::CaptureSettings_WhiteBalance; 633 | auto capture_settings = cam->GetCaptureSettings(FuntionMode); 634 | if (capture_settings) { 635 | std::cout << "WB : " << capture_settings->GetIntValue(white_blance_type) << std::endl; 636 | } 637 | 638 | int wb; 639 | std::cout << "please enter WB: "; 640 | std::cin >> wb; 641 | capture_settings->SetValue(white_blance_type, wb); 642 | auto ret = cam->SetCaptureSettings(FuntionMode, capture_settings); 643 | if (ret) { 644 | capture_settings = cam->GetCaptureSettings(FuntionMode); 645 | if (capture_settings) { 646 | std::cout << "WB : " << capture_settings->GetIntValue(white_blance_type) << std::endl; 647 | } 648 | } 649 | } 650 | 651 | if (option == 17) { 652 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 653 | if (exposure_settings) { 654 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 655 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 656 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 657 | std::cout << "mode : " << static_cast(exposure_settings->ExposureMode()) << std::endl; 658 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 659 | } 660 | 661 | int mode; 662 | std::cout << "[Auto --------------->(0)]" << std::endl; 663 | std::cout << "[ISO_PRIORITY ------->(1)]" << std::endl; 664 | std::cout << "[SHUTTER_PRIORITY --->(2)]" << std::endl; 665 | std::cout << "[MANUAL ------------->(3)]" << std::endl; 666 | std::cout << "[ADAPTIVE ----------->(4)]" << std::endl; 667 | std::cout << "[FULL_AUTO ---------->(5)]" << std::endl; 668 | std::cout << "please enter mode: "; 669 | std::cin >> mode; 670 | exposure_settings->SetExposureMode(static_cast(mode)); 671 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 672 | if (ret) { 673 | exposure_settings = cam->GetExposureSettings(FuntionMode); 674 | std::cout << "success! mode " << exposure_settings->ExposureMode() << std::endl; 675 | } 676 | } 677 | 678 | if (option == 18) { 679 | auto ret = cam->CaptureCurrentStatus(); 680 | if (ret) { 681 | std::cout << "current statue : capture" << std::endl; 682 | } 683 | else { 684 | std::cout << "current statue : not capture" << std::endl; 685 | } 686 | } 687 | 688 | if (option == 19) { 689 | std::string file_to_save_dir; 690 | std::cout << "please input dir to download: "; 691 | std::cin >> file_to_save_dir; 692 | if (file_to_save_dir.empty()) { 693 | std::cout << "Invalid argument" << std::endl; 694 | continue; 695 | } 696 | 697 | std::replace(file_to_save_dir.begin(), file_to_save_dir.end(), '\\', '/'); 698 | if (!fileIsExist(file_to_save_dir)) { 699 | std::cout << "not exitst: " << file_to_save_dir << std::endl; 700 | continue; 701 | } 702 | 703 | bool ret = cam->SetPhotoSubMode(ins_camera::SubPhotoMode::PHOTO_SINGLE); 704 | if (!ret) { 705 | std::cout << "change sub mode failed!" << std::endl; 706 | continue; 707 | } 708 | 709 | const auto url = cam->TakePhoto(); 710 | if (!url.IsSingleOrigin() || url.Empty()) { 711 | std::cout << "failed to take picture" << std::endl; 712 | continue; 713 | } 714 | 715 | if (!endsWithSlash(file_to_save_dir)) { 716 | file_to_save_dir.append("/"); 717 | } 718 | 719 | const std::string download_url = url.GetSingleOrigin(); 720 | const std::string file_name = GetFileName(download_url); 721 | 722 | std::string save_path = file_to_save_dir + file_name; 723 | ret = cam->DownloadCameraFile(download_url, save_path); 724 | if (ret) { 725 | std::cout << "Download " << download_url << " succeed!!!" << std::endl; 726 | } 727 | else { 728 | std::cout << "Download " << download_url << " failed!!!" << std::endl; 729 | } 730 | std::this_thread::sleep_for(std::chrono::microseconds(1)); 731 | } 732 | 733 | if (option == 20) { 734 | auto ret = cam->StartRecording(); 735 | if (ret) { 736 | std::cerr << "success!" << std::endl; 737 | } 738 | else { 739 | std::cerr << "failed to start recording" << std::endl; 740 | } 741 | } 742 | 743 | if (option == 21) { 744 | ins_camera::BatteryStatus status{}; 745 | bool ret = cam->GetBatteryStatus(status); 746 | if (!ret) { 747 | std::cerr << "GetBatteryStatus failed" << std::endl; 748 | continue; 749 | } 750 | std::cout << "PowerType : " << status.power_type << std::endl; 751 | std::cout << "battery_level : " << status.battery_level << std::endl; 752 | std::cout << "battery_scale : " << status.battery_scale << std::endl; 753 | } 754 | 755 | if (option == 22) { 756 | ins_camera::StorageStatus status{}; 757 | bool ret = cam->GetStorageState(status); 758 | if (!ret) { 759 | std::cerr << "GetBatteryStatus failed" << std::endl; 760 | continue; 761 | } 762 | std::cout << "free_space : " << status.free_space << std::endl; 763 | std::cout << "total_space : " << status.total_space << std::endl; 764 | std::cout << "state : " << status.state << std::endl; 765 | } 766 | 767 | if (option == 23) { 768 | std::vector file_list; 769 | bool ret = cam->GetRecordingFiles(file_list); 770 | if (!ret) { 771 | std::cerr << "GetRecordingFiles failed" << std::endl; 772 | continue; 773 | } 774 | for (auto& file : file_list) { 775 | std::cout << file << std::endl; 776 | } 777 | } 778 | 779 | if (option == 24) { 780 | bool is_connected = cam->IsConnected(); 781 | std::cout << is_connected << std::endl; 782 | } 783 | 784 | if (option == 25) { 785 | const auto url = cam->TakePhoto(); 786 | if (!url.IsSingleOrigin() || url.Empty()) { 787 | std::cout << "failed to take picture" << std::endl; 788 | continue; 789 | } 790 | const std::string download_url = url.GetSingleOrigin(); 791 | std::cout << "url: " << download_url << std::endl; 792 | } 793 | 794 | if (option == 30) { 795 | std::vector file_lists = cam->GetCameraFilesList(); 796 | if (!file_lists.empty()) { 797 | std::string file_to_save_dir; 798 | std::cout << "please input dir to download: "; 799 | std::cin >> file_to_save_dir; 800 | std::replace(file_to_save_dir.begin(), file_to_save_dir.end(), '\\', '/'); 801 | 802 | if (!endsWithSlash(file_to_save_dir)) { 803 | file_to_save_dir.append("/"); 804 | } 805 | 806 | int64_t current_progress = -1; 807 | for (const auto& url : file_lists) { 808 | std::cout << "Download url: " << url << std::endl; 809 | const std::string file_name = GetFileName(url); 810 | std::string save_path = file_to_save_dir + file_name; 811 | int ret = cam->DownloadCameraFile(url, save_path, [&](int64_t current, int64_t total_size) { 812 | const int64_t process = current * 100 / total_size; 813 | if (current_progress != process) { 814 | current_progress = process; 815 | std::cout << "\r"; 816 | std::cout << "process = " << process << "%"; 817 | std::cout << std::flush; 818 | } 819 | }); 820 | std::cout << std::endl; 821 | if (ret) { 822 | std::cout << "Download " << url << " succeed!!!" << std::endl; 823 | } 824 | else { 825 | std::cout << "Download " << url << " failed!!!" << std::endl; 826 | } 827 | } 828 | } 829 | } 830 | 831 | if (option == 31) { 832 | const auto file_list = cam->GetCameraFilesList(); 833 | for (const auto& file : file_list) { 834 | const auto ret = cam->DeleteCameraFile(file); 835 | if (ret) { 836 | std::cout << file << " Deletion succeed" << std::endl; 837 | } 838 | } 839 | } 840 | 841 | if (option == 32) { 842 | ins_camera::RecordParams record_params; 843 | record_params.resolution = ins_camera::VideoResolution::RES_2944_2880P30; 844 | record_params.bitrate = { 1024 * 1024 * 10 }; 845 | auto ret = cam->SetVideoCaptureParams(record_params, ins_camera::CameraFunctionMode::FUNCTION_MODE_MOBILE_TIMELAPSE); 846 | if (!ret) { 847 | std::cout << "failed to set video capture param"; 848 | continue; 849 | } 850 | 851 | ins_camera::TimelapseParam param{}; 852 | param.mode = ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO; 853 | param.duration = -1; 854 | param.lapseTime = 500; 855 | param.accelerate_fequency = 5; 856 | cam->SetTimeLapseOption(param); 857 | 858 | ret = cam->StartTimeLapse(ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO); 859 | if (ret) { 860 | std::this_thread::sleep_for(std::chrono::seconds(60 * 12)); 861 | auto ret1 = cam->StopTimeLapse(ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO); 862 | if (!ret1.Empty()) { 863 | std::cout << "Stop timeLapse succeed!" << std::endl; 864 | } 865 | else { 866 | std::cout << "Stop timeLapse failed!" << std::endl; 867 | } 868 | } 869 | else { 870 | std::cout << "failed to start timeLapse failed!" << std::endl; 871 | } 872 | } 873 | 874 | if (option == 33) { 875 | int count = 0; 876 | auto ret = cam->GetCameraFilesCount(count); 877 | if (ret) { 878 | std::cout << "The count of files is:" << count << std::endl; 879 | } 880 | else { 881 | std::cout << "get files count failed!!!" << std::endl; 882 | } 883 | } 884 | 885 | if (option == 34) { 886 | std::vector photo_size_vec = { ins_camera::PhotoSize::Size_11968_5984 ,ins_camera::PhotoSize::Size_5952_2976 }; 887 | if (camera_type < ins_camera::CameraType::Insta360X4) { 888 | photo_size_vec = { ins_camera::PhotoSize::Size_11968_5984 ,ins_camera::PhotoSize::Size_6912_3456 }; 889 | } 890 | 891 | static int hdr_count = 0; 892 | auto urls = cam->StartHDRCapture(photo_size_vec[(hdr_count++) % 2]); 893 | if (urls.Empty()) { 894 | std::cout << "failed to take picture" << std::endl; 895 | } 896 | else { 897 | for (const auto& url : urls.OriginUrls()) { 898 | std::cout << url << std::endl; 899 | } 900 | } 901 | } 902 | 903 | if (option == 35) { 904 | if (camera_type != ins_camera::CameraType::Insta360X5 && camera_type != ins_camera::CameraType::Insta360X4) { 905 | std::cout << "not support " << std::endl; 906 | } 907 | std::string local_path; 908 | std::cout << "please input full file path to upload: "; 909 | std::cin >> local_path; 910 | if (local_path.empty()) { 911 | std::cout << "Invalid argument" << std::endl; 912 | continue; 913 | } 914 | 915 | if (!fileIsExist(local_path)) { 916 | std::cout << "not exist" << std::endl; 917 | continue; 918 | } 919 | 920 | std::string file_name = "Insta360X4FW.bin"; 921 | if (camera_type == ins_camera::CameraType::Insta360X5) { 922 | file_name = "Insta360X5FW.bin"; 923 | } 924 | 925 | int64_t current_progress = -1; 926 | const auto ret = cam->UploadFile(local_path, file_name, 927 | [&](int64_t total_size, int64_t upload_size) { 928 | const int64_t process = upload_size * 100 / total_size; 929 | if (current_progress != process) { 930 | current_progress = process; 931 | std::cout << "\r"; 932 | std::cout << "process = " << process << "%"; 933 | std::cout << std::flush; 934 | } 935 | }); 936 | std::cout << std::endl; 937 | if (ret) { 938 | std::cout << "Upload " << local_path << " succeed!!!" << std::endl; 939 | } 940 | else { 941 | std::cout << "Upload " << local_path << " failed!!!" << std::endl; 942 | } 943 | cam->Close(); 944 | return 0; 945 | } 946 | 947 | if (option == 36) { 948 | int sensor_device; 949 | std::cout << "FRONT: 1" << std::endl; 950 | std::cout << "REAR: 2" << std::endl; 951 | std::cout << "ALL: 3" << std::endl; 952 | std::cout << "please sensor device index: "; 953 | std::cin >> sensor_device; 954 | if (sensor_device > 3 || sensor_device < 1) { 955 | std::cout << "Invalid argument" << std::endl; 956 | continue; 957 | } 958 | 959 | const auto ret = cam->SetActiveSensor(static_cast(sensor_device)); 960 | if (ret) { 961 | std::cout << "Succeed to set active sensor" << std::endl; 962 | } 963 | else { 964 | std::cout << "failed to set active sensor" << std::endl; 965 | } 966 | } 967 | 968 | if (option == 37) { 969 | auto media_time = cam->GetCameraMediaTime(); 970 | std::cout << "media time : " << media_time << std::endl; 971 | } 972 | 973 | if (option == 38) { 974 | const auto ret = cam->ShutdownCamera(); 975 | if (ret) { 976 | std::cout << "Succeed to shut down camera" << std::endl; 977 | } 978 | break; 979 | } 980 | 981 | if (option == 39) { 982 | const auto log_url = cam->GetCameraLogFileUrl(); 983 | if (log_url.empty()) { 984 | std::cout << "failed to get log url"; 985 | continue; 986 | } 987 | std::cout << "log url: " << log_url << std::endl; 988 | std::string file_to_save_dir; 989 | std::cout << "please input dir to download: "; 990 | std::cin >> file_to_save_dir; 991 | if (file_to_save_dir.empty()) { 992 | std::cout << "Invalid argument" << std::endl; 993 | continue; 994 | } 995 | 996 | std::replace(file_to_save_dir.begin(), file_to_save_dir.end(), '\\', '/'); 997 | if (!fileIsExist(file_to_save_dir)) { 998 | std::cout << "not exitst: " << file_to_save_dir << std::endl; 999 | continue; 1000 | } 1001 | 1002 | std::string log_dir; 1003 | std::string log_file_name; 1004 | parsePath(log_url, log_dir, log_file_name); 1005 | if (!endsWithSlash(file_to_save_dir)) { 1006 | file_to_save_dir.append("/"); 1007 | } 1008 | 1009 | std::string log_save_path = file_to_save_dir + log_file_name; 1010 | 1011 | int64_t current_process = -1; 1012 | const auto ret = cam->DownloadCameraFile(log_url, 1013 | log_save_path, [&](int64_t current, int64_t total_size) { 1014 | const int64_t process = current * 100 / total_size; 1015 | if (process != current_process) { 1016 | std::cout << "\r"; 1017 | std::cout << "process = " << process << "%"; 1018 | std::cout << std::flush; 1019 | } 1020 | }); 1021 | std::cout << std::endl; 1022 | if (ret) { 1023 | std::cout << "Download " << log_save_path << " succeed!!!" << std::endl; 1024 | } 1025 | else { 1026 | std::cout << "Download " << log_save_path << " failed!!!" << std::endl; 1027 | } 1028 | } 1029 | } 1030 | 1031 | cam->Close(); 1032 | return 0; 1033 | } -------------------------------------------------------------------------------- /Demo/Windows/Camera SDK/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef _WIN32 15 | #include 16 | #define ACCESS_FUNC _access 17 | #define F_OK 0 18 | #else 19 | #include 20 | #include 21 | #define ACCESS_FUNC access 22 | #endif 23 | 24 | std::shared_ptr cam = nullptr; 25 | 26 | std::string getCurrentTime() { 27 | const auto now = std::chrono::system_clock::now(); 28 | const std::time_t t = std::chrono::system_clock::to_time_t(now); 29 | std::tm tm{}; 30 | #ifdef WIN32 31 | if (localtime_s(&tm, &t)) 32 | #else 33 | if (localtime_r(&t, &tm)) 34 | #endif 35 | { 36 | } 37 | std::stringstream ss; 38 | ss << std::put_time(&tm, "%Y-%m-%d%H%M%S"); 39 | return ss.str(); 40 | } 41 | 42 | bool fileIsExist(const std::string& file_path) { 43 | return ACCESS_FUNC(file_path.c_str(), F_OK) == 0; 44 | } 45 | 46 | bool endsWithSlash(const std::string& path) { 47 | if (path.empty()) { 48 | return false; 49 | } 50 | return path.back() == '/' || path.back() == '\\'; 51 | } 52 | 53 | void parsePath(const std::string& path, std::string& dir, std::string& filename) { 54 | // 查找最后一个路径分隔符(支持'/'和'\') 55 | size_t lastSlash = path.find_last_of("/\\"); 56 | 57 | if (lastSlash == std::string::npos) { 58 | // 没有找到分隔符,整个字符串作为文件名 59 | dir.clear(); 60 | filename = path; 61 | } 62 | else { 63 | // 分隔符前的部分为路径,包含分隔符 64 | dir = path.substr(0, lastSlash + 1); 65 | // 分隔符后的部分为文件名 66 | filename = path.substr(lastSlash + 1); 67 | } 68 | } 69 | 70 | std::string GetFileName(const std::string& path) { 71 | std::smatch sm; 72 | std::string dir, name; 73 | std::regex_match(path, sm, std::regex("(.+?)([^\\/\\\\]+$)")); 74 | if (sm.size() <= 2) { 75 | return path; 76 | } 77 | return sm[2].str(); 78 | } 79 | 80 | class TestStreamDelegate : public ins_camera::StreamDelegate { 81 | public: 82 | TestStreamDelegate() = default; 83 | 84 | virtual ~TestStreamDelegate() { 85 | StopStream(); 86 | } 87 | 88 | void OnAudioData(const uint8_t* data, size_t size, int64_t timestamp) override { 89 | } 90 | 91 | void OnVideoData(const uint8_t* data, size_t size, int64_t timestamp, uint8_t streamType, int stream_index) override { 92 | if (stream_index == 0 && fp1) { 93 | fwrite(data, size, 1, fp1); 94 | } 95 | if (stream_index == 1 && fp2) { 96 | fwrite(data, size, 1, fp2); 97 | } 98 | } 99 | 100 | void OnGyroData(const std::vector& data) override {} 101 | 102 | void OnExposureData(const ins_camera::ExposureData& data) override {} 103 | 104 | void StopStream() { 105 | if (fp1) { 106 | fclose(fp1); 107 | fp1 = nullptr; 108 | } 109 | 110 | if (fp2) { 111 | fclose(fp2); 112 | fp2 = nullptr; 113 | } 114 | } 115 | 116 | void StartStream() { 117 | StopStream(); 118 | const std::string cur_time = getCurrentTime(); 119 | const std::string stream_1 = std::string("./01_") + cur_time + std::string(".h264"); 120 | const std::string stream_2 = std::string("./02_") + cur_time + std::string(".h264"); 121 | #ifdef WIN32 122 | const errno_t err1 = fopen_s(&fp1, stream_1.c_str(), "wb"); 123 | if (err1 != 0) { 124 | std::cerr << "failed to create file " << std::endl; 125 | } 126 | const errno_t err2 = fopen_s(&fp2, stream_2.c_str(), "wb"); 127 | if (err2 != 0) { 128 | std::cerr << "failed to create file " << std::endl; 129 | } 130 | #else 131 | fp1 = fopen(stream_1.c_str(), "wb"); 132 | fp2 = fopen(stream_2.c_str(), "wb"); 133 | #endif 134 | } 135 | 136 | private: 137 | FILE* fp1 = nullptr; 138 | FILE* fp2 = nullptr; 139 | }; 140 | 141 | void signalHandle(int sig) { 142 | if (sig == SIGINT || sig == SIGTERM) { 143 | std::cout << "signal handler: " << sig << std::endl; 144 | if (cam) { 145 | cam->Close(); 146 | } 147 | } 148 | } 149 | 150 | int main(int argc, char* argv[]) { 151 | (void)(signal(SIGINT, signalHandle)); 152 | (void)(signal(SIGTERM, signalHandle)); 153 | 154 | std::cout << "begin open camera" << std::endl; 155 | ins_camera::SetLogLevel(ins_camera::LogLevel::ERR); 156 | for (int i = 1; i < argc; i++) { 157 | const std::string arg = argv[i]; 158 | if (arg == std::string("--debug")) { 159 | ins_camera::SetLogLevel(ins_camera::LogLevel::VERBOSE); 160 | } 161 | else if (arg == std::string("--log_file")) { 162 | const std::string log_file = argv[++i]; 163 | ins_camera::SetLogPath(log_file); 164 | } 165 | } 166 | 167 | ins_camera::DeviceDiscovery discovery; 168 | auto list = discovery.GetAvailableDevices(); 169 | if (list.empty()) { 170 | std::cerr << "no device found." << std::endl; 171 | return -1; 172 | } 173 | 174 | for (const auto& camera : list) { 175 | std::cout << "serial:" << camera.serial_number << "\t" 176 | << ";camera type:" << camera.camera_name << "\t" 177 | << ";fw version:" << camera.fw_version << "\t" 178 | << std::endl; 179 | } 180 | 181 | cam = std::make_shared(list[0].info); 182 | if (!cam->Open()) { 183 | std::cerr << "failed to open camera" << std::endl; 184 | return -1; 185 | } 186 | 187 | const auto camera_type = list[0].camera_type; 188 | const auto serial_number = list[0].serial_number; 189 | 190 | discovery.FreeDeviceDescriptors(list); 191 | 192 | std::shared_ptr delegate = std::make_shared(); 193 | cam->SetStreamDelegate(delegate); 194 | 195 | std::cout << "Succeed to open camera..." << std::endl; 196 | 197 | std::cout << "Usage:" << std::endl; 198 | std::cout << "1: get file list(only video and photo)" << std::endl; 199 | std::cout << "2: delete file" << std::endl; 200 | std::cout << "3: download file" << std::endl; 201 | std::cout << "4: switch video mode" << std::endl; 202 | std::cout << "5: switch photo mode" << std::endl; 203 | std::cout << "6: start normal video mode recording" << std::endl; 204 | std::cout << "7: stop recording" << std::endl; 205 | std::cout << "8: start timelapse " << std::endl; 206 | std::cout << "9: stop timelapse " << std::endl; 207 | std::cout << "10: start preview live streaming:" << std::endl; 208 | std::cout << "11: stop preview live streaming:" << std::endl; 209 | std::cout << "12: enable In-camera stitching (Compatible with X4 and later camera only)" << std::endl; 210 | std::cout << "13: set EV" << std::endl; 211 | std::cout << "14: set ISO" << std::endl; 212 | std::cout << "15: set shutter" << std::endl; 213 | std::cout << "16: set WB" << std::endl; 214 | std::cout << "17: set expouse mode:" << std::endl; 215 | std::cout << "18: get current capture status " << std::endl; 216 | std::cout << "19: test take photo and download " << std::endl; 217 | std::cout << "20: start recording " << std::endl; 218 | std::cout << "21: get battery info " << std::endl; 219 | std::cout << "22: get storage info " << std::endl; 220 | std::cout << "23: get recording file " << std::endl; 221 | std::cout << "24: Check if the camera is still connected" << std::endl; 222 | std::cout << "25: take photo " << std::endl; 223 | std::cout << "30: batch download list files " << std::endl; 224 | std::cout << "31: delete camera all files " << std::endl; 225 | std::cout << "34: start hdr capture " << std::endl; 226 | std::cout << "33: get file list count " << std::endl; 227 | std::cout << "35: upload Firmware (Compatible with X4 and later camera only)" << std::endl; 228 | std::cout << "36: set active sensor (switch lens)" << std::endl; 229 | std::cout << "37: get media time from camera " << std::endl; 230 | std::cout << "38: Shutdown camera " << std::endl; 231 | std::cout << "39: Get camera log" << std::endl; 232 | std::cout << "0: exit" << std::endl; 233 | 234 | time_t now = time(nullptr); 235 | std::tm tm{}; 236 | time_t time_seconds = now; 237 | #ifdef WIN32 238 | (void)(localtime_s(&tm, &now)); 239 | time_seconds = _mkgmtime(&tm); 240 | #else 241 | localtime_r(&now, &tm); 242 | time_seconds = timegm(&tm); 243 | #endif 244 | 245 | std::cout << "UTC time: " << now << std::endl; 246 | std::cout << "GMT time: " << time_seconds << std::endl; 247 | cam->SyncLocalTimeToCamera(time_seconds); 248 | 249 | /*************************demo for 普通照片72MP和 HDR录制5.7K******************/ 250 | //cam->SetPhotoSize(ins_camera::FUNCTION_MODE_NORMAL_IMAGE, ins_camera::PhotoSize::Size_6912_3456); 251 | //ins_camera::RecordParams record_params_test; 252 | //record_params_test.resolution = ins_camera::VideoResolution::RES_2880_2880P30; 253 | //cam->SetVideoCaptureParams(record_params_test, ins_camera::CameraFunctionMode::FUNCTION_MODE_HDR_VIDEO); 254 | /*************************demo for 普通照片72MP和 HDR录制5.7K******************/ 255 | 256 | ins_camera::CameraFunctionMode FuntionMode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 257 | 258 | int option = 0; 259 | while (true) { 260 | std::cout << "please enter index: "; 261 | std::cin >> option; 262 | if (option < 0 || option > 39) { 263 | std::cout << "Invalid index" << std::endl; 264 | continue; 265 | } 266 | 267 | if (option == 0) { 268 | break; 269 | } 270 | 271 | if (option == 1) { 272 | const auto file_list = cam->GetCameraFilesList(); 273 | for (const auto& file : file_list) { 274 | std::cout << "File: " << file << std::endl; 275 | } 276 | } 277 | 278 | if (option == 2) { 279 | const auto file_list = cam->GetCameraFilesList(); 280 | for (const auto& file : file_list) { 281 | std::cout << "File: " << file << std::endl; 282 | } 283 | 284 | std::string file_to_delete; 285 | std::cout << "please input full file path to delete: "; 286 | std::cin >> file_to_delete; 287 | if (file_to_delete.empty()) { 288 | std::cout << "Invalid argument" << std::endl; 289 | continue; 290 | } 291 | 292 | auto exist = std::find_if(file_list.begin(), file_list.end(), [file_to_delete](const std::string& file) 293 | { 294 | return file_to_delete == file; 295 | }) != file_list.end(); 296 | 297 | if (!exist) { 298 | std::cout << "the file that deleted is not exist " << std::endl; 299 | continue; 300 | } 301 | 302 | const auto ret = cam->DeleteCameraFile(file_to_delete); 303 | if (ret) { 304 | std::cout << "deleted succeed" << std::endl; 305 | } 306 | } 307 | 308 | if (option == 3) { 309 | const auto file_list = cam->GetCameraFilesList(); 310 | for (const auto& file : file_list) { 311 | std::cout << "File: " << file << std::endl; 312 | } 313 | 314 | std::string file_to_download; 315 | std::string file_to_save; 316 | std::cout << "please input full file path to download: "; 317 | std::cin >> file_to_download; 318 | 319 | bool exist = std::find_if(file_list.begin(), file_list.end(), [file_to_download](const std::string& file) 320 | { 321 | return file_to_download == file; 322 | }) != file_list.end(); 323 | 324 | if (!exist) { 325 | std::cout << "the file that deleted is not exist " << std::endl; 326 | continue; 327 | } 328 | 329 | std::cout << "please input full file path to save: "; 330 | std::cin >> file_to_save; 331 | 332 | std::string file_to_save_dir; 333 | std::string file_to_save_file_name; 334 | parsePath(file_to_save, file_to_save_dir, file_to_save_file_name); 335 | if (!fileIsExist(file_to_save_dir)) { 336 | std::cout << "dir is not exist, please create it: " << file_to_save_dir << std::endl; 337 | continue; 338 | } 339 | 340 | if (file_to_save_file_name.empty()) { 341 | std::cout << "please input file name" << std::endl; 342 | continue; 343 | } 344 | 345 | int64_t current_process = -1; 346 | const auto ret = cam->DownloadCameraFile(file_to_download, 347 | file_to_save, [&](int64_t current, int64_t total_size) { 348 | const int64_t process = current * 100 / total_size; 349 | if (process != current_process) { 350 | std::cout << "\r"; 351 | std::cout << "process = " << process << "%"; 352 | std::cout << std::flush; 353 | } 354 | }); 355 | std::cout << std::endl; 356 | if (ret) { 357 | std::cout << "Download " << file_to_download << " succeed!!!" << std::endl; 358 | } 359 | else { 360 | std::cout << "Download " << file_to_download << " failed!!!" << std::endl; 361 | } 362 | } 363 | 364 | if (option == 4) { 365 | std::vector support_mode = { 0,2,3,4,11 }; 366 | std::cout << "normal video [0]" << std::endl; 367 | std::cout << "timeplase video [2]" << std::endl; 368 | std::cout << "hdr video [3]" << std::endl; 369 | std::cout << "timeshift video [4]" << std::endl; 370 | std::cout << "pure video [11]" << std::endl; 371 | int video_mode = 0; 372 | std::cout << "Please enter the video mode: "; 373 | std::cin >> video_mode; 374 | if (std::find(support_mode.begin(), support_mode.end(), video_mode) == support_mode.end()) { 375 | std::cerr << "The input video mode is not supported" << std::endl; 376 | continue; 377 | } 378 | bool ret = cam->SetVideoSubMode(static_cast(video_mode)); 379 | if (ret) { 380 | std::cout << "Change Sub mode Succeed!" << std::endl; 381 | } 382 | else { 383 | std::cout << "Change Sub mode Failed!" << std::endl; 384 | } 385 | } 386 | 387 | if (option == 5) { 388 | std::cout << "normal photo [0]" << std::endl; 389 | std::cout << "HDR photo [1]" << std::endl; 390 | std::cout << "INTERVAL photo [2]" << std::endl; 391 | 392 | int photo_mode = 0; 393 | std::cout << "Please enter the photo mode: "; 394 | std::cin >> photo_mode; 395 | if (photo_mode > 7) { 396 | std::cerr << "The input photo mode is not supported" << std::endl; 397 | continue; 398 | } 399 | bool ret = cam->SetPhotoSubMode(static_cast(photo_mode)); 400 | if (ret) { 401 | std::cout << "Change Sub mode Succeed!" << std::endl; 402 | } 403 | else { 404 | std::cout << "Change Sub mode Failed!" << std::endl; 405 | } 406 | } 407 | 408 | if (option == 6) { 409 | bool ret = cam->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_NORMAL); 410 | if (!ret) { 411 | std::cout << "change sub mode failed!" << std::endl; 412 | continue; 413 | } 414 | 415 | ins_camera::RecordParams record_params; 416 | record_params.resolution = ins_camera::VideoResolution::RES_3840_3840P30; 417 | record_params.bitrate = 1024 * 1024 * 10; 418 | if (!cam->SetVideoCaptureParams(record_params, ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_VIDEO)) { 419 | std::cerr << "failed to set capture settings." << std::endl; 420 | } 421 | else { 422 | ret = cam->StartRecording(); 423 | if (ret) { 424 | std::cerr << "success!" << std::endl; 425 | } 426 | else { 427 | std::cerr << "failed to start recording" << std::endl; 428 | } 429 | } 430 | } 431 | 432 | if (option == 7) { 433 | auto url = cam->StopRecording(); 434 | if (url.Empty()) { 435 | std::cerr << "stop recording failed" << std::endl; 436 | continue; 437 | } 438 | auto& origins = url.OriginUrls(); 439 | std::cout << "stop recording success" << std::endl; 440 | for (auto& origin_url : origins) { 441 | std::cout << "url:" << origin_url << std::endl; 442 | } 443 | } 444 | 445 | if (option == 8) { 446 | bool ret = cam->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_TIMELAPSE); 447 | if (!ret) { 448 | std::cout << "change sub mode failed!" << std::endl; 449 | continue; 450 | } 451 | 452 | // 11K30 RES_5632_5632P30 453 | // 8K RES_3840_3840P30 454 | // 5.7K RES_2880_2880P30 455 | // X4支持11K30, X3不支持 456 | std::vector support_list = { 457 | ins_camera::VideoResolution::RES_5632_5632P30, 458 | ins_camera::VideoResolution::RES_3840_3840P30, 459 | ins_camera::VideoResolution::RES_2880_2880P30 460 | }; 461 | 462 | static int count = 0; 463 | ins_camera::RecordParams record_params; 464 | record_params.resolution = support_list[(count++) % 3]; 465 | if (!cam->SetVideoCaptureParams(record_params, ins_camera::CameraFunctionMode::FUNCTION_MODE_MOBILE_TIMELAPSE)) { 466 | std::cerr << "failed to set capture settings." << std::endl; 467 | break; 468 | } 469 | 470 | //mode 是你相机所支持的模式 471 | ins_camera::TimelapseParam param = { ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO, 10,5000,5 }; 472 | if (!cam->SetTimeLapseOption(param)) { 473 | std::cerr << "failed to set capture settings." << std::endl; 474 | } 475 | else { 476 | ret = cam->StartTimeLapse(param.mode); 477 | if (ret) { 478 | std::cerr << "success!" << std::endl; 479 | } 480 | else { 481 | std::cerr << "failed to start timelapse" << std::endl; 482 | } 483 | } 484 | } 485 | 486 | if (option == 9) { 487 | auto url = cam->StopTimeLapse(ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO); 488 | if (url.Empty()) { 489 | std::cerr << "stop timelapse failed" << std::endl; 490 | continue; 491 | } 492 | 493 | std::cout << "stop timelapse success" << std::endl; 494 | auto& origins = url.OriginUrls(); 495 | for (auto& origin_url : origins) { 496 | std::cout << "url:" << origin_url << std::endl; 497 | } 498 | } 499 | 500 | if (option == 10) { 501 | // 对于X4相机 设置预览流,相机里面固定写死的,设置也不会生效 502 | // 对于X3相机,支持 RES_3840_1920P30 和 RES_1440_720P30 503 | // 开启 using_lrv 为true时。获取到的分辨率时1024x512. 504 | ins_camera::LiveStreamParam param; 505 | param.video_resolution = ins_camera::VideoResolution::RES_3840_1920P30; 506 | param.lrv_video_resulution = ins_camera::VideoResolution::RES_1440_720P30; 507 | param.video_bitrate = 1024 * 1024 / 2; 508 | param.enable_audio = false; 509 | param.using_lrv = false; 510 | 511 | auto stream_delegate = std::dynamic_pointer_cast(delegate); 512 | if (stream_delegate) { 513 | stream_delegate->StartStream(); 514 | } 515 | 516 | if (cam->StartLiveStreaming(param)) { 517 | std::cout << "successfully started live stream" << std::endl; 518 | } 519 | } 520 | 521 | if (option == 11) { 522 | if (cam->StopLiveStreaming()) { 523 | auto stream_delegate = std::dynamic_pointer_cast(delegate); 524 | if (stream_delegate) { 525 | stream_delegate->StopStream(); 526 | } 527 | std::cout << "success!" << std::endl; 528 | } 529 | else { 530 | std::cerr << "failed to stop live." << std::endl; 531 | } 532 | } 533 | 534 | if (option == 12) { 535 | if (camera_type < ins_camera::CameraType::Insta360X4) { 536 | std::cout << "In-camera stitching is only supported on X4/X5" << std::endl; 537 | continue; 538 | } 539 | int enable = 0; 540 | std::cout << "In-camera stitching: Enable (1) / Disable (0)?" << std::endl; 541 | std::cin >> enable; 542 | if (cam->EnableInCameraStitching(enable ? true : false)) { 543 | std::cout << "In-camera stitching function activated successfully." << std::endl; 544 | } 545 | } 546 | 547 | if (option == 13) { 548 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 549 | if (exposure_settings) { 550 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 551 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 552 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 553 | std::cout << "mode : " << static_cast(exposure_settings->ExposureMode()) << std::endl; 554 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 555 | } 556 | 557 | auto exposure_mode = exposure_settings->ExposureMode(); 558 | if (exposure_mode != ins_camera::PhotographyOptions_ExposureMode::AUTO && exposure_mode != ins_camera::PhotographyOptions_ExposureMode::FULL_AUTO) { 559 | std::cout << "please switch exposure mode to AUTO mode or FULL_AUTO mode " << std::endl; 560 | continue; 561 | } 562 | 563 | int bias; 564 | std::cout << "please enter EVBIOS: "; 565 | std::cin >> bias; 566 | 567 | exposure_settings->SetEVBias(bias); 568 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 569 | if (ret) { 570 | exposure_settings = cam->GetExposureSettings(FuntionMode); 571 | std::cout << "success! bias " << exposure_settings->EVBias() << std::endl; 572 | } 573 | } 574 | 575 | if (option == 14) { 576 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 577 | if (exposure_settings) { 578 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 579 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 580 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 581 | std::cout << "mode : " << exposure_settings->ExposureMode() << std::endl; 582 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 583 | } 584 | 585 | // ISO只有在手动模式或者优先挡位才可以设置 586 | auto exposure_mode = exposure_settings->ExposureMode(); 587 | if (exposure_mode != ins_camera::PhotographyOptions_ExposureMode::MANUAL && exposure_mode != ins_camera::PhotographyOptions_ExposureMode::ISO_PRIORITY) { 588 | std::cout << "please switch exposure mode to MANUAL mode or ISO_PRIORITY mode " << std::endl; 589 | continue; 590 | } 591 | 592 | int iso; 593 | std::cout << "please enter ISO: "; 594 | std::cin >> iso; 595 | exposure_settings->SetIso(iso); 596 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 597 | if (ret) { 598 | exposure_settings = cam->GetExposureSettings(FuntionMode); 599 | std::cout << "success! ISO " << exposure_settings->Iso() << std::endl; 600 | } 601 | } 602 | 603 | if (option == 15) { 604 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 605 | if (exposure_settings) { 606 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 607 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 608 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 609 | std::cout << "mode : " << exposure_settings->ExposureMode() << std::endl; 610 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 611 | } 612 | 613 | // 快门只有在手动模式或者优先挡位才可以设置 614 | auto exposure_mode = exposure_settings->ExposureMode(); 615 | if (exposure_mode != ins_camera::PhotographyOptions_ExposureMode::MANUAL && exposure_mode != ins_camera::PhotographyOptions_ExposureMode::SHUTTER_PRIORITY) { 616 | std::cout << "please switch exposure mode to MANUAL mode or SHUTTER_PRIORITY mode " << std::endl; 617 | continue; 618 | } 619 | 620 | double speed; 621 | std::cout << "please enter Shutter: "; 622 | std::cin >> speed; 623 | exposure_settings->SetShutterSpeed(speed); 624 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 625 | if (ret) { 626 | exposure_settings = cam->GetExposureSettings(FuntionMode); 627 | std::cout << "success! shutter " << exposure_settings->ShutterSpeed() << std::endl; 628 | } 629 | } 630 | 631 | if (option == 16) { 632 | const auto white_blance_type = ins_camera::CaptureSettings::SettingsType::CaptureSettings_WhiteBalance; 633 | auto capture_settings = cam->GetCaptureSettings(FuntionMode); 634 | if (capture_settings) { 635 | std::cout << "WB : " << capture_settings->GetIntValue(white_blance_type) << std::endl; 636 | } 637 | 638 | int wb; 639 | std::cout << "please enter WB: "; 640 | std::cin >> wb; 641 | capture_settings->SetValue(white_blance_type, wb); 642 | auto ret = cam->SetCaptureSettings(FuntionMode, capture_settings); 643 | if (ret) { 644 | capture_settings = cam->GetCaptureSettings(FuntionMode); 645 | if (capture_settings) { 646 | std::cout << "WB : " << capture_settings->GetIntValue(white_blance_type) << std::endl; 647 | } 648 | } 649 | } 650 | 651 | if (option == 17) { 652 | auto exposure_settings = cam->GetExposureSettings(FuntionMode); 653 | if (exposure_settings) { 654 | std::cout << "EVBias : " << exposure_settings->EVBias() << std::endl; 655 | std::cout << "ISO : " << exposure_settings->Iso() << std::endl; 656 | std::cout << "speed : " << exposure_settings->ShutterSpeed() << std::endl; 657 | std::cout << "mode : " << static_cast(exposure_settings->ExposureMode()) << std::endl; 658 | std::cout << "videoISOLimit: " << exposure_settings->VideoISOTopLimit() << std::endl; 659 | } 660 | 661 | int mode; 662 | std::cout << "[Auto --------------->(0)]" << std::endl; 663 | std::cout << "[ISO_PRIORITY ------->(1)]" << std::endl; 664 | std::cout << "[SHUTTER_PRIORITY --->(2)]" << std::endl; 665 | std::cout << "[MANUAL ------------->(3)]" << std::endl; 666 | std::cout << "[ADAPTIVE ----------->(4)]" << std::endl; 667 | std::cout << "[FULL_AUTO ---------->(5)]" << std::endl; 668 | std::cout << "please enter mode: "; 669 | std::cin >> mode; 670 | exposure_settings->SetExposureMode(static_cast(mode)); 671 | auto ret = cam->SetExposureSettings(FuntionMode, exposure_settings); 672 | if (ret) { 673 | exposure_settings = cam->GetExposureSettings(FuntionMode); 674 | std::cout << "success! mode " << exposure_settings->ExposureMode() << std::endl; 675 | } 676 | } 677 | 678 | if (option == 18) { 679 | auto ret = cam->CaptureCurrentStatus(); 680 | if (ret) { 681 | std::cout << "current statue : capture" << std::endl; 682 | } 683 | else { 684 | std::cout << "current statue : not capture" << std::endl; 685 | } 686 | } 687 | 688 | if (option == 19) { 689 | std::string file_to_save_dir; 690 | std::cout << "please input dir to download: "; 691 | std::cin >> file_to_save_dir; 692 | if (file_to_save_dir.empty()) { 693 | std::cout << "Invalid argument" << std::endl; 694 | continue; 695 | } 696 | 697 | std::replace(file_to_save_dir.begin(), file_to_save_dir.end(), '\\', '/'); 698 | if (!fileIsExist(file_to_save_dir)) { 699 | std::cout << "not exitst: " << file_to_save_dir << std::endl; 700 | continue; 701 | } 702 | 703 | bool ret = cam->SetPhotoSubMode(ins_camera::SubPhotoMode::PHOTO_SINGLE); 704 | if (!ret) { 705 | std::cout << "change sub mode failed!" << std::endl; 706 | continue; 707 | } 708 | 709 | const auto url = cam->TakePhoto(); 710 | if (!url.IsSingleOrigin() || url.Empty()) { 711 | std::cout << "failed to take picture" << std::endl; 712 | continue; 713 | } 714 | 715 | if (!endsWithSlash(file_to_save_dir)) { 716 | file_to_save_dir.append("/"); 717 | } 718 | 719 | const std::string download_url = url.GetSingleOrigin(); 720 | const std::string file_name = GetFileName(download_url); 721 | 722 | std::string save_path = file_to_save_dir + file_name; 723 | ret = cam->DownloadCameraFile(download_url, save_path); 724 | if (ret) { 725 | std::cout << "Download " << download_url << " succeed!!!" << std::endl; 726 | } 727 | else { 728 | std::cout << "Download " << download_url << " failed!!!" << std::endl; 729 | } 730 | std::this_thread::sleep_for(std::chrono::microseconds(1)); 731 | } 732 | 733 | if (option == 20) { 734 | auto ret = cam->StartRecording(); 735 | if (ret) { 736 | std::cerr << "success!" << std::endl; 737 | } 738 | else { 739 | std::cerr << "failed to start recording" << std::endl; 740 | } 741 | } 742 | 743 | if (option == 21) { 744 | ins_camera::BatteryStatus status{}; 745 | bool ret = cam->GetBatteryStatus(status); 746 | if (!ret) { 747 | std::cerr << "GetBatteryStatus failed" << std::endl; 748 | continue; 749 | } 750 | std::cout << "PowerType : " << status.power_type << std::endl; 751 | std::cout << "battery_level : " << status.battery_level << std::endl; 752 | std::cout << "battery_scale : " << status.battery_scale << std::endl; 753 | } 754 | 755 | if (option == 22) { 756 | ins_camera::StorageStatus status{}; 757 | bool ret = cam->GetStorageState(status); 758 | if (!ret) { 759 | std::cerr << "GetBatteryStatus failed" << std::endl; 760 | continue; 761 | } 762 | std::cout << "free_space : " << status.free_space << std::endl; 763 | std::cout << "total_space : " << status.total_space << std::endl; 764 | std::cout << "state : " << status.state << std::endl; 765 | } 766 | 767 | if (option == 23) { 768 | std::vector file_list; 769 | bool ret = cam->GetRecordingFiles(file_list); 770 | if (!ret) { 771 | std::cerr << "GetRecordingFiles failed" << std::endl; 772 | continue; 773 | } 774 | for (auto& file : file_list) { 775 | std::cout << file << std::endl; 776 | } 777 | } 778 | 779 | if (option == 24) { 780 | bool is_connected = cam->IsConnected(); 781 | std::cout << is_connected << std::endl; 782 | } 783 | 784 | if (option == 25) { 785 | const auto url = cam->TakePhoto(); 786 | if (!url.IsSingleOrigin() || url.Empty()) { 787 | std::cout << "failed to take picture" << std::endl; 788 | continue; 789 | } 790 | const std::string download_url = url.GetSingleOrigin(); 791 | std::cout << "url: " << download_url << std::endl; 792 | } 793 | 794 | if (option == 30) { 795 | std::vector file_lists = cam->GetCameraFilesList(); 796 | if (!file_lists.empty()) { 797 | std::string file_to_save_dir; 798 | std::cout << "please input dir to download: "; 799 | std::cin >> file_to_save_dir; 800 | std::replace(file_to_save_dir.begin(), file_to_save_dir.end(), '\\', '/'); 801 | 802 | if (!endsWithSlash(file_to_save_dir)) { 803 | file_to_save_dir.append("/"); 804 | } 805 | 806 | int64_t current_progress = -1; 807 | for (const auto& url : file_lists) { 808 | std::cout << "Download url: " << url << std::endl; 809 | const std::string file_name = GetFileName(url); 810 | std::string save_path = file_to_save_dir + file_name; 811 | int ret = cam->DownloadCameraFile(url, save_path, [&](int64_t current, int64_t total_size) { 812 | const int64_t process = current * 100 / total_size; 813 | if (current_progress != process) { 814 | current_progress = process; 815 | std::cout << "\r"; 816 | std::cout << "process = " << process << "%"; 817 | std::cout << std::flush; 818 | } 819 | }); 820 | std::cout << std::endl; 821 | if (ret) { 822 | std::cout << "Download " << url << " succeed!!!" << std::endl; 823 | } 824 | else { 825 | std::cout << "Download " << url << " failed!!!" << std::endl; 826 | } 827 | } 828 | } 829 | } 830 | 831 | if (option == 31) { 832 | const auto file_list = cam->GetCameraFilesList(); 833 | for (const auto& file : file_list) { 834 | const auto ret = cam->DeleteCameraFile(file); 835 | if (ret) { 836 | std::cout << file << " Deletion succeed" << std::endl; 837 | } 838 | } 839 | } 840 | 841 | if (option == 32) { 842 | ins_camera::RecordParams record_params; 843 | record_params.resolution = ins_camera::VideoResolution::RES_2944_2880P30; 844 | record_params.bitrate = { 1024 * 1024 * 10 }; 845 | auto ret = cam->SetVideoCaptureParams(record_params, ins_camera::CameraFunctionMode::FUNCTION_MODE_MOBILE_TIMELAPSE); 846 | if (!ret) { 847 | std::cout << "failed to set video capture param"; 848 | continue; 849 | } 850 | 851 | ins_camera::TimelapseParam param{}; 852 | param.mode = ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO; 853 | param.duration = -1; 854 | param.lapseTime = 500; 855 | param.accelerate_fequency = 5; 856 | cam->SetTimeLapseOption(param); 857 | 858 | ret = cam->StartTimeLapse(ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO); 859 | if (ret) { 860 | std::this_thread::sleep_for(std::chrono::seconds(60 * 12)); 861 | auto ret1 = cam->StopTimeLapse(ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO); 862 | if (!ret1.Empty()) { 863 | std::cout << "Stop timeLapse succeed!" << std::endl; 864 | } 865 | else { 866 | std::cout << "Stop timeLapse failed!" << std::endl; 867 | } 868 | } 869 | else { 870 | std::cout << "failed to start timeLapse failed!" << std::endl; 871 | } 872 | } 873 | 874 | if (option == 33) { 875 | int count = 0; 876 | auto ret = cam->GetCameraFilesCount(count); 877 | if (ret) { 878 | std::cout << "The count of files is:" << count << std::endl; 879 | } 880 | else { 881 | std::cout << "get files count failed!!!" << std::endl; 882 | } 883 | } 884 | 885 | if (option == 34) { 886 | std::vector photo_size_vec = { ins_camera::PhotoSize::Size_11968_5984 ,ins_camera::PhotoSize::Size_5952_2976 }; 887 | if (camera_type < ins_camera::CameraType::Insta360X4) { 888 | photo_size_vec = { ins_camera::PhotoSize::Size_11968_5984 ,ins_camera::PhotoSize::Size_6912_3456 }; 889 | } 890 | 891 | static int hdr_count = 0; 892 | auto urls = cam->StartHDRCapture(photo_size_vec[(hdr_count++) % 2]); 893 | if (urls.Empty()) { 894 | std::cout << "failed to take picture" << std::endl; 895 | } 896 | else { 897 | for (const auto& url : urls.OriginUrls()) { 898 | std::cout << url << std::endl; 899 | } 900 | } 901 | } 902 | 903 | if (option == 35) { 904 | if (camera_type != ins_camera::CameraType::Insta360X5 && camera_type != ins_camera::CameraType::Insta360X4) { 905 | std::cout << "not support " << std::endl; 906 | } 907 | std::string local_path; 908 | std::cout << "please input full file path to upload: "; 909 | std::cin >> local_path; 910 | if (local_path.empty()) { 911 | std::cout << "Invalid argument" << std::endl; 912 | continue; 913 | } 914 | 915 | if (!fileIsExist(local_path)) { 916 | std::cout << "not exist" << std::endl; 917 | continue; 918 | } 919 | 920 | std::string file_name = "Insta360X4FW.bin"; 921 | if (camera_type == ins_camera::CameraType::Insta360X5) { 922 | file_name = "Insta360X5FW.bin"; 923 | } 924 | 925 | int64_t current_progress = -1; 926 | const auto ret = cam->UploadFile(local_path, file_name, 927 | [&](int64_t total_size, int64_t upload_size) { 928 | const int64_t process = upload_size * 100 / total_size; 929 | if (current_progress != process) { 930 | current_progress = process; 931 | std::cout << "\r"; 932 | std::cout << "process = " << process << "%"; 933 | std::cout << std::flush; 934 | } 935 | }); 936 | std::cout << std::endl; 937 | if (ret) { 938 | std::cout << "Upload " << local_path << " succeed!!!" << std::endl; 939 | } 940 | else { 941 | std::cout << "Upload " << local_path << " failed!!!" << std::endl; 942 | } 943 | cam->Close(); 944 | return 0; 945 | } 946 | 947 | if (option == 36) { 948 | int sensor_device; 949 | std::cout << "FRONT: 1" << std::endl; 950 | std::cout << "REAR: 2" << std::endl; 951 | std::cout << "ALL: 3" << std::endl; 952 | std::cout << "please sensor device index: "; 953 | std::cin >> sensor_device; 954 | if (sensor_device > 3 || sensor_device < 1) { 955 | std::cout << "Invalid argument" << std::endl; 956 | continue; 957 | } 958 | 959 | const auto ret = cam->SetActiveSensor(static_cast(sensor_device)); 960 | if (ret) { 961 | std::cout << "Succeed to set active sensor" << std::endl; 962 | } 963 | else { 964 | std::cout << "failed to set active sensor" << std::endl; 965 | } 966 | } 967 | 968 | if (option == 37) { 969 | auto media_time = cam->GetCameraMediaTime(); 970 | std::cout << "media time : " << media_time << std::endl; 971 | } 972 | 973 | if (option == 38) { 974 | const auto ret = cam->ShutdownCamera(); 975 | if (ret) { 976 | std::cout << "Succeed to shut down camera" << std::endl; 977 | } 978 | break; 979 | } 980 | 981 | if (option == 39) { 982 | const auto log_url = cam->GetCameraLogFileUrl(); 983 | if (log_url.empty()) { 984 | std::cout << "failed to get log url"; 985 | continue; 986 | } 987 | std::cout << "log url: " << log_url << std::endl; 988 | std::string file_to_save_dir; 989 | std::cout << "please input dir to download: "; 990 | std::cin >> file_to_save_dir; 991 | if (file_to_save_dir.empty()) { 992 | std::cout << "Invalid argument" << std::endl; 993 | continue; 994 | } 995 | 996 | std::replace(file_to_save_dir.begin(), file_to_save_dir.end(), '\\', '/'); 997 | if (!fileIsExist(file_to_save_dir)) { 998 | std::cout << "not exitst: " << file_to_save_dir << std::endl; 999 | continue; 1000 | } 1001 | 1002 | std::string log_dir; 1003 | std::string log_file_name; 1004 | parsePath(log_url, log_dir, log_file_name); 1005 | if (!endsWithSlash(file_to_save_dir)) { 1006 | file_to_save_dir.append("/"); 1007 | } 1008 | 1009 | std::string log_save_path = file_to_save_dir + log_file_name; 1010 | 1011 | int64_t current_process = -1; 1012 | const auto ret = cam->DownloadCameraFile(log_url, 1013 | log_save_path, [&](int64_t current, int64_t total_size) { 1014 | const int64_t process = current * 100 / total_size; 1015 | if (process != current_process) { 1016 | std::cout << "\r"; 1017 | std::cout << "process = " << process << "%"; 1018 | std::cout << std::flush; 1019 | } 1020 | }); 1021 | std::cout << std::endl; 1022 | if (ret) { 1023 | std::cout << "Download " << log_save_path << " succeed!!!" << std::endl; 1024 | } 1025 | else { 1026 | std::cout << "Download " << log_save_path << " failed!!!" << std::endl; 1027 | } 1028 | } 1029 | } 1030 | 1031 | cam->Close(); 1032 | return 0; 1033 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to get? 2 | 3 | Please visit https://www.insta360.com/sdk/apply to apply for the latest SDK. 4 | 5 | # Support 6 | 7 | Developers' Page: https://www.insta360.com/developer/home 8 | 9 | Insta360 Enterprise: https://www.insta360.com/enterprise 10 | 11 | Issue Report: https://insta.jinshuju.com/f/hZ4aMW 12 | 13 | # [中文文档](README_zh.md) 14 | 15 | # Overview 16 | 17 | CameraSDK is primarily used for connecting to cameras, configuring and retrieving camera parameters, controlling camera operations for capturing photos and recording videos, downloading files, and upgrading firmware (only supported for cameras from model X4 and later). It supports camera connections exclusively via USB. Designed for enterprise users, it mainly supports panoramic cameras such as the ONE X, ONE X2, R/RS, X3, X4, X5. The primary supported platforms are Windows and Ubuntu 22.04. 18 | 19 | - **Supported cameras** 20 | 21 | | Model | Link | 22 | | :--------------------------------------- | :-------------------------------------------------------- | 23 | | ONE X (Discontinued) | http://insta360.com/product/insta360-onex/ | 24 | | ONE R Twin Edition (Discontinued) | http://insta360.com/product/insta360-oner_twin-edition | 25 | | ONE X2 | https://www.insta360.com/product/insta360-onex2 | 26 | | ONE RS 1-Inch 360 Edition (Discontinued) | https://www.insta360.com/product/insta360-oners/1inch-360 | 27 | | X3 | https://www.insta360.com/product/insta360-x3 | 28 | | X4 | https://www.insta360.com/product/insta360-x4 | 29 | | X5 | https://www.insta360.com/product/insta360-x5 | 30 | 31 | - **Supported platforms** 32 | 33 | | Platform | Version | 34 | | :------- | :----------------------------------------------------------- | 35 | | Windows | Windows 7 or later, only x64 supported | 36 | | Linux | Ubuntu 22.04 (x86_64), other distributions need to be tested | 37 | 38 | # **Table of contents** 39 | 40 | * [Environment Setup](#Environment-Setup) 41 | * [Camera Discovery](#Camera-Discovery) 42 | * [Camera Connection and Disconnection](#Camera-Connection-and-Disconnection) 43 | * [Photo Capture](#Photo-Capture) 44 | * [Video Recording](#Video-Recording) 45 | * [File Download](#File-Download) 46 | * [File Information Retrieval](#File-Information-Retrieval) 47 | * [File Deletion](#File-Deletion) 48 | * [Recorded File Name Retrieval](#Recorded-File-Name-Retrieval) 49 | * [Firmware Upgrade](#Firmware-Upgrade-(Only-Supported-for-X4-and-Later-Cameras)) 50 | * [Status Query](#Status-Query) 51 | * [Preview Stream Functionality](#Preview-Stream-Functionality) 52 | * [Log](#Log) 53 | * [Others](#Others) 54 | 55 | 56 | 57 | # **Feature Usage Instructions** 58 | 59 | ## **Environment Setup** 60 | 61 | ### **Switching the Camera to Android Mode** 62 | 63 | By default, when you connect an Insta360 camera to a computer, the camera automatically switches to U disk mode, causing it to be recognized as a USB storage device. To use the camera’s “Android” control mode, you must switch the camera to **Android** mode. 64 | 65 | #### **For ONE X** 66 | 67 | You need to upgrade to a special firmware version, which can be downloaded [[here](https://insta360-dev.oss-cn-hangzhou.aliyuncs.com/developer/releases/a33b3362-4767-47c3-ba9d-6ed07febb210.zip)]. After the upgrade, open the camera’s settings, locate the “Android” option, and enable it. 68 | 69 | #### **For ONE R/RS,** **ONE X2**, X3 70 | 71 | On the camera, swipe down to access the main menu, then go to **Settings** → **General** → **USB Mode**, and set **USB Mode** to **Android**. 72 | 73 | #### **For** **X4**、X5 74 | 75 | Connect the camera via USB. Once connected, a pop-up page will appear; on that page, select Android mode. 76 | 77 | ### Driver Installation 78 | 79 | #### **Linux** 80 | 81 | Ensure that the distribution has libusb installed. Installation can be performed using yum or apt-get. 82 | 83 | ```bash 84 | sudo apt-get install libusb-dev 85 | sudo apt-get install libudev-dev 86 | ``` 87 | 88 | Or build from source: 89 | 90 | ```bash 91 | wget http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.9/libusb-1.0.9.tar.bz2 92 | tar xjf libusb-1.0.9.tar.bz2 93 | cd libusb-1.0.9 94 | ./configure 95 | make 96 | sudo make install 97 | ``` 98 | 99 | Once the driver installation is complete, you can use the lsusb command to check if the camera is detected properly. If you see a device with an ID such as 0x2e1a, it indicates the driver is installed correctly. 100 | 101 | **Note**: On Linux systems, if you encounter permission issues, you must run the program with sudo. For example: 102 | 103 | ```bash 104 | sudo ./CameraSDKDemo // for Ubuntu 105 | ``` 106 | 107 | #### **Windows** 108 | 109 | Please install the [**libusbK**](https://sourceforge.net/projects/libusbk/files/libusbK-release/3.0.7.0/) driver. You can install libusbK directly or use [**Zadig**](https://zadig.akeo.ie/) to install the libusbK driver. 110 | 111 | ## Camera Discovery 112 | 113 | Camera discovery is primarily achieved through the **ins\_camera::DeviceDiscovery** interface. 114 | 115 | ```c++ 116 | // Example code 117 | // The DeviceDescriptor struct mainly stores basic camera information for connection purposes. 118 | struct DeviceDescriptor { 119 | CameraType camera_type; // Camera type, e.g., X3 or X4 120 | std::string serial_number; // Serial number of the current camera 121 | std::string fw_version; // Version number of the current camera firmware 122 | DeviceConnectionInfo info; // This information is not used; PC SDK only supports USB connections 123 | }; 124 | 125 | ins_camera::DeviceDiscovery discovery; 126 | // Store discovered camera information in the list 127 | std::vector list = discovery.GetAvailableDevices(); 128 | ``` 129 | 130 | 131 | 132 | ## Camera Connection and Disconnection 133 | 134 | ### **Creating a Camera Instance** 135 | 136 | After obtaining the camera information, use the **ins\_camera::Camera** and **DeviceDescriptor** interfaces to create an instance that controls the camera. 137 | 138 | ```c++ 139 | // Get the necessary parameter information from the camera list 140 | auto camera_info = list[0].info; 141 | auto camera = std::make_shared(camera_info); 142 | // Once successfully created, a camera instance is generated 143 | ``` 144 | 145 | ### **Opening the Camera** 146 | 147 | Next, you can open the camera using the **Open**interface: 148 | 149 | ```c++ 150 | bool success = camera->Open(); 151 | if(!success) { 152 | std::cout << "failed to open camera" << std::endl; 153 | return -1; 154 | } 155 | ``` 156 | 157 | ### **Disconnecting the Camera** 158 | 159 | The camera can be disconnected by calling the **Close** interface. 160 | 161 | > **Note**: After using the firmware upgrade interface, it is necessary to call the interface to close the camera. Once the upgrade is successful, recreate the camera instance. 162 | 163 | ```c++ 164 | camera->Close(); 165 | ``` 166 | 167 | ### **Checking Camera Connection Status** 168 | 169 | Use the **IsConnected** interface to determine whether the camera is currently connected. 170 | 171 | **Note**: Avoid calling this interface while the camera is switching modes. 172 | 173 | 174 | 175 | ## **Photo Capture** 176 | 177 | ### **Basic Parameter Settings** 178 | 179 | #### **Setting Camera Photo Mode** 180 | 181 | Use the SetPhotoSubMode interface to switch between different **Photo Modes**. The supported modes are listed below. For specific usage, please refer to the camera’s interface. 182 | 183 | ```c++ 184 | enum SubPhotoMode { 185 | PHOTO_SINGLE = 0, // Photo 186 | PHOTO_HDR = 1, // HDR Photo 187 | PHOTO_INTERVAL = 2, // Interval 188 | PHOTO_BURST = 3, // Burst 189 | PHOTO_STARLAPSE = 7 // Starlapse 190 | }; 191 | // Use the interface to switch Photo Modes 192 | camera->SetPhotoSubMode(SubPhotoMode::PHOTO_SINGLE) 193 | ``` 194 | 195 | 196 | 197 | #### **Setting Photo Resolution** 198 | 199 | The **SetPhotoSize** interface allows setting the photo size. Currently, **X4** **and** **X3** support formats mainly **72M** and **18M**. 200 | 201 | **Note**: This interface can only be applied to the photo modes in the **CameraFunctionMode** enumeration. **Video modes do not support the PhotoSize interface.** 202 | 203 | ```C++ 204 | // Photo Resolution Options 205 | enum PhotoSize { 206 | Size_6912_3456 = 0, // X3 18MP 207 | Size_6272_3136 = 1, 208 | Size_6080_3040 = 2, 209 | Size_4000_3000 = 3, 210 | Size_4000_2250 = 4, 211 | Size_5212_3542 = 5, 212 | Size_5312_2988 = 6, 213 | Size_8000_6000 = 7, 214 | Size_8000_4500 = 8, 215 | Size_2976_2976 = 9, 216 | Size_5984_5984 = 10, 217 | Size_11968_5984 = 11, // 72MP 218 | Size_5952_2976 = 12, // X4 18MP 219 | }; 220 | 221 | // Photo Modes 222 | enum CameraFunctionMode { 223 | FUNCTION_MODE_NORMAL = 0, // Default Mode 224 | FUNCTION_MODE_INTERVAL_SHOOTING = 3, // Interval Shooting Mode 225 | FUNCTION_MODE_BURST = 5, // Burst Mode 226 | FUNCTION_MODE_NORMAL_IMAGE = 6, // Photo Mode 227 | FUNCTION_MODE_HDR_IMAGE = 8, // HDR Photo Mode 228 | FUNCTION_MODE_AEB_NIGHT_IMAGE = 13, 229 | FUNCTION_MODE_STARLAPSE_IMAGE = 18, // Starlapse Mode 230 | ... 231 | }; 232 | 233 | //Example: Setting a Photo Mode to 72MP Resolution 234 | camera->SetPhotoSize(CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE,PhotoSize::Size_11968_5984) 235 | ``` 236 | 237 | #### **Exposure Parameters** 238 | 239 | The ExposureSettings interface is used to store exposure parameters. The ExposureSettings interface includes **ISO,** **Shutter** **Speed, Exposure Mode**, and **Exposure Compensation (EV Bias)**. Refer to the following code example: 240 | 241 | ```C++ 242 | class CAMERASDK_API ExposureSettings { 243 | public: 244 | friend class Camera; 245 | ExposureSettings(); 246 | 247 | void SetIso(int32_t value); 248 | void SetShutterSpeed(double speed); 249 | void SetExposureMode(PhotographyOptions_ExposureMode mode); 250 | void SetEVBias(int32_t value); 251 | 252 | int32_t Iso() const; 253 | double ShutterSpeed() const; 254 | PhotographyOptions_ExposureMode ExposureMode() const; 255 | int32_t EVBias() const; 256 | 257 | private: 258 | std::shared_ptr private_impl_; 259 | }; 260 | ``` 261 | 262 | Use the **GetExposureSettings** interface to obtain the exposure parameters for each Photo Mode. Refer to the following example: 263 | 264 | ```C++ 265 | // Get exposure parameters for Photo mode 266 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 267 | auto exposure_settings = camera->GetExposureSettings(funtion_mode); 268 | auto iso = exposure_settings->Iso(); 269 | auto shutter_speed = exposure_settings->ShutterSpeed(); 270 | // ... 271 | ``` 272 | 273 | Use the **SetExposureSettings** interface to configure the exposure parameters for each Photo Mode. Refer to the following example: 274 | 275 | ```C++ 276 | // 1. Get exposure parameters for Photo mode 277 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 278 | auto exposure_settings = camera->GetExposureSettings(funtion_mode); 279 | 280 | // 2. Set exposure parameters 281 | exposure_settings->SetEVBias(bias); // range -80 ~ 80, default 0, step 1 282 | exposure_settings->SetIso(800); 283 | exposure_settings->SetShutterSpeed(1.0 / 120.0); 284 | 285 | // 3. Apply exposure settings to the camera 286 | camera->SetExposureSettings(funtion_mode,exposure_settings); 287 | ``` 288 | 289 | #### **White Balance Parameters** 290 | 291 | The **White Balance** interface is stored in the **CaptureSettings** interface, which contains **White Balance** and other parameters. 292 | 293 | The **current White Balance parameters** are obtained using the **GetCaptureSettings** interface. Refer to the following code: 294 | 295 | ```C++ 296 | // Get White Balance parameters for the Photo Mode 297 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 298 | auto capture_setting = camera->GetCaptureSettings(funtion_mode); 299 | auto value = settings->GetIntValue(ins_camera::CaptureSettings::SettingsType::CaptureSettings_WhiteBalance); 300 | ``` 301 | 302 | Use the **SetCaptureSettings** interface to configure the White Balance parameters. Example: 303 | 304 | ```C++ 305 | // 1. Get White Balance parameters 306 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 307 | auto capture_setting = camera->GetCaptureSettings(funtion_mode); 308 | 309 | // 2. Set White Balance parameters 310 | capture_setting->SetWhiteBalance(ins_camera::PhotographyOptions_WhiteBalance::WB_6500K); 311 | 312 | // 3. Apply the parameters to the camera 313 | camera->SetCaptureSettings(funtion_mode, capture_setting); 314 | ``` 315 | 316 | ### **Normal Photo** 317 | 318 | **Normal photos** can be captured using the following reference code: 319 | 320 | ```C++ 321 | // Set to Photo Mode 322 | camera->SetPhotoSubMode(SubPhotoMode::PHOTO_SINGLE) 323 | 324 | // Set resolution to 18MP. This applies to X3. For X4, set to Size_5952_2976 325 | ins_camera::PhotoSize photo_size = ins_camera::PhotoSize::Size_6912_3456; 326 | if (camera_type == ins_camera::CameraType::Insta360X4) { 327 | photo_size = ins_camera::PhotoSize::Size_5952_2976; 328 | } 329 | camera->SetPhotoSize(CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE,photo_size); 330 | 331 | // Capture photo 332 | camera->takePhoto(); 333 | ``` 334 | 335 | ### **HDR** **Photo** 336 | 337 | A dedicated interface is provided for **HDR** **Photo**: **StartHDRCapture**. 338 | 339 | For cameras prior to **X3**, once exposure is complete, the number of photos obtained is typically **3**, **5**, **7**, or **9**. 340 | 341 | For **X4** cameras, after the capture is complete, **1** photo is obtained, which has already been merged for HDR and can **be** **stitched directly.** 342 | 343 | ```C++ 344 | ins_camera::PhotoSize photo_size = ins_camera::PhotoSize::Size_6912_3456; 345 | if (camera_type == ins_camera::CameraType::Insta360X4) { 346 | photo_size = ins_camera::PhotoSize::Size_5952_2976; 347 | } 348 | camera->StartHDRCapture(photo_size); 349 | ``` 350 | 351 | 352 | 353 | ## **Video Recording** 354 | 355 | ### **Basic Parameter Settings** 356 | 357 | #### **Setting Camera Video Mode** 358 | 359 | Use the **SetVideoSubMode** interface to switch between different **video modes**. The supported modes are listed below. For specific usage, refer to the Camera Menu. 360 | 361 | ```c++ 362 | enum SubVideoMode { 363 | VIDEO_NORMAL = 0, // Normal Video 364 | VIDEO_BULLETTIME = 1, // Bullet Time 365 | VIDEO_TIMELAPSE = 2, // Timelapse 366 | VIDEO_HDR = 3, // HDR Video 367 | VIDEO_TIMESHIFT = 4, // Timeshift 368 | VIDEO_LOOPRECORDING = 6 // Loop Recording 369 | }; 370 | 371 | // Use the interface to switch video modes 372 | camera->SetVideoSubMode(SubVideoMode::VIDEO_NORMAL); 373 | ``` 374 | 375 | 376 | 377 | #### **Setting Resolution** 378 | 379 | The **SetVideoCaptureParams** interface is used to configure recording parameters. 380 | 381 | This interface is only applicable to video modes listed under **CameraFunctionMode**.The **SetVideoCaptureParams** interface **does not support** setting parameters for photo modes. 382 | 383 | ```c++ 384 | // Video Modes 385 | enum CameraFunctionMode { 386 | FUNCTION_MODE_MOBILE_TIMELAPSE = 2, // Mobile Timelapse Mode 387 | FUNCTION_MODE_NORMAL_VIDEO = 7, // Normal Video Mode 388 | FUNCTION_MODE_HDR_VIDEO = 9, // HDR Video Mode 389 | FUNCTION_MODE_INTERVAL_VIDEO = 10, // Interval Video Mode 390 | FUNCTION_MODE_STATIC_TIMELAPSE = 11, // Timelapse Mode 391 | FUNCTION_MODE_TIMESHIFT = 12, // Timeshift Mode 392 | FUNCTION_MODE_LOOP_RECORDING_VIDEO = 17 // Loop Recording Mode 393 | }; 394 | 395 | // This structure defines recording resolution, frame rate, and bitrate 396 | struct RecordParams { 397 | VideoResolution resolution; 398 | int32_t bitrate{ 0 }; 399 | }; 400 | 401 | auto function_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_VIDEO; 402 | ins_camera::RecordParams record_params; 403 | // Set 5.7K 60FPS 404 | record_params.resolution = ins_camera::VideoResolution::RES_2880_2880P60; 405 | // Set bitrate to 10MB. This value may not be valid, and certain bitrates might cause write failures during recording. 406 | record_params.bitrate = 1024 * 1024 * 10; 407 | if (!cam->SetVideoCaptureParams(record_params, function_mode)) { 408 | std::cerr << "failed to set capture settings." << std::endl; 409 | } 410 | ``` 411 | 412 | 413 | 414 | #### **Exposure Parameters** 415 | 416 | Refer to [Exposure Parameters](#exposure-parameters) 417 | 418 | #### **White Balance Parameters** 419 | 420 | Refer to [White Balance Parameters](#white-balance-parameters) 421 | 422 | ### **Normal Recording** 423 | 424 | Normal recording can be demonstrated using the following reference code. 425 | 426 | #### **Start Recording** 427 | 428 | ```c++ 429 | // 1. Switch mode to normal video mode 430 | bool ret = camera->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_NORMAL); 431 | if (!ret) { 432 | std::cout << "change sub mode failed!" << std::endl; 433 | continue; 434 | } 435 | 436 | // 2. Set current resolution, frame rate, and bitrate 437 | auto function_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_VIDEO; 438 | ins_camera::RecordParams record_params; 439 | // Set 5.7K 60FPS 440 | record_params.resolution = ins_camera::VideoResolution::RES_2880_2880P60; 441 | record_params.bitrate = 1024 * 1024 * 10; 442 | // Set bitrate to 10MB, this parameter may not take effect, as certain camera models or settings may have a fixed bitrate 443 | if (!camera->SetVideoCaptureParams(record_params, function_mode)) { 444 | std::cerr << "failed to set capture settings." << std::endl; 445 | } 446 | else { 447 | // 3. Start recording 448 | const auto ret = camera->StartRecording(); 449 | if (ret) { 450 | std::cerr << "success!" << std::endl; 451 | } 452 | else { 453 | std::cerr << "failed to start recording" << std::endl; 454 | } 455 | } 456 | ``` 457 | 458 | #### **Stopping recording** 459 | 460 | ```c++ 461 | // Stopping recording 462 | auto url = cam->StopRecording(); 463 | if (url.Empty()) { 464 | std::cerr << "stop recording failed" << std::endl; 465 | continue; 466 | } 467 | // Output all original URLs generated by the recording 468 | auto& origins = url.OriginUrls(); 469 | std::cout << "stop recording success" << std::endl; 470 | for (auto& origin_url : origins) { 471 | std::cout << "url:" << origin_url << std::endl; 472 | } 473 | ``` 474 | 475 | ### **Timelapse Recording** 476 | 477 | Timelapse recording can be demonstrated using the reference code below: 478 | 479 | The table below shows the supported **resolution-frame rate** mappings for Timelapse mode on different cameras. 480 | 481 | | **Resolution-Frame Rate** | **X4**、X5 | **X3** | **ONE X2** | **R** | **RS** | **ONE X** | 482 | | :-----------------------: | :--------------: | :--------------: | :--------: | :---: | :----: | :-------: | 483 | | **11K30** | RES_5632_5632P30 | Not Supported | Todo | Todo | Todo | Todo | 484 | | **8K30** | RES_3840_3840P30 | RES_3840_3840P30 | Todo | Todo | Todo | Todo | 485 | | **5.7K30** | RES_2880_2880P30 | RES_2880_2880P30 | Todo | Todo | Todo | Todo | 486 | 487 | #### **Start Recording** 488 | 489 | ```c++ 490 | 491 | // 1. Switch the camera mode to timelapse mode 492 | bool ret = cam->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_TIMELAPSE); 493 | if (!ret) { 494 | std::cout << "change sub mode failed!" << std::endl; 495 | continue; 496 | } 497 | 498 | // 2. Set the resolution and frame rate for the current mode 499 | auto function_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_MOBILE_TIMELAPSE; 500 | ins_camera::RecordParams record_params; 501 | // 8K30 resolution 502 | record_params.resolution = ins_camera::VideoResolution::RES_3840_3840P30; 503 | if (!cam->SetVideoCaptureParams(record_params, function_mode )) { 504 | std::cerr << "failed to set capture settings." << std::endl; 505 | break; 506 | } 507 | 508 | // 3. Set the parameters for mobile timelapse 509 | auto timelapse_mode = ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO; 510 | const uint32_t record_duration_s = 10; // Recording duration: 10 seconds 511 | const uint32_t lapseTime_ms = 1000; // Interval duration: 1 second 512 | ins_camera::TimelapseParam param = { timelapse_mode, 10, 1000, 0 }; 513 | if (!cam->SetTimeLapseOption(param)) { 514 | std::cerr << "failed to set capture settings." << std::endl; 515 | } 516 | else { 517 | // 4. Start recording 518 | const auto ret = cam->StartTimeLapse(param.mode); 519 | if (ret) { 520 | std::cerr << "success!" << std::endl; 521 | } 522 | else { 523 | std::cerr << "failed to start timelapse" << std::endl; 524 | } 525 | } 526 | ``` 527 | 528 | #### **Stop Recording** 529 | 530 | ```c++ 531 | auto timelapse_mode = ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO; 532 | auto url = cam->StopTimeLapse(timelapse_mode ); 533 | if (url.Empty()) { 534 | std::cerr << "stop timelapse failed" << std::endl; 535 | continue; 536 | } 537 | // Get the recorded media file location on the camera 538 | auto& origins = url.OriginUrls(); 539 | std::cout << "stop timelapse success" << std::endl; 540 | for (auto& origin_url : origins) { 541 | std::cout << "url:" << origin_url << std::endl; 542 | } 543 | ``` 544 | 545 | 546 | 547 | ## **File Information** 548 | 549 | ### **Retrieving the Number of Files** 550 | 551 | Use the **GetCameraFilesCount** interface to obtain the number of recorded files on the camera’s SD card. 552 | 553 | ### **Retrieving the File List** 554 | 555 | Use the **GetCameraFilesList** interface to obtain a list of recorded files on the SD card. Refer to the code below: 556 | 557 | ```C++ 558 | auto file_list = camera->GetCameraFilesList(); 559 | for(const auto& file : file_list) { 560 | std::cout << file << std::endl; 561 | } 562 | 563 | // print output 564 | /DCIM/Camera01/VID_20250122_071405_00_001.insv 565 | /DCIM/Camera01/LRV_20250122_071405_01_001.lrv 566 | /DCIM/Camera01/VID_20250214_063916_00_002.insv 567 | /DCIM/Camera01/LRV_20250214_063916_01_002.lrv 568 | ``` 569 | 570 | 571 | 572 | ## **Retrieving the List of Files Currently Being Recorded** 573 | 574 | Use the **GetRecordingFiles** interface to obtain the names of files currently being recorded on the camera. 575 | 576 | ## **File Download** 577 | 578 | ### **Download Files** 579 | 580 | Using the **DownloadCameraFile** interface allows downloading existing media from the camera or SD card to the local device. 581 | 582 | A callback can be set to obtain the current file download process. This interface is called synchronously; it returns only after the download is complete or has failed. 583 | 584 | > **Note:** 585 | > 586 | > 1. Before downloading, ensure that the directory path on the local device has been created. 587 | > 588 | > 2. Because the SDK starts an HttpServer, if the port is occupied, the service may fail to start. The SDK provides the **SetServicePort **interface to resolve this issue. The default port in the SDK is **9099**. It is necessary for the caller to check whether the port is in use. If the port is already occupied, set the port before calling the **Open** interface. 589 | 590 | ```c++ 591 | // Camera-side file path 592 | std::string camera_file = "/DCIM/Camera01/VID_20250122_071405_00_001.insv"; 593 | // Local save path 594 | std::string local_save_file = "/path/to/local/VID_20250122_071405_00_001.insv"; 595 | 596 | // Start download 597 | bool ret = camera->DownloadCameraFile(camera_file, local_save_file, [](int64_t current, int64_t total_size) { 598 | //Display Progress 599 | std::cout << "current :" << current << "; total_size: " << total_size << std::endl; 600 | }); 601 | 602 | // Download result 603 | if(ret) { 604 | std::cout << "successed to download file" << std::end; 605 | } 606 | ``` 607 | 608 | 609 | 610 | ### **Cancel Download** 611 | 612 | Use the **CancelDownload** interface to cancel the file that is currently being downloaded. 613 | 614 | 615 | 616 | ## **Delete Files** 617 | 618 | Use the **DeleteCameraFile** interface to delete unwanted files from the SD card. 619 | 620 | ```C++ 621 | const auto camera_file = "/DCIM/Camera01/VID_20250122_071405_00_001.insv"; 622 | camera_file->DeleteCameraFile(camera_file); 623 | ``` 624 | 625 | 626 | 627 | ## **Firmware Upgrade (Only Supported for X4 and Later Cameras)** 628 | 629 | The **UploadFile** interface is used to upgrade the firmware version. Currently, only **X4** and later cameras are supported. The predefined firmware file name is: **Insta360X4FW.bin**. Below is an example code snippet: 630 | 631 | ```c++ 632 | // Set the firmware file name 633 | const std::string fireware_name = "Insta360X4FW.bin"; 634 | std::string file_name = "Insta360X4FW.bin"; 635 | if (camera_type == ins_camera::CameraType::Insta360X5) { 636 | file_name = "Insta360X5FW.bin"; 637 | } 638 | 639 | const auto ret = cam->UploadFile(local_path, file_name, 640 | // Specify the local path of the firmware 641 | const std::string local_file = "/path/to/fireware/Insta360X4FW.bin"; 642 | 643 | // Start uploading 644 | bool ret = cam->UploadFile(local_file, fireware_name , 645 | [](int64_t current, int64_t total_size) { 646 | // Firmware upload progress display 647 | std::cout << "current :" << current << ";total_size: " << total_size << std::endl; 648 | }); 649 | 650 | if (ret) { 651 | std::cout << "succeeded to upload file" << std::endl; 652 | } 653 | 654 | //After a successful upload, the camera must be powered off. Once the upgrade is complete, recreate the camera instance (the camera needs to restart for the upgrade). 655 | camera->close(); 656 | ``` 657 | 658 | ## **Status Query** 659 | 660 | ### **Battery Status Information** 661 | 662 | Use the **GetBatteryStatus** interface to obtain the camera’s current battery information, such as the current battery level. 663 | 664 | ```c++ 665 | // These definitions are provided in the SDK's header file 666 | enum PowerType { 667 | BATTERY = 0, 668 | ADAPTER = 1, 669 | }; 670 | 671 | struct BatteryStatus { 672 | PowerType power_type; // Power source type 673 | uint32_t battery_level; // Current battery percentage (0~100) 674 | uint32_t battery_scale; // This value is not used. 675 | }; 676 | 677 | BatteryStatus status; 678 | bool successed = camera->GetBatteryStatus(status); 679 | ``` 680 | 681 | 682 | 683 | ### **SD Card Storage Information** 684 | 685 | Use the **GetStorageState** interface to obtain the current status of the SD card, including its state and available space. 686 | 687 | ```c++ 688 | // These definitions are provided in the SDK's header file 689 | enum CardState { 690 | STOR_CS_PASS = 0, // Normal 691 | STOR_CS_NOCARD = 1, // No card 692 | STOR_CS_NOSPACE = 2, // Insufficient space 693 | STOR_CS_INVALID_FORMAT = 3,// Incorrect card format 694 | STOR_CS_WPCARD = 4, // Write-protected card 695 | STOR_CS_OTHER_ERROR = 5 // Other errors 696 | }; 697 | 698 | struct StorageStatus { 699 | CardState state; // SD card status 700 | uint64_t free_space; // Remaining space on the SD card 701 | uint64_t total_space; // Total space on the SD card 702 | }; 703 | 704 | StorageStatus status; 705 | bool successed = camera->GetStorageState(status); 706 | ``` 707 | 708 | ### **Current Camera Capture or Recording Status** 709 | 710 | The interface **CaptureCurrentStatus** can be used to check whether the camera is in photo or video mode. "Capture" refers to taking photos. 711 | 712 | ```c++ 713 | auto ret= camera->CaptureCurrentStatus(); 714 | if (ret) { 715 | std::cout << "current statue : capture" << std::endl; 716 | } 717 | else { 718 | std::cout << "current statue : not capture" << std::endl; 719 | } 720 | ``` 721 | 722 | ### **Camera Information Notifications** 723 | 724 | This section provides interfaces for the camera’s active notifications, which primarily involve low battery, SD card full, camera overheating, and recording stoppage. 725 | 726 | ```C++ 727 | // This interface is used to set the low battery notification 728 | void SetBatteryLowNotification(BatteryLowCallBack callback); 729 | 730 | // This interface is used to set the SD card full notification 731 | void SetStorageFullNotification(StorageFullCallBack callback); 732 | 733 | // This interface is used to set the camera recording interruption notification 734 | void SetCaptureStoppedNotification(CaptureStoppedCallBack callback); 735 | 736 | // This interface is used to set the camera high-temperature notification 737 | void SetTemperatureHighNotification(TemperatureHighCallBack callback); 738 | ``` 739 | 740 | ## **Preview Stream Functionality** 741 | 742 | ### **Setting the Preview Stream Data Delegate Interface** 743 | 744 | The interface **ins\_camera::StreamDelegate** can be inherited to implement access to raw video streams, audio streams, gyro data, and exposure data. Refer to the following code: 745 | 746 | ```c++ 747 | class TestStreamDelegate : public ins_camera::StreamDelegate { 748 | public: 749 | TestStreamDelegate() {} 750 | 751 | // Callback for audio data 752 | void OnAudioData(const uint8_t* data, size_t size, int64_t timestamp) override {} 753 | 754 | // Callback for video data 755 | void OnVideoData(const uint8_t* data, size_t size, int64_t timestamp, uint8_t streamType, int stream_index) override { 756 | if (stream_index == 0) { 757 | // First video stream 758 | } 759 | if (stream_index == 1) { 760 | // Second video stream 761 | } 762 | } 763 | 764 | // Callback for gyro data 765 | void OnGyroData(const std::vector& data) override {} 766 | 767 | // Callback for exposure data 768 | void OnExposureData(const ins_camera::ExposureData& data) override {} 769 | }; 770 | ``` 771 | 772 | 1. For video data, if the resolution is less than 5.7K (5760×2280), the preview stream consists of a single video stream. If the resolution is 5.7K or higher, there will be **two video streams**. The data format is encoded in either H.265 or H.264, which can be retrieved using the interface **GetVideoEncodeType** to obtain the actual encoding format of the camera. A decoder can be created based on the encoding format to decode the data. The decoded data is not stitched together but consists of two fisheye images. Generally, the resolution of the preview stream is **1920×960**. 773 | 774 | 2. After implementing this delegate interface, an instance must be created and assigned to the camera instance using the **SetStreamDelegate** interface. The following code demonstrates this: 775 | 776 | ```c++ 777 | auto delegate = std::make_shared(); 778 | camera->SetStreamDelegate(delegate); 779 | ``` 780 | 781 | 782 | 783 | ### **Starting the Preview Stream** 784 | 785 | The preview stream can be enabled by setting the preview stream parameters and calling the **StartLiveStreaming** interface. For the preview stream resolution, **1920×960** is currently recommended. 786 | 787 | ```c++ 788 | ins_camera::LiveStreamParam param; 789 | param.video_resolution = ins_camera::VideoResolution::RES_1920_960P30; 790 | param.lrv_video_resulution = ins_camera::VideoResolution::RES_1920_960P30; 791 | param.video_bitrate = 1024 * 1024 / 2; 792 | param.enable_audio = false; 793 | param.using_lrv = false; 794 | if (cam->StartLiveStreaming(param)) { 795 | std::cout << "successfully started live stream" << std::endl; 796 | } 797 | ``` 798 | 799 | ### **Stopping the Preview Stream** 800 | 801 | Use the **StopLiveStreaming** interface to stop the preview stream. 802 | 803 | 804 | 805 | ## **Logging Feature** 806 | 807 | ### **Setting the Log Path** 808 | 809 | This interface is mainly used to set the SDK’s log path, where the SDK’s log information can be saved. 810 | 811 | ```C++ 812 | void SetLogPath(const std::string log_path) 813 | ``` 814 | 815 | ### **Setting the Log Level** 816 | 817 | This interface is used to set the log level for the SDK’s log output. 818 | 819 | ```C++ 820 | void SetLogLevel(LogLevel level) 821 | ``` 822 | 823 | ### **Retrieving the Camera** **Log** **Path** 824 | 825 | This interface is used to retrieve the path of the camera’s log file. Once the path is obtained, you can use the download interface to download the log file locally. 826 | 827 | ```C++ 828 | std::string GetCameraLogFileUrl() const; 829 | ``` 830 | 831 | ## **Others** 832 | 833 | ### **Retrieving Camera Media Time: GetCameraMediaTime()** 834 | 835 | This interface retrieves the camera’s current media time, which can be used to synchronize with the tail-end information of recorded files. 836 | 837 | 838 | 839 | ### **Switch Camera Lens – SetActiveSensor** 840 | 841 | This interface allows switching between different camera lenses. 842 | 843 | **SENSOR_DEVICE_FRONT(1)** – Switch to the lens on the screen side 844 | 845 | **SENSOR_DEVICE_REAR(2)** – Switch to the lens on the back side of the screen 846 | 847 | **SENSOR_DEVICE_ALL(3)** – Switch to panoramic mode 848 | 849 | ### **Turn Off the Camera (Only Supported on X5 and Later)** 850 | 851 | ```C++ 852 | void ShutdownCamera() 853 | ``` 854 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # 简要 2 | 3 | CameraSDK主要用于连接、设置和获取相机参数、控制相机进行拍照和录制、文件下载和固件升级(仅支持X4)等。仅支持通过usb进行连接相机。用于toB用户,主要支持的相机有ONE X,ONE X2、R/RS、X3、X4以及X5全景相机。主要支持的平台有windows、ubuntu22.04。 4 | 5 | - 支持机型 6 | 7 | | 型号 | 连接 | 8 | | :------------------------------- | :-------------------------------------------------------- | 9 | | ONE X (停产) | http://insta360.com/product/insta360-onex/ | 10 | | ONE R Twin Edition (停产) | http://insta360.com/product/insta360-oner_twin-edition | 11 | | ONE X2 | https://www.insta360.com/product/insta360-onex2 | 12 | | ONE RS 1-Inch 360 Edition (停产) | https://www.insta360.com/product/insta360-oners/1inch-360 | 13 | | X3 | https://www.insta360.com/product/insta360-x3 | 14 | | X4 | https://www.insta360.com/product/insta360-x4 | 15 | | X5 | https://www.insta360.com/cn/product/insta360-x5 | 16 | 17 | - **支持平台** 18 | 19 | | 平台 | 版本 | 20 | | :------ | :----------------------------------------- | 21 | | Windows | Windows 7 或更高版本,仅支持 x64 | 22 | | Linux | Ubuntu 22.04(x86_64),其他发行版需要测试 | 23 | 24 | # 目录 25 | * [环境准备](#环境准备) 26 | * [相机发现](#相机发现) 27 | * [相机连接和断连](#相机连接和断连) 28 | * [拍照](#拍照) 29 | * [录制](#录制) 30 | * [获取文件信息](#获取文件信息) 31 | * [获取录制中的文件名称](#获取录制中的文件名称) 32 | * [下载文件](#下载文件) 33 | * [删除文件](#删除文件) 34 | * [固件升级](#固件升级) 35 | * [状态查询](#状态查询) 36 | * [预览流功能](#预览流功能) 37 | * [日记功能](#日记功能) 38 | * [其他](#其他) 39 | 40 | 41 | # 功能使用说明 42 | 43 | ## 环境准备 44 | 45 | ### 相机切换到安卓模式下 46 | 47 | 默认情况下,当你将Insta360相机连接到计算机时,相机会自动切换到U盘模式,使相机成为一个USB存储设备。 我们需要将相机切换到正确模式,才能连接并控制它。 48 | 49 | #### For ONE X 50 | 51 | 你需要升级到一个特殊版本的固件,[在此处下载](https://insta360-dev.oss-cn-hangzhou.aliyuncs.com/developer/releases/a33b3362-4767-47c3-ba9d-6ed07febb210.zip) 52 | 53 | 升级后,在相机上进入设置,找到USB选项,将其设置为**Android**模式。 54 | 55 | #### For ONE R/RS、ONE X2、X3 56 | 57 | 在摄像头界面,向下滑动屏幕进入主菜单,进入“设置”->“常规”,将USB模式设置为“Android”,将U盘模式设置为“Android”模式。 58 | 59 | #### For X4、X5 60 | 61 | 先连接usb线,然后弹出模式选择的界面,选择“**Android**”模式,等待切换成功。 62 | 63 | ### 驱动安装 64 | 65 | **On Linux**, 请确保你的发行版已安装libusb。你可以通过yum或apt-get进行安装。 66 | 67 | ```Bash 68 | sudo apt-get install libusb-dev 69 | sudo apt-get install libudev-dev 70 | ``` 71 | 72 | 或者从源代码构建 73 | 74 | ```Bash 75 | wget http://sourceforge.net/projects/libusb/files/libusb-1.0/libusb-1.0.9/libusb-1.0.9.tar.bz2 76 | tar xjf libusb-1.0.9.tar.bz2 77 | cd libusb-1.0.9 78 | ./configure 79 | make 80 | sudo make install 81 | ``` 82 | 83 | 安装驱动程序后,通过“lsusb”命令检查是否检测到摄像头。如果找到供应商ID为0x2e1a的任何USB设备,恭喜,您的驱动程序已成功安装。 84 | 85 | **注意:在Linux系统上,演示程序必须使用“sudo”运行,例如** 86 | 87 | ```Bash 88 | sudo ./CameraSDKDemo //for ubuntu 89 | ``` 90 | 91 | **在Windows系统上,请确保已安装libusbK驱动程序。你可以直接安装[libusbK](https://sourceforge.net/projects/libusbk/files/libusbK-release/3.0.7.0/),也可以使用[zadig](https://zadig.akeo.ie/)来协助安装libusbK驱动程序。** 92 | 93 | ## 相机发现 94 | 95 | 相机发现主要通过**ins\_camera::DeviceDiscovery**这个接口去实现的 96 | 97 | ```C++ 98 | //示例代码 99 | //这个DeviceDescriptor结构体主要保存了相机的基本信息,主要用于连接 100 | struct DeviceDescriptor { 101 | CameraType camera_type; //相机类型,比如x3或者x4 102 | std::string serial_number; //当前相机的序列号 103 | std::string fw_version; //当前相机固件的版本号 104 | DeviceConnectionInfo info; //这个信息没有用,主要PC端的SDK仅支持USB连接 105 | }; 106 | 107 | ins_camera::DeviceDiscovery discovery; 108 | //遍历到的相机信息保存这个list中。 109 | std::vector list = discovery.GetAvailableDevices(); 110 | ``` 111 | 112 | ## 相机连接和断连 113 | 114 | ### 创建相机实例 115 | 116 | 在获取到相机信息后,通过接口**ins_camera::Camera** 和 **DeviceDescriptor** 去创建控制相机的实例**。** 117 | 118 | ```C++ 119 | // 从相机列表中获取创建实例所需要的信息 120 | auto camera_info = list[0].info; 121 | auto camera = std::make_shared(camera_info); 122 | //到此已经创建好一个相机实例 123 | ``` 124 | 125 | ### 打开相机 126 | 127 | 接下来打开相机,可以通过接口**Open**去实现 128 | 129 | ```C++ 130 | bool success = camera->Open(); 131 | if(!success) { 132 | std::cout << "failed to open camera" << std::endl; 133 | return -1; 134 | } 135 | ``` 136 | 137 | ### 相机断连 138 | 139 | 相机断连,可以通过接口**Close**去实现 140 | 141 | > ⚠️ **注意:** 在使用升级固件按钮完成后,需要切换电源开关。等待升级成功后,再重新创建相机实例。 142 | 143 | ```C++ 144 | camera->Close(); 145 | ``` 146 | 147 | ### 判断相机是否连接 148 | 149 | 判断相机目前是否还在连接状态,请使用接口 **IsConnected** 150 | 151 | 注意:在相机切换状态下,避免调用此接口. 152 | 153 | ## 拍照 154 | 155 | ### 基本参数设置 156 | 157 | #### 设置相机照片模式 158 | 159 | 通过接口 **SetPhotoSubMode **进行各个照片模式的切换,下面是目前相机支持的模式,具体实际情况可以参考相机的界面。 160 | 161 | ```C++ 162 | enum SubPhotoMode { 163 | PHOTO_SINGLE = 0, // 普通拍照 164 | PHOTO_HDR = 1, // HDR拍照 165 | PHOTO_INTERVAL = 2, // Interval拍照 166 | PHOTO_BURST = 3, // Burst拍照 167 | PHOTO_STARLAPSE = 7, // 星空模式拍照 168 | }; 169 | 170 | // 可以通过接口进行照片模式的切换 171 | camera->SetPhotoSubMode(SubPhotoMode::PHOTO_SINGLE) 172 | ``` 173 | 174 | #### 设置分辨率大小 175 | 176 | 可以通过接口 **SetPhotoSize** 设置照片分辨率。目前,X4 和 X3 支持 72MP 和 18MP 两种格式。 177 | 178 | 接口如下:这个接口只能使用下面 **CameraFunctionMode **枚举的中照片的模式。视频的模式是不支持PhotoSize这个接口的。 179 | 180 | ```c++ 181 | //照片大小 182 | enum PhotoSize { 183 | Size_6912_3456 = 0, // X3 18MP 184 | Size_6272_3136 = 1, 185 | Size_6080_3040 = 2, 186 | Size_4000_3000 = 3, 187 | Size_4000_2250 = 4, 188 | Size_5212_3542 = 5, 189 | Size_5312_2988 = 6, 190 | Size_8000_6000 = 7, 191 | Size_8000_4500 = 8, 192 | Size_2976_2976 = 9, 193 | Size_5984_5984 = 10, 194 | Size_11968_5984 = 11, // 72MP 195 | Size_5952_2976 = 12, // X4 18MP 196 | }; 197 | 198 | // 照片模式 199 | enum CameraFunctionMode { 200 | FUNCTION_MODE_NORMAL = 0, // 默认模式 201 | FUNCTION_MODE_INTERVAL_SHOOTING = 3, // Interval拍照模式 202 | FUNCTION_MODE_BURST = 5, // Brust拍照模式 203 | FUNCTION_MODE_NORMAL_IMAGE = 6, // 普通拍照模式 204 | FUNCTION_MODE_HDR_IMAGE = 8, // HDR拍照模式 205 | FUNCTION_MODE_AEB_NIGHT_IMAGE = 13, 206 | FUNCTION_MODE_STARLAPSE_IMAGE = 18, // 星空模式 207 | ... 208 | }; 209 | 210 | // 设置普通拍照的照片大小为72MP 211 | camera->SetPhotoSize(CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE,PhotoSize::Size_11968_5984) 212 | ``` 213 | 214 | #### 曝光参数 215 | 216 | 曝光的接口是通过接口**ExposureSettings**去保存的 ,接口 **ExposureSettings 中**包含了ISO、快门、曝光模式以及曝光补偿。参考如下代码 217 | 218 | ```C++ 219 | class CAMERASDK_API ExposureSettings { 220 | public: 221 | friend class Camera; 222 | ExposureSettings(); 223 | 224 | void SetIso(int32_t value); 225 | void SetShutterSpeed(double speed); 226 | void SetExposureMode(PhotographyOptions_ExposureMode mode); 227 | void SetEVBias(int32_t value); 228 | 229 | int32_t Iso() const; 230 | double ShutterSpeed() const; 231 | PhotographyOptions_ExposureMode ExposureMode() const; 232 | int32_t EVBias() const; 233 | 234 | private: 235 | std::shared_ptr private_impl_; 236 | }; 237 | ``` 238 | 239 | 通过这个接口 **GetExposureSettings** 去获取各个模式下曝光参数。参考如下代码: 240 | 241 | ```C++ 242 | // 可以通过GetExposureSettings获取普通拍照模式的曝光参数 243 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 244 | auto exposure_settings = camera->GetExposureSettings(funtion_mode); 245 | auto iso = exposure_settings->Iso(); 246 | auto shutter_speed = exposure_settings->ShutterSpeed(); 247 | // ... 248 | ``` 249 | 250 | 通过这个接口 **SetExposureSettings** 去设置各个模式下的曝光参数。参数如下代码: 251 | 252 | ```C++ 253 | //1. 可以通过GetExposureSettings获取普通拍照模式的曝光参数 254 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 255 | auto exposure_settings = camera->GetExposureSettings(funtion_mode); 256 | 257 | //2. 设置参数 258 | exposure_settings->SetEVBias(bias); // range -80 ~ 80, default 0, step 1 259 | exposure_settings->SetIso(800); 260 | exposure_settings->SetShutterSpeed(1.0 / 120.0); 261 | 262 | //3. 发送参数可以相机 263 | camera->SetExposureSettings(funtion_mode,exposure_settings); 264 | ``` 265 | 266 | #### 白平衡参数 267 | 268 | 白平衡的接口通过这个接口 **CaptureSettings **去保存的 ,这个接口 **CaptureSettings **中包含了白平衡等其他参数。 269 | 270 | 获取当前白平衡参数通过接口 GetCaptureSettings 去获取。参考如下代码: 271 | 272 | ```C++ 273 | // 可以通过GetCaptureSettings获取普通拍照模式的白平衡参数 274 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 275 | auto capture_setting = camera->GetCaptureSettings(funtion_mode); 276 | auto value = settings->GetIntValue(ins_camera::CaptureSettings::SettingsType::CaptureSettings_WhiteBalance); 277 | ``` 278 | 279 | 设置白平衡参数可以通过接口 SetCaptureSettings 去设置。参考如下代码: 280 | 281 | ```C++ 282 | // 1. 获取当前参数 283 | const auto funtion_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE; 284 | auto capture_setting = camera->GetCaptureSettings(funtion_mode); 285 | 286 | // 2. 设置白平衡参数 287 | capture_setting->SetWhiteBalance(ins_camera::PhotographyOptions_WhiteBalance::WB_6500K); 288 | 289 | // 3. 设置给相机生效 290 | camera->SetCaptureSettings(funtion_mode, capture_setting); 291 | ``` 292 | 293 | ### 普通拍照 294 | 295 | 普通拍照可以通过以下参考代码: 296 | 297 | ```C++ 298 | // 设置为普通模式 299 | camera->SetPhotoSubMode(SubPhotoMode::PHOTO_SINGLE) 300 | 301 | // 设置为18M,这个是针对X3的。对于X4,需要设置为 Size_5952_2976 302 | ins_camera::PhotoSize photo_size = ins_camera::PhotoSize::Size_6912_3456; 303 | if (camera_type == ins_camera::CameraType::Insta360X4) { 304 | photo_size = ins_camera::PhotoSize::Size_5952_2976; 305 | } 306 | camera->SetPhotoSize(CameraFunctionMode::FUNCTION_MODE_NORMAL_IMAGE,photo_size); 307 | 308 | //进行拍照 309 | camera->takePhoto(); 310 | ``` 311 | 312 | ### HDR拍照 313 | 314 | 对于HDR拍照,我们单独提供了一个接口:**StartHDRCapture。** 315 | 316 | 对于X3之前的相机,拍照完成后,获取到照片的数量,一般是3,5,7或者9张素材。 317 | 318 | 对于X4相机以及之后的相机,拍照完成后,默认是获取到1张素材,并且这张素材已经是进行了HDR的融合操作,可以直接进行拼接。 319 | 320 | ```C++ 321 | ins_camera::PhotoSize photo_size = ins_camera::PhotoSize::Size_6912_3456; 322 | if (camera_type == ins_camera::CameraType::Insta360X4) { 323 | photo_size = ins_camera::PhotoSize::Size_5952_2976; 324 | } 325 | camera->StartHDRCapture(photo_size); 326 | ``` 327 | 328 | ## 录制 329 | 330 | ### 基本参数设置 331 | 332 | #### 设置相机视频模式 333 | 334 | 通过接口 **SetVideoSubMode**进行各个视频模式的切换,下面是目前相机支持的模式,具体实际情况可以参考相机的界面 335 | 336 | ```c++ 337 | enum SubVideoMode { 338 | VIDEO_NORMAL = 0, // 普通录制 339 | VIDEO_BULLETTIME = 1, // 子弹时间 340 | VIDEO_TIMELAPSE = 2, // timelapse录制 341 | VIDEO_HDR = 3, // HDR录制 342 | VIDEO_TIMESHIFT = 4, // timeshift录制 343 | VIDEO_LOOPRECORDING = 6, // 循环录影 344 | }; 345 | 346 | // 可以通过接口进行照片模式的切换 347 | camera->SetVideoSubMode(SubVideoMode::VIDEO_NORMAL); 348 | ``` 349 | 350 | #### 设置分辨率大小 351 | 352 | 可以通过接口 **SetVideoCaptureParams**的设置录制时的参数 353 | 354 | 接口如下:这个接口只能使用下面 CameraFunctionMode 枚举的中视频的模式。**SetVideoCaptureParams **这个接口是不支持设置照片的模式的。 355 | 356 | ```c++ 357 | // 视频模式 358 | enum CameraFunctionMode { 359 | FUNCTION_MODE_MOBILE_TIMELAPSE = 2, // 移动延时视频模式 360 | FUNCTION_MODE_NORMAL_VIDEO = 7, // 普通视频模式 361 | FUNCTION_MODE_HDR_VIDEO = 9, // HDR视频模式 362 | FUNCTION_MODE_INTERVAL_VIDEO = 10, // Interval视频模式 363 | FUNCTION_MODE_STATIC_TIMELAPSE = 11, // 延时视频模式 364 | FUNCTION_MODE_TIMESHIFT = 12, // Timeshift模式 365 | FUNCTION_MODE_LOOP_RECORDING_VIDEO = 17, // 循环录影模式 366 | }; 367 | 368 | // 这个结构体定义录制时的分辨率、帧率和码率 369 | struct RecordParams { 370 | VideoResolution resolution; 371 | int32_t bitrate{ 0 }; 372 | }; 373 | 374 | auto function_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_VIDEO; 375 | ins_camera::RecordParams record_params; 376 | // 设置5.7K60帧 377 | record_params.resolution = ins_camera::VideoResolution::RES_2880_2880P60; 378 | // 设置码率10MB,这个参数可能不生效,录制里面可能在某些挡位会写死码率 379 | record_params.bitrate = 1024 * 1024 * 10; 380 | if (!cam->SetVideoCaptureParams(record_params,function_mode )) { 381 | std::cerr << "failed to set capture settings." << std::endl; 382 | } 383 | ``` 384 | 385 | #### 曝光参数 386 | 387 | 参考 [曝光参数](#曝光参数) 388 | 389 | 390 | #### 白平衡参数 391 | 392 | 参数 [白平衡参数](#白平衡参数) 393 | 394 | ### 普通录制 395 | 396 | 普通录制可以通过以下参考代码进行演示 397 | 398 | #### 开始录制 399 | 400 | ```C++ 401 | // 1.将模式切换为视频普通模式 402 | bool ret = camera->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_NORMAL); 403 | if (!ret) { 404 | std::cout << "change sub mode failed!" << std::endl; 405 | continue; 406 | } 407 | 408 | // 2.设置当前的分辨率和帧率以及码率 409 | auto function_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_NORMAL_VIDEO; 410 | ins_camera::RecordParams record_params; 411 | // 设置5.7K60帧 412 | record_params.resolution = ins_camera::VideoResolution::RES_2880_2880P60; 413 | record_params.bitrate = 1024 * 1024 * 10; 414 | // 设置码率10MB,这个参数可能不生效,相机里面可能在某些挡位或者某些机型会写死码率,可以不进行设置 415 | if (!camera->SetVideoCaptureParams(record_params, function_mode)) { 416 | std::cerr << "failed to set capture settings." << std::endl; 417 | } 418 | else { 419 | // 3. 开始录制 420 | const auto ret = camera->StartRecording(); 421 | if (ret) { 422 | std::cerr << "success!" << std::endl; 423 | } 424 | else { 425 | std::cerr << "failed to start recording" << std::endl; 426 | } 427 | } 428 | ``` 429 | 430 | #### 停止录制 431 | 432 | ```C++ 433 | // 停止录制操作 434 | auto url = cam->StopRecording(); 435 | if (url.Empty()) { 436 | std::cerr << "stop recording failed" << std::endl; 437 | continue; 438 | } 439 | // 获取到录制素材在相机中地址 440 | auto& origins = url.OriginUrls(); 441 | std::cout << "stop recording success" << std::endl; 442 | for (auto& origin_url : origins) { 443 | std::cout << "url:" << origin_url << std::endl; 444 | } 445 | ``` 446 | 447 | ### Timelapse录制 448 | 449 | Timelapse录制可以通过以下参考代码进行演示: 450 | 451 | 这个表是timelapse下目前相机支持的分辨率帧率的枚举对应关系 452 | 453 | | 分辨率/帧率 | X4、X5 | X3 | ONE X2 | R | RS | ONE X | 454 | | :---------: | :--------------: | :--------------: | :----: | :--: | :--: | :---: | 455 | | **11K30** | RES_5632_5632P30 | 不支持 | Todo | Todo | Todo | Todo | 456 | | **8K30** | RES_3840_3840P30 | RES_3840_3840P30 | Todo | Todo | Todo | Todo | 457 | | **5.7K30** | RES_2880_2880P30 | RES_2880_2880P30 | Todo | Todo | Todo | Todo | 458 | 459 | #### 开始录制 460 | 461 | ```C++ 462 | // 1.将相机模式切换到timelapse模式 463 | bool ret = cam->SetVideoSubMode(ins_camera::SubVideoMode::VIDEO_TIMELAPSE); 464 | if (!ret) { 465 | std::cout << "change sub mode failed!" << std::endl; 466 | continue; 467 | } 468 | 469 | // 2. 设置当前模式的分辨率和帧率 470 | auto function_mode = ins_camera::CameraFunctionMode::FUNCTION_MODE_MOBILE_TIMELAPSE; 471 | ins_camera::RecordParams record_params; 472 | // 8K30的分辨率 473 | record_params.resolution = ins_camera::VideoResolution::RES_3840_3840P30; 474 | if (!cam->SetVideoCaptureParams(record_params, function_mode )) { 475 | std::cerr << "failed to set capture settings." << std::endl; 476 | break; 477 | } 478 | 479 | // 3. 设置延时摄影的参数 480 | auto timelapse_mode = ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO; 481 | const uint32_t record_duration_s = 10; // 拍摄时间为10秒 482 | const uint32_t lapseTime_ms = 1000; // 间隔时长为1秒 483 | ins_camera::TimelapseParam param = { timelapse_mode, 10,1000,0 }; 484 | if (!cam->SetTimeLapseOption(param)) { 485 | std::cerr << "failed to set capture settings." << std::endl; 486 | } 487 | else { 488 | // 4. 开始录制 489 | const auto ret = cam->StartTimeLapse(param.mode); 490 | if (ret) { 491 | std::cerr << "success!" << std::endl; 492 | } 493 | else { 494 | std::cerr << "failed to start timelapse" << std::endl; 495 | } 496 | } 497 | ``` 498 | 499 | #### 停止录制 500 | 501 | ```C++ 502 | auto timelapse_mode = ins_camera::CameraTimelapseMode::MOBILE_TIMELAPSE_VIDEO; 503 | auto url = cam->StopTimeLapse(timelapse_mode ); 504 | if (url.Empty()) { 505 | std::cerr << "stop timelapse failed" << std::endl; 506 | continue; 507 | } 508 | // 获取到录制素材在相机中地址 509 | auto& origins = url.OriginUrls(); 510 | std::cout << "stop timelapse success" << std::endl; 511 | for (auto& origin_url : origins) { 512 | std::cout << "url:" << origin_url << std::endl; 513 | } 514 | ``` 515 | 516 | ## 获取文件信息 517 | 518 | ### 获取文件个数 519 | 520 | 通过接口 **GetCameraFilesCount **获取当前相机SD卡中录制的文件个数 521 | 522 | ### 获取文件列表 523 | 524 | 通过接口 **GetCameraFilesList **获取当前相机SD卡中录制素材的列表.具体使用参考以下代码 525 | 526 | ```c++ 527 | auto file_list = camera->GetCameraFilesList(); 528 | for(const auto& file : file_list) { 529 | std::cout << file << std::endl; 530 | } 531 | 532 | //print output 533 | /DCIM/Camera01/VID_20250122_071405_00_001.insv 534 | /DCIM/Camera01/LRV_20250122_071405_01_001.lrv 535 | /DCIM/Camera01/VID_20250214_063916_00_002.insv 536 | /DCIM/Camera01/LRV_20250214_063916_01_002.lrv 537 | ``` 538 | 539 | ## 获取录制中的文件列表 540 | 541 | 通过接口 **GetRecordingFiles **可以当前相机中正在录制的文件名称 542 | 543 | ## 文件下载 544 | 545 | ### 下载文件 546 | 547 | 通过接口 `DownloadCameraFile` 可以将相机 SD 卡中已经存在的素材下载到本地。 548 | 549 | 通过设置回调可以获取当前文件的下载进度,这个接口是同步调用,下载完成或者下载失败后才能退出。以下是演示代码: 550 | 551 | > **注意:** 552 | > 553 | > 1. 在下载之前,确保创建好下载到本地的路径目录 554 | > 2. 由于在SDK中启动了HttpServer, 可能会存在端口占用导致服务启动失败的情况,SDK中提供了 **SetServicePort** 这个接口去避免这个问题。SDK中默认的端口号是 9099。端口占用的情况需要调用者去进行判断。如果有占用的情况,需要在**Open**接口调用前进行端口设置。 555 | 556 | ```C++ 557 | //相机的文件路径: 558 | std::string camera_file = "/DCIM/Camera01/VID_20250122_071405_00_001.insv"; 559 | //本地的文件路径: 560 | std::string local_save_file = "/path/to/local/VID_20250122_071405_00_001.insv"; 561 | 562 | //开始下载 563 | bool ret = camera->DownloadCameraFile(camera_file, local_save_file, [](int64_t current, int64_t total_size) { 564 | // 展示进度 565 | std::cout << "current :" << current << "; total_size: " << total_size << std::endl; 566 | }); 567 | 568 | // 下载结束 569 | if(ret) { 570 | std::cout << "successed to download file" << std::end; 571 | } 572 | ``` 573 | 574 | ### 取消下载 575 | 576 | 通过接口 **CancelDownload **可以取消正在下载的文件 577 | 578 | ## 删除文件 579 | 580 | 通过接口 **DeleteCameraFile **删除SD卡中不需要的文件 581 | 582 | ```C++ 583 | const auto camera_file = "/DCIM/Camera01/VID_20250122_071405_00_001.insv"; 584 | camera_file->DeleteCameraFile(camera_file); 585 | ``` 586 | 587 | ## 固件升级 588 | (仅适用于X4以及后续机型) 589 | 590 | 通过接口 **UploadFile **去进行固件版本的升级,目前仅适用于X4以及后续机型,固件的相机名称为:**Insta360X4FW.bin** 这个是定义好的. 下面是演示代码: 591 | 592 | ```c++ 593 | //固件名称 594 | const std::string fireware_name = "Insta360X4FW.bin"; 595 | std::string file_name = "Insta360X4FW.bin"; 596 | if (camera_type == ins_camera::CameraType::Insta360X5) { 597 | file_name = "Insta360X5FW.bin"; 598 | } 599 | 600 | const auto ret = cam->UploadFile(local_path, file_name, 601 | //固件的本地保存路径 602 | const std::string local_file = "/path/to/fireware/Insta360X4FW.bin"; 603 | 604 | // 开始上传 605 | bool ret = cam->UploadFile(local_file, fireware_name , 606 | [](int64_t current, int64_t total_size) { 607 | // 固件上传进度展示 608 | std::cout << "current :" << current << ";total_size: " << total_size << std::endl; 609 | }); 610 | 611 | if (ret) { 612 | std::cout << "succeed to Upload file !!!" << std::endl; 613 | } 614 | 615 | // 上传成功后,必须关闭相机,等待相机升级成功后重新创建相机实例(原因是相机升级需要重新启动) 616 | camera->close(); 617 | ``` 618 | 619 | ## 状态查询 620 | 621 | ### 电池状态信息 622 | 623 | 通过接口 **GetBatteryStatus **可以获取当前相机的电池信息,可以获取当前电池的使用情况,比如电池电量 624 | 625 | ```c++ 626 | //这些定义都有SDK的头文件中提供 627 | enum PowerType { 628 | BATTERY = 0, 629 | ADAPTER = 1, 630 | }; 631 | 632 | struct BatteryStatus { 633 | PowerType power_type; //电源类型 634 | uint32_t battery_level; //这个就是当前的电池电量(0~100) 635 | uint32_t battery_scale; //这个值无用 636 | }; 637 | 638 | BatteryStatus status; 639 | bool successed = camera->GetBatteryStatus(status); 640 | ``` 641 | 642 | ### SD卡存储信息 643 | 644 | 通过接口 **GetStorageState **可以获取到当前SD卡的状态. 可以获取当前SD卡的状态以及空间大小情况 645 | 646 | ```c++ 647 | //这些定义都有SDK的头文件中提供 648 | enum CardState { 649 | STOR_CS_PASS = 0, // SD卡可以正常使用 650 | STOR_CS_NOCARD = 1, // 相机中没有SD卡 651 | STOR_CS_NOSPACE = 2, // SD卡没有剩余空间 652 | STOR_CS_INVALID_FORMAT = 3,// SD卡的格式不对 653 | STOR_CS_WPCARD = 4, 654 | STOR_CS_OTHER_ERROR = 5 // 其他错误 655 | }; 656 | 657 | struct StorageStatus { 658 | CardState state; 659 | uint64_t free_space; // SD卡的剩余空间 660 | uint64_t total_space; // SD卡的总空间 661 | }; 662 | 663 | StorageStatus status; 664 | bool successed = camera->GetStorageState(status); 665 | ``` 666 | 667 | ### 当前相机捕获或者录制状态 668 | 669 | 通过接口 CaptureCurrentStatus 可以查询状态是否处于捕获或者录制状态。 670 | 671 | ```c++ 672 | auto ret= camera->CaptureCurrentStatus(); 673 | if (ret) { 674 | std::cout << "current statue : capture" << std::endl; 675 | } 676 | else { 677 | std::cout << "current statue : not capture" << std::endl; 678 | } 679 | ``` 680 | 681 | ### 相机信息通知 682 | 683 | 这部分的接口主要来自于相机的主动通知,涉及到低电量、SD卡满、相机高温以及相机录制异常中断 684 | 685 | ```c++ 686 | //这个接口用于通知当前相机电量低 687 | void SetBatteryLowNotification(BatteryLowCallBack callback); 688 | 689 | //这个接口用于通知当前相机SD卡已经满了 690 | void SetStorageFullNotification(StorageFullCallBack callback); 691 | 692 | //这个接口用于通知录制异常中断 693 | void SetCaptureStoppedNotification(CaptureStoppedCallBack callback); 694 | 695 | //这个接口用于通知相机温度过高 696 | void SetTemperatureHighNotification(TemperatureHighCallBack callback); 697 | ``` 698 | 699 | ## 预览流功能 700 | 701 | ### 设置预览流数据的委托接口 702 | 703 | 可以继承接口 **ins\_camera::StreamDelegate **来实现获取原始视频流、音频流、防抖数据以及曝光数据。可以参考一下代码: 704 | 705 | ```c++ 706 | class TestStreamDelegate : public ins_camera::StreamDelegate { 707 | public: 708 | TestStreamDelegate() {} 709 | 710 | // 音频数据的回调 711 | void OnAudioData(const uint8_t* data, size_t size, int64_t timestamp) override {} 712 | 713 | // 视频数据的回调 714 | void OnVideoData(const uint8_t* data, size_t size, int64_t timestamp, uint8_t streamType, int stream_index) override { 715 | if (stream_index == 0) { 716 | // 第一路视频 717 | } 718 | if (stream_index == 1) { 719 | // 第二路视频 720 | } 721 | } 722 | 723 | // 防抖数据的回调 724 | void OnGyroData(const std::vector& data) override {} 725 | 726 | // 曝光数据的回调 727 | void OnExposureData(const ins_camera::ExposureData& data) override {} 728 | 729 | }; 730 | ``` 731 | 732 | 1、对于视频数据,小于5.7k(5760x2280)的预览流只有一路视频,大于等于5.7k才有两路视频。数据的格式是h265或者h264编码的,可以通过接口 **GetVideoEncodeType **获取到当前相机的实际编码格式。通过编码格式创建解码器进行数据的解码,解码后的数据是没有进行拼接的,是两个鱼眼图片。一般情况下,预览流的分辨率都是1920x960的。 733 | 734 | 2、这个委托接口实现后,需要生成实例后,通过接口 **SetStreamDelegate **设置给相机实例。如下代码: 735 | 736 | ```c++ 737 | auto delegate = std::make_shared(); 738 | camera->SetStreamDelegate(delegate); 739 | ``` 740 | 741 | ### 开启预览流 742 | 743 | 可以通过设置预览流参数和接口 **StartLiveStreaming **开启预览流功能,对于预览流的分辨率,目前建议使用1920x960 744 | 745 | ```c++ 746 | ins_camera::LiveStreamParam param; 747 | param.video_resolution = ins_camera::VideoResolution::RES_1920_960P30; 748 | param.lrv_video_resulution = ins_camera::VideoResolution::RES_1920_960P30; 749 | param.video_bitrate = 1024 * 1024 / 2; 750 | param.enable_audio = false; 751 | param.using_lrv = false; 752 | if (cam->StartLiveStreaming(param)) { 753 | std::cout << "successfully started live stream" << std::endl; 754 | } 755 | ``` 756 | 757 | ### 关闭预览流 758 | 759 | 通过接口 **StopLiveStreaming **去关闭预览流功能. 760 | 761 | ## 日记功能 762 | 763 | ### 设置日记路径 764 | 765 | 这个接口主要用于设置SDK中的日记路径,可以保存SDK中的日记信息 766 | 767 | ```C++ 768 | void SetLogPath(const std::string log_path) 769 | ``` 770 | 771 | ### 设置日记打印等级 772 | 773 | 这个接口用于设置SDK中日记打印的等级 774 | 775 | ```C++ 776 | void SetLogLevel(LogLevel level) 777 | ``` 778 | 779 | ### 获取相机日记路径 780 | 781 | 这个接口用于获取相机中的日记路径,获取后可以通过下载接口将日记下载到本地 782 | 783 | ```C++ 784 | std::string GetCameraLogFileUrl() const; 785 | ``` 786 | 787 | ## 其他 788 | 789 | ### 获取相机mediaTime 790 | 791 | 这个接口可以获取相机中当前的media时间,可以和录制文件的文件尾信息做时间同步。 792 | 793 | ```C++ 794 | int64_t GetCameraMediaTime() 795 | ``` 796 | 797 | ### 切换相机镜头 SetActiveSensor 798 | 799 | 可以通过这个接口去进行镜头切换 800 | 801 | > SENSOR\_DEVICE\_FRONT(1) 切换到屏幕这边的镜头 802 | 803 | > SENSOR\_DEVICE\_REAR (2) 切换到屏幕后面的镜头 804 | 805 | > SENSOR\_DEVICE\_ALL (3) 切换到全景模式 806 | 807 | ### 关闭相机(仅支持X5之后的相机) 808 | 809 | ```C++ 810 | void ShutdownCamera() 811 | ``` 812 | --------------------------------------------------------------------------------