175int main(
int argc,
char** argv) {
176 std::string binary = GetFileName(std::string(argv[0]));
181 const std::string command(argv[1]);
182 std::string file_path;
184 file_path = std::string(argv[2]);
188 const std::string short_opts =
"f:c:k:o:alr:b:e:s:d:p:i:m:hCH";
189 static const struct option long_opts[] = {
190 {
"files", required_argument,
nullptr,
'f'},
191 {
"white-channel", required_argument,
nullptr,
'c'},
192 {
"black-channel", required_argument,
nullptr,
'k'},
193 {
"output", required_argument,
nullptr,
'o'},
194 {
"all", no_argument,
nullptr,
'a'},
195 {
"loop", no_argument,
nullptr,
'l'},
196 {
"rate", required_argument,
nullptr,
'r'},
197 {
"begin", required_argument,
nullptr,
'b'},
198 {
"end", required_argument,
nullptr,
'e'},
199 {
"start", required_argument,
nullptr,
's'},
200 {
"delay", required_argument,
nullptr,
'd'},
201 {
"preload", required_argument,
nullptr,
'p'},
202 {
"segment-interval", required_argument,
nullptr,
'i'},
203 {
"segment-size", required_argument,
nullptr,
'm'},
204 {
"help", no_argument,
nullptr,
'h'},
205 {
"cpu-profile", no_argument,
nullptr,
'C'},
206 {
"heap-profule", no_argument,
nullptr,
'H'}};
208 std::vector<std::string> opt_file_vec;
209 std::vector<std::string> opt_output_vec;
210 std::vector<std::string> opt_white_channels;
211 std::vector<std::string> opt_black_channels;
212 static bool enable_cpu_profile =
false;
213 static bool enable_heap_profile =
false;
214 bool opt_all =
false;
215 bool opt_loop =
false;
216 float opt_rate = 1.0f;
217 uint64_t opt_begin = 0;
218 uint64_t opt_end = std::numeric_limits<uint64_t>::max();
219 double opt_start = 0;
220 uint64_t opt_delay = 0;
221 uint32_t opt_preload = 3;
226 getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index);
232 enable_cpu_profile =
true;
235 enable_heap_profile =
true;
239 auto opt_file_abs_path =
242 opt_file_vec.emplace_back(opt_file_abs_path);
244 opt_file_vec.emplace_back(std::string(optarg));
247 opt_file_vec.emplace_back(std::string(optarg));
249 for (
int i = optind; i < argc; i++) {
250 if (*argv[i] !=
'-') {
253 "/" + std::string(argv[i]);
255 opt_file_vec.emplace_back(opt_file_abs_path);
257 opt_file_vec.emplace_back(std::string(argv[i]));
260 opt_file_vec.emplace_back(std::string(argv[i]));
268 opt_white_channels.emplace_back(std::string(optarg));
269 for (
int i = optind; i < argc; i++) {
270 if (*argv[i] !=
'-') {
271 opt_white_channels.emplace_back(std::string(argv[i]));
278 opt_black_channels.emplace_back(std::string(optarg));
279 for (
int i = optind; i < argc; i++) {
280 if (*argv[i] !=
'-') {
281 opt_black_channels.emplace_back(std::string(argv[i]));
289 auto opt_output_file_abs_path =
291 opt_output_vec.push_back(opt_output_file_abs_path);
293 opt_output_vec.push_back(std::string(optarg));
304 opt_rate = std::stof(optarg);
305 }
catch (
const std::invalid_argument& ia) {
306 std::cout <<
"Invalid argument: -r/--rate " << std::string(optarg)
309 }
catch (
const std::out_of_range& e) {
310 std::cout <<
"Argument is out of range: -r/--rate "
311 << std::string(optarg) << std::endl;
317 StringToUnixSeconds(std::string(optarg)) * 1000 * 1000 * 1000ULL;
321 StringToUnixSeconds(std::string(optarg)) * 1000 * 1000 * 1000ULL;
325 opt_start = std::stod(optarg);
326 }
catch (
const std::invalid_argument& ia) {
327 std::cout <<
"Invalid argument: -s/--start " << std::string(optarg)
330 }
catch (
const std::out_of_range& e) {
331 std::cout <<
"Argument is out of range: -s/--start "
332 << std::string(optarg) << std::endl;
338 opt_delay = std::stoi(optarg);
339 }
catch (std::invalid_argument& ia) {
340 std::cout <<
"Invalid argument: -d/--delay " << std::string(optarg)
343 }
catch (
const std::out_of_range& e) {
344 std::cout <<
"Argument is out of range: -d/--delay "
345 << std::string(optarg) << std::endl;
351 opt_preload = std::stoi(optarg);
352 }
catch (std::invalid_argument& ia) {
353 std::cout <<
"Invalid argument: -p/--preload " << std::string(optarg)
356 }
catch (
const std::out_of_range& e) {
357 std::cout <<
"Argument is out of range: -p/--preload "
358 << std::string(optarg) << std::endl;
364 int interval_s = std::stoi(optarg);
365 if (interval_s < 0) {
366 std::cout <<
"Argument is less than zero: -i/--segment-interval "
367 << std::string(optarg) << std::endl;
370 opt_header.set_segment_interval(interval_s * 1000000000ULL);
371 }
catch (std::invalid_argument& ia) {
372 std::cout <<
"Invalid argument: -i/--segment-interval "
373 << std::string(optarg) << std::endl;
375 }
catch (
const std::out_of_range& e) {
376 std::cout <<
"Argument is out of range: -i/--segment-interval "
377 << std::string(optarg) << std::endl;
383 int size_mb = std::stoi(optarg);
385 std::cout <<
"Argument is less than zero: -m/--segment-size "
386 << std::string(optarg) << std::endl;
389 opt_header.set_segment_raw_size(size_mb * 1024 * 1024ULL);
390 }
catch (std::invalid_argument& ia) {
391 std::cout <<
"Invalid argument: -m/--segment-size "
392 << std::string(optarg) << std::endl;
394 }
catch (
const std::out_of_range& e) {
395 std::cout <<
"Argument is out of range: -m/--segment-size "
396 << std::string(optarg) << std::endl;
409 if (command ==
"info") {
410 if (file_path.empty()) {
411 std::cout <<
"usage: cyber_recorder info file" << std::endl;
417 if (std::filesystem::exists(file_path_abs)) {
418 file_path = file_path_abs;
423 bool info_result = info.
Display(file_path);
424 return info_result ? 0 : -1;
425 }
else if (command ==
"recover") {
426 if (opt_file_vec.empty()) {
427 std::cout <<
"MUST specify file option (-f)." << std::endl;
430 if (opt_file_vec.size() > 1 || opt_output_vec.size() > 1) {
431 std::cout <<
"TOO many input/output file option (-f/-o)." << std::endl;
434 if (opt_output_vec.empty()) {
435 std::string default_output_file = opt_file_vec[0] +
".recover";
436 opt_output_vec.push_back(default_output_file);
439 Recoverer recoverer(opt_file_vec[0], opt_output_vec[0]);
440 bool recover_result = recoverer.
Proc();
441 return recover_result ? 0 : -1;
444 if (command ==
"play") {
445 if (opt_file_vec.empty()) {
446 std::cout <<
"MUST specify file option (-f)." << std::endl;
459 play_param.
files_to_play.insert(opt_file_vec.begin(), opt_file_vec.end());
461 opt_black_channels.end());
463 opt_white_channels.end());
464 Player player(play_param);
465 const bool play_result = player.
Init() && player.
Start();
466 return play_result ? 0 : -1;
467 }
else if (command ==
"record") {
468 if (opt_white_channels.empty() && !opt_all) {
470 <<
"MUST specify channels option (-c) or all channels option (-a)."
474 if (opt_output_vec.size() > 1) {
475 std::cout <<
"TOO many output file option (-o)." << std::endl;
478 if (opt_output_vec.empty()) {
479 std::string default_output_file =
481 UnixSecondsToString(time(
nullptr),
"%Y%m%d%H%M%S") +
".record";
482 opt_output_vec.push_back(default_output_file);
485 auto recorder = std::make_shared<Recorder>(opt_output_vec[0], opt_all,
487 opt_black_channels, opt_header);
488 std::signal(SIGTERM, [](
int sig) {
490 if (enable_cpu_profile) {
493 if (enable_heap_profile) {
494 HeapProfilerDump(
"Befor shutdown");
499 std::signal(SIGINT, [](
int sig) {
501 if (enable_cpu_profile) {
504 if (enable_heap_profile) {
505 HeapProfilerDump(
"Befor shutdown");
510 auto base_name = std::string(argv[0]) + std::string(
".prof");
511 if (enable_cpu_profile) {
512 ProfilerStart(base_name.c_str());
514 if (enable_heap_profile) {
515 HeapProfilerStart(base_name.c_str());
517 bool record_result = recorder->Start();
520 std::this_thread::sleep_for(std::chrono::milliseconds(100));
522 record_result = recorder->Stop();
524 return record_result ? 0 : -1;
525 }
else if (command ==
"split") {
526 if (opt_file_vec.empty()) {
527 std::cout <<
"Must specify file option (-f)." << std::endl;
530 if (opt_file_vec.size() > 1 || opt_output_vec.size() > 1) {
531 std::cout <<
"Too many input/output file option (-f/-o)." << std::endl;
534 if (opt_output_vec.empty()) {
535 std::string default_output_file = opt_file_vec[0] +
".split";
536 opt_output_vec.push_back(default_output_file);
539 Spliter spliter(opt_file_vec[0], opt_output_vec[0], opt_white_channels,
540 opt_black_channels, opt_begin, opt_end);
541 bool split_result = spliter.
Proc();
542 return split_result ? 0 : -1;