Beispiel #1
0
EbmlElement *
kax_file_c::read_one_element() {
  if (m_segment_end && (m_in.getFilePointer() >= m_segment_end))
    return nullptr;

  auto upper_lvl_el = 0;
  auto l1           = m_es->FindNextElement(EBML_CLASS_CONTEXT(KaxSegment), upper_lvl_el, 0xFFFFFFFFL, true);

  if (!l1)
    return nullptr;

  auto callbacks = find_ebml_callbacks(EBML_INFO(KaxSegment), EbmlId(*l1));
  if (!callbacks)
    callbacks = &EBML_CLASS_CALLBACK(KaxSegment);

  auto l2 = static_cast<EbmlElement *>(nullptr);
  try {
    l1->Read(*m_es.get(), EBML_INFO_CONTEXT(*callbacks), upper_lvl_el, l2, true);

  } catch (std::runtime_error &e) {
    mxdebug_if(m_debug_resync, boost::format("exception reading element data: %1%\n") % e.what());
    m_in.setFilePointer(l1->GetElementPosition() + 1);
    delete l1;
    return nullptr;
  }

  auto element_size = get_element_size(l1);
  if (m_debug_resync)
    mxinfo(boost::format("kax_file::read_one_element(): read element at %1% calculated size %2% stored size %3%\n")
           % l1->GetElementPosition() % element_size % (l1->IsFiniteSize() ? (boost::format("%1%") % l1->ElementSize()).str() : std::string("unknown")));
  m_in.setFilePointer(l1->GetElementPosition() + element_size, seek_beginning);

  return l1;
}
Beispiel #2
0
std::map<id_timecode_t, uint64_t>
cues_c::calculate_block_positions(KaxCluster &cluster)
  const {

  std::map<id_timecode_t, uint64_t> positions;

  for (auto child : cluster) {
    auto simple_block = dynamic_cast<KaxSimpleBlock *>(child);
    if (simple_block) {
      simple_block->SetParent(cluster);
      positions[ id_timecode_t{ simple_block->TrackNum(), simple_block->GlobalTimecode() } ] = simple_block->GetElementPosition();
      continue;
    }

    auto block_group = dynamic_cast<KaxBlockGroup *>(child);
    if (!block_group)
      continue;

    auto block = FindChild<KaxBlock>(block_group);
    if (!block)
      continue;

    block->SetParent(cluster);
    positions[ id_timecode_t{ block->TrackNum(), block->GlobalTimecode() } ] = block->GetElementPosition();
  }

  return positions;
}
Beispiel #3
0
uint64 EbmlVoid::ReplaceWith(EbmlElement & EltToReplaceWith, IOCallback & output, bool ComeBackAfterward, bool bWithDefault)
{
	EltToReplaceWith.UpdateSize(bWithDefault);
	if (HeadSize() + GetSize() < EltToReplaceWith.GetSize() + EltToReplaceWith.HeadSize()) {
		// the element can't be written here !
		return INVALID_FILEPOS_T;
	}
	if (HeadSize() + GetSize() - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() == 1) {
		// there is not enough space to put a filling element
		return INVALID_FILEPOS_T;
	}

	uint64 CurrentPosition = output.getFilePointer();

	output.setFilePointer(GetElementPosition());
	EltToReplaceWith.Render(output, bWithDefault);

	if (HeadSize() + GetSize() - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() > 1) {
	  // fill the rest with another void element
	  EbmlVoid aTmp;
	  aTmp.SetSize_(HeadSize() + GetSize() - EltToReplaceWith.GetSize() - EltToReplaceWith.HeadSize() - 1); // 1 is the length of the Void ID
	  int HeadBefore = aTmp.HeadSize();
	  aTmp.SetSize_(aTmp.GetSize() - CodedSizeLength(aTmp.GetSize(), aTmp.GetSizeLength(), aTmp.IsFiniteSize()));
	  int HeadAfter = aTmp.HeadSize();
	  if (HeadBefore != HeadAfter) {
		  aTmp.SetSizeLength(CodedSizeLength(aTmp.GetSize(), aTmp.GetSizeLength(), aTmp.IsFiniteSize()) - (HeadAfter - HeadBefore));
	  }
	  aTmp.RenderHead(output, false, bWithDefault); // the rest of the data is not rewritten
	}

	if (ComeBackAfterward) {
		output.setFilePointer(CurrentPosition);
	}

	return GetSize() + HeadSize();
}
Beispiel #4
0
uint64 KaxSegment::GetGlobalPosition(uint64 aRelativePosition) const
{
	return aRelativePosition + GetElementPosition() + HeadSize();
}
Beispiel #5
0
uint64 KaxSegment::GetRelativePosition(uint64 aGlobalPosition) const
{
	return aGlobalPosition - GetElementPosition() - HeadSize();
}
Beispiel #6
0
EbmlElement *
kax_file_c::read_next_level1_element_internal(uint32_t wanted_id) {
  if (m_segment_end && (m_in.getFilePointer() >= m_segment_end))
    return nullptr;

  m_resynced         = false;
  m_resync_start_pos = 0;

  // Read the next ID.
  auto search_start_pos = m_in.getFilePointer();
  auto actual_id        = vint_c::read_ebml_id(m_in);
  m_in.setFilePointer(search_start_pos, seek_beginning);

  if (m_debug_read_next)
    mxinfo(boost::format("kax_file::read_next_level1_element(): search at %1% for %|4$x| act id %|2$x| is_valid %3%\n") % search_start_pos % actual_id.m_value % actual_id.is_valid() % wanted_id);

  // If no valid ID was read then re-sync right away. No other tests
  // can be run.
  if (!actual_id.is_valid())
    return resync_to_level1_element(wanted_id);


  // Easiest case: next level 1 element following the previous one
  // without any element inbetween.
  if (   (wanted_id == actual_id.m_value)
      || (   (0 == wanted_id)
          && (   is_level1_element_id(actual_id)
              || is_global_element_id(actual_id)))) {
    auto l1 = read_one_element();
    if (l1)
      return l1;
  }

  // If a specific level 1 is wanted then look for next ID by skipping
  // other level 1 or special elements. If that files fallback to a
  // byte-for-byte search for the ID.
  if ((0 != wanted_id) && (is_level1_element_id(actual_id) || is_global_element_id(actual_id))) {
    m_in.setFilePointer(search_start_pos, seek_beginning);
    auto l1 = read_one_element();

    if (l1) {
      auto element_size = get_element_size(l1);
      auto ok           = (0 != element_size) && m_in.setFilePointer2(l1->GetElementPosition() + element_size, seek_beginning);

      if (m_debug_read_next)
        mxinfo(boost::format("kax_file::read_next_level1_element(): other level 1 element %1% new pos %2% fsize %3% epos %4% esize %5%\n")
               % EBML_NAME(l1)  % (l1->GetElementPosition() + element_size) % m_file_size
               % l1->GetElementPosition() % element_size);

      delete l1;

      return ok ? read_next_level1_element(wanted_id) : nullptr;
    }
  }

  // Last case: no valid ID found. Try a byte-for-byte search for the
  // next wanted/level 1 ID. Also try to locate at least three valid
  // ID/sizes, not just one ID.
  m_in.setFilePointer(search_start_pos, seek_beginning);
  return resync_to_level1_element(wanted_id);
}