std::vector<std::string> EbmlMaster::FindAllMissingElements() { assert(Context.GetSize() != 0); std::vector<std::string> missingElements; for (size_t ChildElementNo = 0; ChildElementNo < ElementList.size(); ChildElementNo++) { EbmlElement *childElement = ElementList[ChildElementNo]; if (!childElement->ValueIsSet()) { std::string missingValue; missingValue = "The Child Element \""; missingValue.append(EBML_NAME(childElement)); missingValue.append("\" of EbmlMaster \""); missingValue.append(EBML_NAME(this)); missingValue.append("\", does not have a value set."); missingElements.push_back(missingValue); } if (childElement->IsMaster()) { EbmlMaster *childMaster = (EbmlMaster *)childElement; std::vector<std::string> childMissingElements = childMaster->FindAllMissingElements(); for (size_t s = 0; s < childMissingElements.size(); s++) missingElements.push_back(childMissingElements[s]); } } unsigned int EltIdx; for (EltIdx = 0; EltIdx < EBML_CTX_SIZE(Context); EltIdx++) { if (EBML_CTX_IDX(Context,EltIdx).IsMandatory()) { if (FindElt(EBML_CTX_IDX_INFO(Context,EltIdx)) == NULL) { std::string missingElement; missingElement = "Missing element \""; missingElement.append(EBML_INFO_NAME(EBML_CTX_IDX_INFO(Context,EltIdx))); missingElement.append("\" in EbmlMaster \""); missingElement.append(EBML_INFO_NAME(*EBML_CTX_MASTER(Context))); missingElement.append("\""); missingElements.push_back(missingElement); } } } return missingElements; }
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. int64_t search_start_pos = m_in->getFilePointer(); vint_c 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)))) { EbmlElement *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); EbmlElement *l1 = read_one_element(); if (l1) { int64_t element_size = get_element_size(l1); bool 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); }