int main()

in vireo/tools/frames/main.cpp [38:337]


int main(int argc, const char* argv[]) {
  if (argc < 2) {
    const string name = common::Path::Filename(argv[0]);
    cout << "Usage: " << name << " [options] input" << endl;
    cout << "\nOptions:" << endl;
    cout << "--audio:\tprint audio samples (default: false)" << endl;
    cout << "--video:\tprint video samples (default: false)" << endl;
    cout << "--data:\tprint data samples (default: false)" << endl;
    cout << "--samples:\tprint ordered list of samples (default: false)" << endl;
    return 1;
  }

  // Parse arguments
  int last_arg = 1;
  bool audio = false;
  bool video = false;
  bool data = false;
  bool samples = false;
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "--video") == 0) {
      video = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--audio") == 0) {
      audio = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--data") == 0) {
      data = true;
      last_arg = i + 1;
    } else if (strcmp(argv[i], "--samples") == 0) {
      samples = true;
      last_arg = i + 1;
    }
  }
  if (last_arg >= argc) {
    cerr << "Need to specify input file" << endl;
    return 1;
  }
  if ((audio | video) & samples) {
    cerr << "--samples cannot be used with --video or --audio" << endl;
    return 1;
  }

  const string seperator = ", ";
  const uint32_t bitrate_width = 2;
  const uint32_t bitrate_precision = 2;
  const uint32_t time_width = 3;
  const uint32_t time_precision = 3;

  auto print_sample = [seperator, time_precision, time_width](const decode::Sample& sample, uint64_t index, float play_time = -1) -> void {
    const uint32_t index_width = 5;
    const uint32_t pts_dts_width = 8;
    const uint32_t pos_width = 10;
    const uint32_t size_width = 8;
    if (index && sample.keyframe && sample.type == SampleType::Video) {
      cout << endl;
    }
    cout << "    ";
    cout << "SAMPLE";
    cout << " ";
    cout << std::setw(index_width) << index;
    cout << " :: ";
    cout << (sample.type == SampleType::Audio ? "AUDIO" : (sample.type == SampleType::Data ? "DATA" : "VIDEO"));
    cout << " :: ";
    if (sample.byte_range.available) {
      cout << "POS = " << std::setw(pos_width) << sample.byte_range.pos << " bytes";
      cout << seperator;
      cout << "SIZE = " << std::setw(size_width) << sample.byte_range.size << " bytes";
      cout << seperator;
    }
    cout << "PTS = " << std::setw(pts_dts_width) << sample.pts;
    cout << seperator;
    cout << "DTS = " << std::setw(pts_dts_width) << sample.dts;
    if (play_time >= 0) {
      cout << seperator;
      cout << "TIME = " << std::fixed << std::showpoint << std::setw(time_width + time_precision) << std::setprecision(time_precision) << play_time << " s";
    }
    if (sample.keyframe && sample.type == SampleType::Video) {
      cout << " : KEY";
    } else if (!sample.keyframe && sample.type == SampleType::Audio) {
      cout << " : NOT KEY";
    }
    cout << endl;
  };

  auto print_edit_boxes = [&seperator](const vector<vireo::common::EditBox>& edit_boxes) -> void {
    const uint32_t index_width = 1;
    const uint32_t pts_dts_width = 8;
    cout << endl;
    uint64_t index = 0;
    for (auto edit_box: edit_boxes) {
      cout << "    ";
      cout << "EDIT BOX ";
      cout << std::setw(index_width) << index;
      cout << " :: ";
      cout << "START PTS = " << std::setw(pts_dts_width) << edit_box.start_pts;
      cout << seperator;
      cout << "DURATION PTS = " << std::setw(pts_dts_width) << edit_box.duration_pts;
      cout << endl;
      ++index;
    }
    if (index == 0) {
      cout << "    ";
      cout << "NO EDIT BOXES" << endl;
    }
    cout << endl;
  };

  auto print_ordered_samples = [&print_sample](vector<decode::Sample>& samples) -> void {
    sort(samples.begin(), samples.end(), [](const decode::Sample& a, const decode::Sample& b){
      return a.byte_range.pos < b.byte_range.pos;
    });
    uint32_t a_index = 0;
    uint32_t v_index = 0;
    for (const auto& sample: samples) {
      THROW_IF(sample.type == SampleType::Data, Unsupported, "not implemented");
      uint32_t index = (sample.type == SampleType::Video) ? v_index++ : a_index++;
      print_sample(sample, index);
    }
  };

  auto print_video_track = [&](const functional::Video<decode::Sample>& video_track,
                               const uint64_t duration,
                               const vector<common::EditBox>& edit_boxes) -> void {
    const auto& settings = video_track.settings();
    cout << "  ";
    cout << "VIDEO TRACK";
    cout << " ::: ";
    cout << "WIDTH = " << settings.width;
    cout << seperator;
    cout << "HEIGHT = " << settings.height;
    cout << seperator;
    cout << "PAR WIDTH = " << settings.par_width;
    cout << seperator;
    cout << "PAR HEIGHT = " << settings.par_height;
    cout << seperator;
    cout << "CODED WIDTH = " << settings.coded_width;
    cout << seperator;
    cout << "CODED HEIGHT = " << settings.coded_height;
    cout << seperator;
    cout << "ORIENTATION = " << settings::kOrientationToString[settings.orientation];
    cout << seperator;
    cout << "TIMESCALE = " << settings.timescale;
    cout << seperator;
    cout << "DURATION = " << duration;
    float duration_in_sec = (float)duration / settings.timescale;
    cout << " (" << std::fixed << std::showpoint << std::setw(time_width + time_precision) << std::setprecision(time_precision) << duration_in_sec << " s)";
    if (duration) {
      // Calculate average bitrate
      uint64_t bytes = 0;
      for (const auto& sample: video_track) {
        bytes += sample.byte_range.available ? sample.byte_range.size : sample.nal().count();
      }
      const float bitrate = (float)bytes * settings.timescale * CHAR_BIT / (1000.0f * duration);
      cout << seperator;
      cout << "BITRATE = " << std::fixed << std::showpoint << std::setw(bitrate_width + bitrate_precision) << std::setprecision(bitrate_precision) << bitrate << " kbps";
    }
    cout << seperator;
    cout << "CODEC = " << settings::kVideoCodecToString[settings.codec];
    cout << endl;

    // Edit boxes and PTS/DTS info
    if (video) {
      print_edit_boxes(edit_boxes);
      uint64_t index = 0;
      for (const auto& sample: video_track) {
        float play_time = (float)common::EditBox::RealPts(edit_boxes, sample.pts) / settings.timescale;
        print_sample(sample, index++, play_time);
      }
    }
  };

  auto print_audio_track = [&](const functional::Audio<decode::Sample>& audio_track,
                               const uint64_t duration,
                               const vector<common::EditBox>& edit_boxes) -> void {
    const auto& settings = audio_track.settings();
    cout << "  ";
    cout << "AUDIO TRACK";
    cout << " ::: ";
    cout << "TIMESCALE= " << settings.timescale;
    cout << seperator;
    cout << "SAMPLE RATE = " << settings.sample_rate;
    cout << seperator;
    cout << "CHANNELS = " << (uint32_t)settings.channels;
    cout << seperator;
    cout << "DURATION = " << duration;
    float duration_in_sec = (float)duration / settings.timescale;
    cout << " (" << std::fixed << std::showpoint << std::setw(time_width + time_precision) << std::setprecision(time_precision) << duration_in_sec << " s)";
    if (duration) {
      // Calculate average bitrate
      uint64_t bytes = 0;
      for (const auto& sample: audio_track) {
        bytes += sample.byte_range.available ? sample.byte_range.size : sample.nal().count();
      }
      const float bitrate = (float)bytes * settings.timescale * CHAR_BIT / (1000.0f * duration);
      cout << seperator;
      cout << "BITRATE = " << std::fixed << std::showpoint << std::setprecision(bitrate_precision) << bitrate << " kbps";
    }
    cout << seperator;
    cout << "CODEC = " << settings::kAudioCodecToString[settings.codec];
    cout << endl;

    // Edit boxes and PTS/DTS info
    if (audio) {
      print_edit_boxes(edit_boxes);
      uint64_t index = 0;
      for (const auto& sample: audio_track) {
        float play_time = (float)common::EditBox::RealPts(edit_boxes, sample.pts) / settings.timescale;
        print_sample(sample, index++, play_time);
      }
    }
  };

  auto print_data_track = [&](const functional::Data<decode::Sample>& data_track) -> void {
    const auto& settings = data_track.settings();
    cout << "   ";
    cout << "DATA TRACK";
    cout << " ::: ";
    cout << "NUM SAMPLES = " << data_track.count();
    cout << seperator;
    cout << "CODEC = " << settings::kDataCodecToString[settings.codec];
    cout << endl;

    // Edit boxes and PTS/DTS info
    if (data) {
      cout << endl;
      uint64_t index = 0;
      for (const auto& sample: data_track) {
        float play_time = (float)sample.pts / settings.timescale;
        print_sample(sample, index++, play_time);
      }
    }
  };

  const string filename = common::Path::MakeAbsolute(argv[last_arg]);

  try {
    vireo::demux::Movie movie(filename);

    // File name
    cout << "GENERAL INFO :::: ";
    cout << "FILENAME = " << filename;
    cout << seperator;
    cout << "FILE TYPE = " << kFileTypeToString[movie.file_type()];
    cout << endl;

    if (samples) {
      cout << endl;
      auto samples = vector<decode::Sample>();
      for (const auto& sample: movie.audio_track) {
        if (!sample.byte_range.available) {
          cerr << "sample order unknown" << endl;
          return 1;
        }
        samples.push_back(sample);
      }
      for (const auto& sample: movie.video_track) {
        if (!sample.byte_range.available) {
          cerr << "sample order unknown" << endl;
          return 1;
        }
        samples.push_back(sample);
      }
      print_ordered_samples(samples);
    } else {
      // Video track
      if (movie.video_track.settings().timescale) {
        if (video) {
          cout << endl;
        }
        print_video_track(movie.video_track, movie.video_track.duration(), movie.video_track.edit_boxes());
      }

      // Audio track
      if (movie.audio_track.settings().sample_rate) {
        if (video && movie.video_track.settings().timescale) {
          cout << endl;
        }
        if (audio) {
          cout << endl;
        }
        print_audio_track(movie.audio_track, movie.audio_track.duration(), movie.audio_track.edit_boxes());
      }

      // Data track
      if (movie.data_track.settings().timescale) {
        if ((video && movie.video_track.settings().timescale) || (audio && movie.audio_track.settings().sample_rate)) {
          cout << endl;
        }
        if (data) {
          cout << endl;
        }
        print_data_track(movie.data_track);
      }
    }
  } catch (std::exception& e) {
    cerr << "Error analyzing movie " << e.what() << endl;
    return 1;
  }
  return 0;
}