172int main(
int argc,
char** argv) {
173 std::string binary = GetFileName(std::string(argv[0]));
178 const std::string command(argv[1]);
179 std::string file_path;
181 file_path = std::string(argv[2]);
185 const std::string short_opts =
"f:c:k:o:alr:b:e:s:d:p:i:m:hCH";
186 static const struct option long_opts[] = {
187 {
"files", required_argument,
nullptr,
'f'},
188 {
"white-channel", required_argument,
nullptr,
'c'},
189 {
"black-channel", required_argument,
nullptr,
'k'},
190 {
"output", required_argument,
nullptr,
'o'},
191 {
"all", no_argument,
nullptr,
'a'},
192 {
"loop", no_argument,
nullptr,
'l'},
193 {
"rate", required_argument,
nullptr,
'r'},
194 {
"begin", required_argument,
nullptr,
'b'},
195 {
"end", required_argument,
nullptr,
'e'},
196 {
"start", required_argument,
nullptr,
's'},
197 {
"delay", required_argument,
nullptr,
'd'},
198 {
"preload", required_argument,
nullptr,
'p'},
199 {
"segment-interval", required_argument,
nullptr,
'i'},
200 {
"segment-size", required_argument,
nullptr,
'm'},
201 {
"help", no_argument,
nullptr,
'h'},
202 {
"cpu-profile", no_argument,
nullptr,
'C'},
203 {
"heap-profule", no_argument,
nullptr,
'H'}};
205 std::vector<std::string> opt_file_vec;
206 std::vector<std::string> opt_output_vec;
207 std::vector<std::string> opt_white_channels;
208 std::vector<std::string> opt_black_channels;
209 static bool enable_cpu_profile =
false;
210 static bool enable_heap_profile =
false;
211 bool opt_all =
false;
212 bool opt_loop =
false;
213 float opt_rate = 1.0f;
214 uint64_t opt_begin = 0;
215 uint64_t opt_end = std::numeric_limits<uint64_t>::max();
216 double opt_start = 0;
217 uint64_t opt_delay = 0;
218 uint32_t opt_preload = 3;
223 getopt_long(argc, argv, short_opts.c_str(), long_opts, &long_index);
229 enable_cpu_profile =
true;
232 enable_heap_profile =
true;
235 opt_file_vec.emplace_back(std::string(optarg));
236 for (
int i = optind; i < argc; i++) {
237 if (*argv[i] !=
'-') {
238 opt_file_vec.emplace_back(std::string(argv[i]));
245 opt_white_channels.emplace_back(std::string(optarg));
246 for (
int i = optind; i < argc; i++) {
247 if (*argv[i] !=
'-') {
248 opt_white_channels.emplace_back(std::string(argv[i]));
255 opt_black_channels.emplace_back(std::string(optarg));
256 for (
int i = optind; i < argc; i++) {
257 if (*argv[i] !=
'-') {
258 opt_black_channels.emplace_back(std::string(argv[i]));
265 opt_output_vec.push_back(std::string(optarg));
275 opt_rate = std::stof(optarg);
276 }
catch (
const std::invalid_argument& ia) {
277 std::cout <<
"Invalid argument: -r/--rate " << std::string(optarg)
280 }
catch (
const std::out_of_range& e) {
281 std::cout <<
"Argument is out of range: -r/--rate "
282 << std::string(optarg) << std::endl;
288 StringToUnixSeconds(std::string(optarg)) * 1000 * 1000 * 1000ULL;
292 StringToUnixSeconds(std::string(optarg)) * 1000 * 1000 * 1000ULL;
296 opt_start = std::stod(optarg);
297 }
catch (
const std::invalid_argument& ia) {
298 std::cout <<
"Invalid argument: -s/--start " << std::string(optarg)
301 }
catch (
const std::out_of_range& e) {
302 std::cout <<
"Argument is out of range: -s/--start "
303 << std::string(optarg) << std::endl;
309 opt_delay = std::stoi(optarg);
310 }
catch (std::invalid_argument& ia) {
311 std::cout <<
"Invalid argument: -d/--delay " << std::string(optarg)
314 }
catch (
const std::out_of_range& e) {
315 std::cout <<
"Argument is out of range: -d/--delay "
316 << std::string(optarg) << std::endl;
322 opt_preload = std::stoi(optarg);
323 }
catch (std::invalid_argument& ia) {
324 std::cout <<
"Invalid argument: -p/--preload " << std::string(optarg)
327 }
catch (
const std::out_of_range& e) {
328 std::cout <<
"Argument is out of range: -p/--preload "
329 << std::string(optarg) << std::endl;
335 int interval_s = std::stoi(optarg);
336 if (interval_s < 0) {
337 std::cout <<
"Argument is less than zero: -i/--segment-interval "
338 << std::string(optarg) << std::endl;
341 opt_header.set_segment_interval(interval_s * 1000000000ULL);
342 }
catch (std::invalid_argument& ia) {
343 std::cout <<
"Invalid argument: -i/--segment-interval "
344 << std::string(optarg) << std::endl;
346 }
catch (
const std::out_of_range& e) {
347 std::cout <<
"Argument is out of range: -i/--segment-interval "
348 << std::string(optarg) << std::endl;
354 int size_mb = std::stoi(optarg);
356 std::cout <<
"Argument is less than zero: -m/--segment-size "
357 << std::string(optarg) << std::endl;
360 opt_header.set_segment_raw_size(size_mb * 1024 * 1024ULL);
361 }
catch (std::invalid_argument& ia) {
362 std::cout <<
"Invalid argument: -m/--segment-size "
363 << std::string(optarg) << std::endl;
365 }
catch (
const std::out_of_range& e) {
366 std::cout <<
"Argument is out of range: -m/--segment-size "
367 << std::string(optarg) << std::endl;
380 if (command ==
"info") {
381 if (file_path.empty()) {
382 std::cout <<
"usage: cyber_recorder info file" << std::endl;
387 bool info_result = info.
Display(file_path);
388 return info_result ? 0 : -1;
389 }
else if (command ==
"recover") {
390 if (opt_file_vec.empty()) {
391 std::cout <<
"MUST specify file option (-f)." << std::endl;
394 if (opt_file_vec.size() > 1 || opt_output_vec.size() > 1) {
395 std::cout <<
"TOO many input/output file option (-f/-o)." << std::endl;
398 if (opt_output_vec.empty()) {
399 std::string default_output_file = opt_file_vec[0] +
".recover";
400 opt_output_vec.push_back(default_output_file);
403 Recoverer recoverer(opt_file_vec[0], opt_output_vec[0]);
404 bool recover_result = recoverer.
Proc();
405 return recover_result ? 0 : -1;
408 if (command ==
"play") {
409 if (opt_file_vec.empty()) {
410 std::cout <<
"MUST specify file option (-f)." << std::endl;
423 play_param.
files_to_play.insert(opt_file_vec.begin(), opt_file_vec.end());
425 opt_black_channels.end());
427 opt_white_channels.end());
428 Player player(play_param);
429 const bool play_result = player.
Init() && player.
Start();
430 return play_result ? 0 : -1;
431 }
else if (command ==
"record") {
432 if (opt_white_channels.empty() && !opt_all) {
434 <<
"MUST specify channels option (-c) or all channels option (-a)."
438 if (opt_output_vec.size() > 1) {
439 std::cout <<
"TOO many output file option (-o)." << std::endl;
442 if (opt_output_vec.empty()) {
443 std::string default_output_file =
444 UnixSecondsToString(time(
nullptr),
"%Y%m%d%H%M%S") +
".record";
445 opt_output_vec.push_back(default_output_file);
448 auto recorder = std::make_shared<Recorder>(opt_output_vec[0], opt_all,
450 opt_black_channels, opt_header);
451 std::signal(SIGTERM, [](
int sig){
453 if (enable_cpu_profile) {
456 if (enable_heap_profile) {
457 HeapProfilerDump(
"Befor shutdown");
462 std::signal(SIGINT, [](
int sig){
464 if (enable_cpu_profile) {
467 if (enable_heap_profile) {
468 HeapProfilerDump(
"Befor shutdown");
473 auto base_name = std::string(argv[0]) + std::string(
".prof");
474 if (enable_cpu_profile) {
475 ProfilerStart(base_name.c_str());
477 if (enable_heap_profile) {
478 HeapProfilerStart(base_name.c_str());
480 bool record_result = recorder->Start();
483 std::this_thread::sleep_for(std::chrono::milliseconds(100));
485 record_result = recorder->Stop();
487 return record_result ? 0 : -1;
488 }
else if (command ==
"split") {
489 if (opt_file_vec.empty()) {
490 std::cout <<
"Must specify file option (-f)." << std::endl;
493 if (opt_file_vec.size() > 1 || opt_output_vec.size() > 1) {
494 std::cout <<
"Too many input/output file option (-f/-o)." << std::endl;
497 if (opt_output_vec.empty()) {
498 std::string default_output_file = opt_file_vec[0] +
".split";
499 opt_output_vec.push_back(default_output_file);
502 Spliter spliter(opt_file_vec[0], opt_output_vec[0], opt_white_channels,
503 opt_black_channels, opt_begin, opt_end);
504 bool split_result = spliter.
Proc();
505 return split_result ? 0 : -1;