int main()

in vireo/tools/transcode/main.cpp [566:683]


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);

    // Process arguments
    if (config.video_only && config.audio_only) {
      cerr << "Only allow one of the --aonly --vonly parameters" << endl;
      return 1;
    } else if (config.video_only && movie.video_track.settings().timescale == 0) {
      cerr << "File does not contain a valid video track" << endl;
      return 1;
    } else if (config.audio_only && (movie.audio_track.settings().timescale == 0 || movie.audio_track.settings().sample_rate == 0)) {
      cerr << "File does not contain a valid audio track" << endl;
      return 1;
    } else if (config.dash_data && config.dash_init) {
      cerr << "Only allow one of the --dashdata --dashinit parameters" << endl;
      return 1;
    } else if (movie.video_track.settings().timescale == 0 && (movie.audio_track.settings().timescale == 0 || movie.audio_track.settings().sample_rate == 0)) {
      cerr << "File does not contain any audio / video tracks" << endl;
      return 1;
    }

    bool transcode_video = (config.audio_only || (movie.video_track.duration() == 0)) ? false : true;
    bool transcode_audio = (config.video_only || (movie.audio_track.duration() == 0)) ? false : true;
    THROW_IF(!transcode_video && !transcode_audio, Invalid);

    auto input_duration = transcode_video ? movie.video_track.duration() : movie.audio_track.duration();
    auto timescale = transcode_video ? movie.video_track.settings().timescale : movie.audio_track.settings().timescale;
    int input_duration_in_ms = 1000.0f * input_duration / timescale;
    int input_start_in_ms = 0;
    if (input_duration_in_ms) {
      auto input_start = transcode_video ? movie.video_track(0).pts : movie.audio_track(0).pts;
      input_start_in_ms = 1000.0f * input_start / timescale;
      THROW_IF(input_start_in_ms < 0, Unsupported);
    }
    int input_end_in_ms = input_start_in_ms + input_duration_in_ms;

    int end = (int)min(config.start + (uint64_t)config.duration, (uint64_t)numeric_limits<int>::max());
    config.start = max(config.start, input_start_in_ms);
    config.duration = max(min(end, input_end_in_ms) - config.start, 0);
    if (config.duration == 0) {
      cout << "No video content in the given time range" << endl;
      return 1;
    }

    // Main
    cout << "Transcoding " << (transcode_video ? (transcode_audio ? "video with audio" : "video") : "audio");
    cout << " of duration " << config.duration << " ms, starting from " << config.start << " ms" << endl;

    uint32_t i = 0;
    cout << Profile::Function("Transcoding", [&]{
      // Keep track of the first pts of the encoded tracks (could be either audio or video)
      FirstPtsAndTimescale first_pts_and_timescale;

      // Get output video track
      auto output_video_track = functional::Video<encode::Sample>();
      auto fps = (config.fps == -1) ? movie.video_track.fps() : config.fps;
      if (transcode_video) {
        output_video_track = transcode(movie.video_track, fps, movie.video_track.edit_boxes(), config, first_pts_and_timescale, i == 0);
      }

      // Get output audio track
      auto output_audio_track = functional::Audio<encode::Sample>();
      if (transcode_audio) {
        output_audio_track = transcode(movie.audio_track, movie.audio_track.edit_boxes(), config, first_pts_and_timescale, i == 0);
      }

      // Get output caption track
      auto output_caption_track = functional::Caption<encode::Sample>();
      if (transcode_video) {
        auto trimmed_caption = transform::Trim<SampleType::Caption>(movie.caption_track, movie.caption_track.edit_boxes(), config.start, config.duration);
        output_caption_track = functional::Caption<encode::Sample>(trimmed_caption.track, encode::Sample::Convert);
      }

      // Create necessary encoder
      functional::Function<common::Data32> encoder;
      if (config.outfile_type == MP4) {
        FileFormat format = FileFormat::Regular;
        if (config.dash_data) {
          format = FileFormat::DashData;
        } else if (config.dash_init) {
          format = FileFormat::DashInitializer;
        } else if (config.samples_only) {
          format = FileFormat::SamplesOnly;
        }
        encoder = mux::MP4(output_audio_track, output_video_track, output_caption_track, format);
      } else if (config.outfile_type == MP2TS) {
        encoder = mux::MP2TS(output_audio_track, output_video_track, output_caption_track);
      } else {
        encoder = mux::WebM(output_audio_track, output_video_track);
      }

      // Start encoding and save the output file once
      const string abs_dst = common::Path::MakeAbsolute(config.outfile);
      if (i == 0) {
        util::save(abs_dst, encoder());
      } else {
        encoder();
      }
      ++i;
    }, config.iterations) << endl;
  } __catch (std::exception& e) {
    cerr << "Error transcoding movie: " << e.what() << endl;
    return 1;
  }
  return 0;
}