int parse_arguments()

in vireo/tools/transcode/main.cpp [164:381]


int parse_arguments(int argc, const char* argv[], Config& config) {
  int last_arg = 1;
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "-iterations") == 0) {
      int arg_iterations = atoi(argv[++i]);
      if (arg_iterations < 1 || arg_iterations > kMaxIterations) {
        cerr << "iterations must be between 1 and " << kMaxIterations << endl;
        return 1;
      }
      config.iterations = (int)arg_iterations;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-start") == 0) {
      int arg_start = atoi(argv[++i]);
      if (arg_start < 0) {
        cerr << "start cannot be non-negative" << endl;
        return 1;
      }
      config.start = (int)arg_start;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-duration") == 0) {
      int arg_duration = atoi(argv[++i]);
      if (arg_duration <= 0) {
        cerr << "duration must be positive" << endl;
        return 1;
      }
      config.duration = (int)arg_duration;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-height") == 0) {
      int arg_height = atoi(argv[++i]);
      if (arg_height < 0 || arg_height > 4096) {
        cerr << "height has to be positive and less than 4096" << endl;
        return 1;
      }
      config.height = (uint16_t)arg_height;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--square") == 0) {
      config.square = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "-optimization") == 0) {
      int arg_optimization = atoi(argv[++i]);
      if (arg_optimization < 0) {
        cerr << "optimization level has to be non-negative" << endl;
        return 1;
      }
      config.optimization = arg_optimization;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "-crf") == 0) {
      float arg_crf = atof(argv[++i]);
      if (arg_crf < encode::kH264MinCRF || arg_crf > encode::kH264MaxCRF) {
        cerr << "crf has to be between " << encode::kH264MinCRF << " - " << encode::kH264MaxCRF << endl;
        return 1;
      }
      config.crf = arg_crf;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "-quantizer") == 0) {
      int arg_quantizer = atoi(argv[++i]);
      if (arg_quantizer < encode::kVP8MinQuantizer || arg_quantizer > encode::kVP8MaxQuantizer) {
        cerr << "quantizer has to be between " << encode::kVP8MinQuantizer << " - " << encode::kVP8MaxQuantizer << endl;
        return 1;
      }
      config.quantizer = arg_quantizer;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-vbitrate") == 0) {
      int arg_video_bitrate = atoi(argv[++i]);
      if (arg_video_bitrate < 0) {
        cerr << "video bitrate has to be non-negative" << endl;
        return 1;
      }
      config.video_bitrate = (int)arg_video_bitrate;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-vmaxbitrate") == 0) {
      int arg_max_video_bitrate = atoi(argv[++i]);
      if (arg_max_video_bitrate < 0) {
        cerr << "video max bitrate has to be non-negative" << endl;
        return 1;
      }
      config.max_video_bitrate = (int)arg_max_video_bitrate;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-dthreads") == 0) {
      int arg_decoder_threads = atoi(argv[++i]);
      if (arg_decoder_threads < 0 || arg_decoder_threads > kMaxThreads) {
        cerr << "decoder thread count has to be between 1 and " << kMaxThreads << endl;
        return 1;
      }
      config.decoder_threads = (int)arg_decoder_threads;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-ethreads") == 0) {
      int arg_encoder_threads = atoi(argv[++i]);
      if (arg_encoder_threads < 0 || arg_encoder_threads > kMaxThreads) {
        cerr << "encoder thread count has to be between 1 and " << kMaxThreads << endl;
        return 1;
      }
      config.encoder_threads = (int)arg_encoder_threads;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--vonly") == 0) {
      config.video_only = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-abitrate") == 0) {
      int arg_audio_bitrate = atoi(argv[++i]);
      if (arg_audio_bitrate < 0) {
        cerr << "audio bitrate has to be non-negative" << endl;
        return 1;
      }
      config.audio_bitrate = (int)arg_audio_bitrate;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--aonly") == 0) {
      config.audio_only = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-bframes") == 0) {
      config.bframes = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--dashdata") == 0) {
      config.dash_data = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--dashinit") == 0) {
      config.dash_init = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--samplesonly") == 0) {
      config.samples_only = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-vprofile") == 0) {
      if (strcmp(argv[++i], "baseline") == 0) {
        config.vprofile = vireo::encode::VideoProfileType::Baseline;
      } else if (strcmp(argv[i], "main") == 0){
        config.vprofile = vireo::encode::VideoProfileType::Main;
      } else if (strcmp(argv[i], "high") == 0){
        config.vprofile = vireo::encode::VideoProfileType::High;
      } else {
        cerr << "only baseline, main or high profile is supported" << endl;
        return 1;
      }
    } else if (strcmp(argv[i], "-rc_method") == 0) {
      config.rc_method = (vireo::encode::RCMethod)atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-refs") == 0) {
      config.frame_references = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--mixed_refs") == 0) {
      config.mixed_refs = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-rc_look_ahead") == 0) {
      config.rc_look_ahead = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--2nd_pass") == 0) {
      config.is_second_pass = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-aq_mode") == 0) {
      auto mode = atoi(argv[++i]);
      config.aq_mode = encode::AdaptiveQuantizationMode(mode);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-trellis") == 0) {
      config.trellis = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-qp_min") == 0) {
      config.qp_min = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-keyint_max") == 0) {
      config.keyint_max = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-keyint_min") == 0) {
      config.keyint_min = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--rc_b_mb_tree") == 0) {
      config.rc_b_mb_tree = (bool)atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-stats_log_path") == 0) {
      config.stats_log_path = argv[++i];
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-fps") == 0) {
      config.fps = atoi(argv[++i]);
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-pyramid_mode") == 0) {
      config.pyramid_mode = encode::PyramidMode(atoi(argv[++i]));
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-me_method") == 0) {
      config.me_method = encode::MotionEstimationMethod(atoi(argv[++i]));
      last_arg = i + 1;
    } else if (strcmp(argv[i], "-subpel_refine") == 0) {
      config.subpel_refine = atoi(argv[++i]);
      last_arg = i + 1;
    }
  }
  if (last_arg + 1 >= argc) {
    cerr << "Need to specify infile and outfile" << endl;
    return 1;
  }
  config.infile = common::Path::MakeAbsolute(argv[last_arg]);
  config.outfile = common::Path::MakeAbsolute(argv[last_arg + 1]);

  struct ExtFileTypePair {
    string ext;
    FileType outfile_type;
  };
  const vector<ExtFileTypePair> ext_file_types = { {".mp4", MP4}, {".m4a", MP4}, {".m4v", MP4}, {".mov", MP4}, {".ts", MP2TS}, {".webm", WebM} };
  for (auto ext_file_type: ext_file_types) {
    auto ext = ext_file_type.ext;
    auto file_type = ext_file_type.outfile_type;
    if (config.outfile.find(ext) != string::npos) {
      config.outfile_type = file_type;
      break;
    }
  }
  if (config.outfile_type == UnknownFileType) {
    cerr << "Output content type is unknown" << endl;
    return 1;
  }

  auto max_optimization = (config.outfile_type == MP4 || config.outfile_type == MP2TS) ? encode::kH264MaxOptimization : encode::kVP8MaxOptimization;
  auto default_optimization = (config.outfile_type == MP4 || config.outfile_type == MP2TS) ? kH264DefaultOptimization : kVP8DefaultOptimization;
  if (config.optimization == -1) {
    config.optimization = default_optimization;
  } else if (config.optimization > max_optimization) {
    cerr << "optimization level has to be between 0 and " << max_optimization << endl;
    return 1;
  }

  return 0;
}