Example #1
0
static vint_c
read_id(int64_t end_pos) {
  try {
    int64_t pos = g_in->getFilePointer();
    int mask    = 0x80;
    int id_len  = 1;

    if (pos >= end_pos)
      throw id_error_c(id_error_c::end_of_scope);

    unsigned char first_byte = g_in->read_uint8();

    while (0 != mask) {
      if (0 != (first_byte & mask))
        break;

      mask >>= 1;
      id_len++;
    }

    if (0 == mask)
      throw id_error_c(id_error_c::first_byte_is_zero);

    if (4 < id_len)
      throw id_error_c(id_error_c::longer_than_four_bytes);

    if ((pos + id_len) > end_pos)
      throw id_error_c(id_error_c::end_of_scope);

    uint32_t id = first_byte;
    int i;
    for (i = 1; i < id_len; ++i) {
      id <<= 8;
      id  |= g_in->read_uint8();
    }

    return vint_c(id, id_len);

  } catch (mtx::exception &error) {
    throw id_error_c(id_error_c::end_of_file);
  }
}
Example #2
0
static vint_c
read_size(int64_t end_pos) {
  try {
    int64_t pos  = g_in->getFilePointer();
    int mask     = 0x80;
    int size_len = 1;

    if (pos >= end_pos)
      throw size_error_c(size_error_c::end_of_scope);

    unsigned char first_byte = g_in->read_uint8();

    while (0 != mask) {
      if (0 != (first_byte & mask))
        break;

      mask >>= 1;
      size_len++;
    }

    if ((pos + size_len) > end_pos)
      throw size_error_c(size_error_c::end_of_scope);

    int64_t size = first_byte & ~mask;
    int i;
    for (i = 1; i < size_len; ++i) {
      size <<= 8;
      size  |= g_in->read_uint8();
    }

    return vint_c(size, size_len);

  } catch (mtx::exception &error) {
    throw size_error_c(size_error_c::end_of_file);
  }
}
Example #3
0
EbmlElement *
kax_file_c::resync_to_level1_element_internal(uint32_t wanted_id) {
  if (m_segment_end && (m_in->getFilePointer() >= m_segment_end))
    return nullptr;

  m_resynced         = true;
  m_resync_start_pos = m_in->getFilePointer();

  uint32_t actual_id = m_in->read_uint32_be();
  int64_t start_time = mtx::sys::get_current_time_millis();
  bool is_cluster_id = !wanted_id || (EBML_ID_VALUE(EBML_ID(KaxCluster)) == wanted_id); // 0 means: any level 1 element will do

  mxinfo(boost::format(Y("%1%: Error in the Matroska file structure at position %2%. Resyncing to the next level 1 element.\n"))
         % m_in->get_file_name() % m_resync_start_pos);

  if (is_cluster_id && (-1 != m_last_timecode)) {
    mxinfo(boost::format(Y("The last timecode processed before the error was encountered was %1%.\n")) % format_timecode(m_last_timecode));
    m_last_timecode = -1;
  }

  if (m_debug_resync)
    mxinfo(boost::format("kax_file::resync_to_level1_element(): starting at %1% potential ID %|2$08x|\n") % m_resync_start_pos % actual_id);

  while (m_in->getFilePointer() < m_file_size) {
    int64_t now = mtx::sys::get_current_time_millis();
    if ((now - start_time) >= 10000) {
      mxinfo(boost::format("Still resyncing at position %1%.\n") % m_in->getFilePointer());
      start_time = now;
    }

    actual_id = (actual_id << 8) | m_in->read_uint8();

    if (   ((0 != wanted_id) && (wanted_id != actual_id))
        || ((0 == wanted_id) && !is_level1_element_id(vint_c(actual_id, 4))))
      continue;

    uint64_t current_start_pos = m_in->getFilePointer() - 4;
    uint64_t element_pos       = current_start_pos;
    unsigned int num_headers   = 1;
    bool valid_unknown_size    = false;

    if (m_debug_resync)
      mxinfo(boost::format("kax_file::resync_to_level1_element(): byte-for-byte search, found level 1 ID %|2$x| at %1%\n") % current_start_pos % actual_id);

    try {
      unsigned int idx;
      for (idx = 0; 3 > idx; ++idx) {
        vint_c length = vint_c::read(m_in);

        if (m_debug_resync)
          mxinfo(boost::format("kax_file::resync_to_level1_element():   read ebml length %1%/%2% valid? %3% unknown? %4%\n")
                 % length.m_value % length.m_coded_size % length.is_valid() % length.is_unknown());

        if (length.is_unknown()) {
          valid_unknown_size = true;
          break;
        }

        if (   !length.is_valid()
            || ((element_pos + length.m_value + length.m_coded_size + 2 * 4) >= m_file_size)
            || !m_in->setFilePointer2(element_pos + 4 + length.m_value + length.m_coded_size, seek_beginning))
          break;

        element_pos      = m_in->getFilePointer();
        uint32_t next_id = m_in->read_uint32_be();

        if (m_debug_resync)
          mxinfo(boost::format("kax_file::resync_to_level1_element():   next ID is %|1$x| at %2%\n") % next_id % element_pos);

        if (   ((0 != wanted_id) && (wanted_id != next_id))
            || ((0 == wanted_id) && !is_level1_element_id(vint_c(next_id, 4))))
          break;

        ++num_headers;
      }
    } catch (...) {
    }

    if ((4 == num_headers) || valid_unknown_size) {
      mxinfo(boost::format(Y("Resyncing successful at position %1%.\n")) % current_start_pos);
      m_in->setFilePointer(current_start_pos, seek_beginning);
      return read_next_level1_element(wanted_id, is_cluster_id);
    }

    m_in->setFilePointer(current_start_pos + 4, seek_beginning);
  }

  mxinfo(Y("Resync failed: no valid Matroska level 1 element found.\n"));

  return nullptr;
}