int main()

in vireo/tools/remux/main.cpp [169:292]


int main(int argc, const char* argv[]) {
  __try {
    // Parse arguments
    if (argc < 3) {
      print_usage(common::Path::Filename(argv[0]));
      return 1;
    }
    Config config;
    if (parse_arguments(argc, argv, config)) {
      return 1;
    }

    // Read input file
    demux::Movie movie(config.infile);

    // Check input / output file format combinations to do remux
    auto infile_type = movie.file_type();
    if (infile_type != config.outfile_type && (infile_type == WebM || config.outfile_type == WebM)) {
      cerr << "Cannot remux from " << kFileTypeToString[infile_type] << " to " << kFileTypeToString[config.outfile_type] << endl;
      return 1;
    }

    // Process arguments
    if (config.video_only && config.audio_only) {
      cerr << "Cannot use video and audio only flags at the same time" << endl;
    } else if (config.video_only && movie.video_track.count() == 0) {
      cerr << "File does not contain a valid video track" << endl;
      return 1;
    } else if (config.audio_only && movie.audio_track.count() == 0) {
      cerr << "File does not contain a valid audio track" << endl;
      return 1;
    } else if (movie.video_track.count() == 0 && movie.audio_track.count() == 0) {
      cerr << "File does not contain any audio / video tracks" << endl;
      return 1;
    }
    bool remux_audio = (config.video_only || (movie.audio_track.count() == 0)) ? false : true;
    bool remux_video = (config.audio_only || (movie.video_track.count() == 0)) ? false : true;

    // Process GOP boundaries / arguments
    struct dts_pair {
      int64_t video;
      int64_t audio;
    };
    vector<dts_pair> dts_at_gop_boundaries;
    if (movie.video_track.count()) {
      for (const auto& sample: movie.video_track) {
        if (sample.keyframe) {
          int64_t video_dts = sample.dts;
          int64_t audio_dts = remux_audio ? common::round_divide((uint64_t)video_dts, (uint64_t)movie.audio_track.settings().timescale, (uint64_t)movie.video_track.settings().timescale) : 0;
          dts_at_gop_boundaries.push_back({ video_dts, audio_dts });
        }
      }
    } else {
      dts_at_gop_boundaries.push_back({ 0, movie.audio_track(0).dts });
    }
    int total_gops = (int)dts_at_gop_boundaries.size();
    dts_at_gop_boundaries.push_back({ numeric_limits<int64_t>::max(), numeric_limits<int64_t>::max() });

    if (config.start_gop >= total_gops) {
      cerr << "start gop has to be between 0 and " << total_gops << endl;
      return 1;
    }
    config.num_gops = min(config.num_gops, (int)total_gops - config.start_gop);

    // Main
    uint32_t i = 0;
    cout << Profile::Function("Remuxing", [&]{
      // Get start / end dts for video track
      auto start_dts_pair = dts_at_gop_boundaries[config.start_gop];
      auto end_dts_pair = dts_at_gop_boundaries[config.start_gop + config.num_gops];

      // Get output video track
      auto output_video_track = functional::Video<encode::Sample>();
      if (remux_video) {
        output_video_track = remux<SampleType::Video>(movie.video_track, config, start_dts_pair.video, end_dts_pair.video, i == 0);
      }

      // Get output audio track
      auto output_audio_track = functional::Audio<encode::Sample>();
      if (remux_audio) {
        output_audio_track = remux<SampleType::Audio>(movie.audio_track, config, start_dts_pair.audio, end_dts_pair.audio, i == 0);
      }

      // Get output caption track
      auto output_caption_track = functional::Caption<encode::Sample>();
      if (remux_video) {
        output_caption_track = remux<SampleType::Caption>(movie.caption_track, config, start_dts_pair.video, end_dts_pair.video, i == 0);
      }

      // Add edit boxes only if remuxing input file without any modifications
      vector<common::EditBox> edit_boxes;
      if (config.file_format == FileFormat::Regular && config.num_gops == total_gops) {
        if (remux_audio) {
          edit_boxes = movie.audio_track.edit_boxes();
        }
        if (remux_video) {
          edit_boxes.insert(edit_boxes.begin(), movie.video_track.edit_boxes().begin(), movie.video_track.edit_boxes().end());
        }
      }

      // Create muxer
      functional::Function<common::Data32> muxer;
      if (config.outfile_type == MP4) {
        muxer = mux::MP4(output_audio_track, output_video_track, output_caption_track, edit_boxes, config.file_format);
      } else if (config.outfile_type == MP2TS) {
        muxer = mux::MP2TS(output_audio_track, output_video_track, output_caption_track);
      } else {
        muxer = mux::WebM(output_audio_track, output_video_track);
      }

      // Save the output file once
      if (i == 0) {
        util::save(common::Path::MakeAbsolute(config.outfile), muxer());
      } else {
        muxer();
      }
      ++i;
    }, config.iterations) << endl;
  } __catch (std::exception& e) {
    cerr << "Error remuxing movie: " << e.what() << endl;
    return 1;
  }
  return 0;
}