示例#1
0
bool
extract_cuesheet(kax_analyzer_c &analyzer,
                 options_c::mode_options_c &options) {
  KaxChapters all_chapters;
  auto chapters_m       = analyzer.read_all(EBML_INFO(KaxChapters));
  auto tags_m           = analyzer.read_all(EBML_INFO(KaxTags));
  KaxChapters *chapters = dynamic_cast<KaxChapters *>(chapters_m.get());
  KaxTags *all_tags     = dynamic_cast<KaxTags *>(    tags_m.get());

  if (!chapters || !all_tags)
    return true;

  for (auto chapter_entry : *chapters) {
    if (!dynamic_cast<KaxEditionEntry *>(chapter_entry))
      continue;

    auto eentry = static_cast<KaxEditionEntry *>(chapter_entry);
    for (auto edition_entry : *eentry)
      if (dynamic_cast<KaxChapterAtom *>(edition_entry))
        all_chapters.PushElement(*edition_entry);
  }

  write_cuesheet(analyzer.get_file().get_file_name(), all_chapters, *all_tags, -1, *open_output_file(options.m_output_file_name));

  while (all_chapters.ListSize() > 0)
    all_chapters.Remove(0);

  return true;
}
示例#2
0
bool
extract_tracks(kax_analyzer_c &analyzer,
               options_c::mode_options_c &options) {
  auto &tspecs = options.m_tracks;

  if (tspecs.empty())
    return false;

  // open input file
  auto &in          = analyzer.get_file();
  auto file         = std::make_shared<kax_file_c>(in);
  int64_t file_size = in.get_size();

  // open input file
  auto af_segment_info = ebml_master_cptr{ analyzer.read_all(EBML_INFO(KaxInfo)) };
  auto segment_info    = dynamic_cast<KaxInfo *>(af_segment_info.get());
  auto af_tracks       = ebml_master_cptr{ analyzer.read_all(EBML_INFO(KaxTracks)) };
  auto tracks          = dynamic_cast<KaxTracks *>(af_tracks.get());

  if (!segment_info || !tracks)
    return false;

  find_and_verify_track_uids(*tracks, tspecs);
  create_extractors(*tracks, tspecs);
  create_timestamp_files(*tracks, tspecs);

  try {
    in.setFilePointer(0);
    auto es = std::make_shared<EbmlStream>(in);

    // Find the EbmlHead element. Must be the first one.
    EbmlElement *l0 = es->FindNextID(EBML_INFO(EbmlHead), 0xFFFFFFFFL);
    if (!l0) {
      show_error(Y("Error: No EBML head found."));
      return false;
    }

    // Don't verify its data for now.
    l0->SkipData(*es, EBML_CONTEXT(l0));
    delete l0;

    while (1) {
      // Next element must be a segment
      l0 = es->FindNextID(EBML_INFO(KaxSegment), 0xFFFFFFFFFFFFFFFFLL);

      if (!l0) {
        show_error(Y("No segment/level 0 element found."));
        return false;
      }

      if (Is<KaxSegment>(l0))
        break;

      l0->SkipData(*es, EBML_CONTEXT(l0));
      delete l0;
    }

    auto previous_percentage = -1;
    auto tc_scale            = FindChildValue<KaxTimecodeScale, uint64_t>(segment_info, 1000000);

    file->set_timestamp_scale(tc_scale);
    file->set_segment_end(*l0);

    while (true) {
      auto cluster = std::unique_ptr<KaxCluster>{file->read_next_cluster()};
      if (!cluster)
        break;

      auto ctc = static_cast<KaxClusterTimecode *> (cluster->FindFirstElt(EBML_INFO(KaxClusterTimecode), false));
      cluster->InitTimecode(ctc ? ctc->GetValue() : 0, tc_scale);

      if (0 == verbose) {
        auto current_percentage = in.getFilePointer() * 100 / file_size;

        if (previous_percentage != static_cast<int>(current_percentage)) {
          if (mtx::cli::g_gui_mode)
            mxinfo(boost::format("#GUI#progress %1%%%\n") % current_percentage);
          else
            mxinfo(boost::format(Y("Progress: %1%%%%2%")) % current_percentage % "\r");

          previous_percentage = current_percentage;
        }
      }

      size_t i;
      int64_t max_timestamp = -1;

      for (i = 0; cluster->ListSize() > i; ++i) {
        int64_t max_bg_timestamp = -1;
        EbmlElement *el          = (*cluster)[i];

        if (Is<KaxBlockGroup>(el))
          max_bg_timestamp = handle_blockgroup(*static_cast<KaxBlockGroup *>(el), *cluster, tc_scale);

        else if (Is<KaxSimpleBlock>(el))
          max_bg_timestamp = handle_simpleblock(*static_cast<KaxSimpleBlock *>(el), *cluster);

        max_timestamp = std::max(max_timestamp, max_bg_timestamp);
      }

      if (-1 != max_timestamp)
        file->set_last_timestamp(max_timestamp);
    }

    delete l0;

    auto af_chapters = ebml_element_cptr{ analyzer.read_all(EBML_INFO(KaxChapters)) };
    auto chapters    = dynamic_cast<KaxChapters *>(af_chapters.get());

    auto af_tags     = ebml_element_cptr{ analyzer.read_all(EBML_INFO(KaxTags)) };
    auto tags        = dynamic_cast<KaxTags *>(af_tags.get());

    if (chapters && tags)
      write_all_cuesheets(*chapters, *tags, tspecs);

    // Now just close the files and go to sleep. Mummy will sing you a
    // lullaby. Just close your eyes, listen to her sweet voice, singing,
    // singing, fading... fad... ing...
    close_extractors();
    close_timestamp_files();

    if (0 == verbose) {
      if (mtx::cli::g_gui_mode)
        mxinfo(boost::format("#GUI#progress %1%%%\n") % 100);
      else
        mxinfo(boost::format(Y("Progress: %1%%%%2%")) % 100 % "\n");
    }

    return true;
  } catch (...) {
    show_error(Y("Caught exception"));

    return false;
  }
}