/*!
 * \brief Parses the "EditionEntry"-element specified when constructing the object.
 *
 * Fetches the chapters() but does not parse them.
 *
 * Clears all previous parsing results.
 */
void MatroskaEditionEntry::parse(Diagnostics &diag)
{
    // clear previous values and status
    static const string context("parsing \"EditionEntry\"-element");
    clear();
    // iterate through children of "EditionEntry"-element
    EbmlElement *entryChild = m_editionEntryElement->firstChild();
    while (entryChild) {
        entryChild->parse(diag);
        switch (entryChild->id()) {
        case MatroskaIds::EditionUID:
            m_id = entryChild->readUInteger();
            break;
        case MatroskaIds::EditionFlagHidden:
            m_hidden = entryChild->readUInteger() == 1;
            break;
        case MatroskaIds::EditionFlagDefault:
            m_default = entryChild->readUInteger() == 1;
            break;
        case MatroskaIds::EditionFlagOrdered:
            m_ordered = entryChild->readUInteger() == 1;
            break;
        case MatroskaIds::ChapterAtom:
            m_chapters.emplace_back(make_unique<MatroskaChapter>(entryChild));
            break;
        default:
            diag.emplace_back(DiagLevel::Warning,
                "\"EditionEntry\"-element contains unknown child element \"" % entryChild->idToString() + "\" which will be ingored.", context);
        }
        entryChild = entryChild->nextSibling();
    }
}
Exemple #2
0
bool EbmlCrc32::CheckElementCRC32(EbmlElement &ElementToCRC)
{
	MemIOCallback memoryBuffer;
	ElementToCRC.Render(memoryBuffer);

	return CheckCRC(m_crc_final, memoryBuffer.GetDataBuffer(), memoryBuffer.GetDataBufferSize());
};
Exemple #3
0
void EbmlCrc32::AddElementCRC32(EbmlElement &ElementToCRC)
{
	// Use a special IOCallback class that Render's to memory instead of to disk
	MemIOCallback memoryBuffer;
	ElementToCRC.Render(memoryBuffer, true, true);

	Update(memoryBuffer.GetDataBuffer(), memoryBuffer.GetDataBufferSize());
//	Finalize();
};
ebml_master_cptr
kax_analyzer_c::read_all(const EbmlCallbacks &callbacks) {
  reopen_file();

  ebml_master_cptr master;
  EbmlStream es(*m_file);
  size_t i;

  for (i = 0; m_data.size() > i; ++i) {
    kax_analyzer_data_c &data = *m_data[i].get();
    if (EBML_INFO_ID(callbacks) != data.m_id)
      continue;

    m_file->setFilePointer(data.m_pos);
    int upper_lvl_el     = 0;
    EbmlElement *element = es.FindNextElement(EBML_CLASS_CONTEXT(KaxSegment), upper_lvl_el, 0xFFFFFFFFL, true);
    if (!element)
      continue;

    if (EbmlId(*element) != EBML_INFO_ID(callbacks)) {
      delete element;
      continue;
    }

    EbmlElement *l2 = nullptr;
    element->Read(*m_stream, EBML_INFO_CONTEXT(callbacks), upper_lvl_el, l2, true);

    if (!master)
      master = ebml_master_cptr(static_cast<EbmlMaster *>(element));
    else {
      EbmlMaster *src = static_cast<EbmlMaster *>(element);
      while (src->ListSize() > 0) {
        master->PushElement(*(*src)[0]);
        src->Remove(0);
      }
      delete element;
    }
  }

  if (master && (master->ListSize() == 0))
    master.reset();

  return master;
}
Exemple #5
0
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;
}
Exemple #6
0
uint64 EbmlVoid::Overwrite(const EbmlElement & EltToVoid, IOCallback & output, bool ComeBackAfterward, bool bWithDefault)
{
//	EltToVoid.UpdateSize(bWithDefault);
	if (EltToVoid.GetElementPosition() == 0) {
		// this element has never been written
		return 0;
	}
	if (EltToVoid.GetSize() + EltToVoid.HeadSize() <2) {
		// the element can't be written here !
		return 0;
	}

	uint64 CurrentPosition = output.getFilePointer();

	output.setFilePointer(EltToVoid.GetElementPosition());

	// compute the size of the voided data based on the original one
	SetSize(EltToVoid.GetSize() + EltToVoid.HeadSize() - 1); // 1 for the ID
	SetSize(GetSize() - CodedSizeLength(GetSize(), GetSizeLength(), IsFiniteSize()));
	// make sure we handle even the strange cases
	//uint32 A1 = GetSize() + HeadSize();
	//uint32 A2 = EltToVoid.GetSize() + EltToVoid.HeadSize();
	if (GetSize() + HeadSize() != EltToVoid.GetSize() + EltToVoid.HeadSize()) {
		SetSize(GetSize()-1);
		SetSizeLength(CodedSizeLength(GetSize(), GetSizeLength(), IsFiniteSize()) + 1);
	}

	if (GetSize() != 0) {
		RenderHead(output, false, bWithDefault); // the rest of the data is not rewritten
	}

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

	return EltToVoid.GetSize() + EltToVoid.HeadSize();
}
Exemple #7
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();
}
Exemple #8
0
void matroska_segment_c::LoadTags( KaxTags *tags )
{
    /* Master elements */
    EbmlParser eparser = EbmlParser( &es, tags, &sys.demuxer, true );
    EbmlElement *el;

    while( ( el = eparser.Get() ) != NULL )
    {
        if( MKV_IS_ID( el, KaxTag ) )
        {
            Tag tag;

            msg_Dbg( &sys.demuxer, "+ Tag" );
            eparser.Down();
            int target_type = 50;
            while( ( el = eparser.Get() ) != NULL )
            {
                if( MKV_IS_ID( el, KaxTagTargets ) )
                {
                    msg_Dbg( &sys.demuxer, "|   + Targets" );
                    eparser.Down();
                    while( ( el = eparser.Get() ) != NULL )
                    {
                        try
                        {
                            if( unlikely( !el->ValidateSize() ) )
                            {
                                msg_Err( &sys.demuxer, "Invalid size while reading tag");
                                break;
                            }
                            if( MKV_CHECKED_PTR_DECL ( ktttv_ptr, KaxTagTargetTypeValue, el ) )
                            {
                                ktttv_ptr->ReadData( es.I_O() );

                                msg_Dbg( &sys.demuxer, "|   |   + TargetTypeValue: %u", uint32(*ktttv_ptr));
                                target_type = static_cast<uint32>( *ktttv_ptr );
                            }
                            else if( MKV_CHECKED_PTR_DECL ( kttu_ptr, KaxTagTrackUID, el ) )
                            {
                                tag.i_tag_type = TRACK_UID;
                                kttu_ptr->ReadData( es.I_O() );
                                tag.i_uid = static_cast<uint64>( *kttu_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + TrackUID: %" PRIu64, tag.i_uid);

                            }
                            else if( MKV_CHECKED_PTR_DECL ( kteu_ptr, KaxTagEditionUID, el ) )
                            {
                                tag.i_tag_type = EDITION_UID;
                                kteu_ptr->ReadData( es.I_O() );
                                tag.i_uid = static_cast<uint64>( *kteu_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + EditionUID: %" PRIu64, tag.i_uid);
                            }
                            else if( MKV_CHECKED_PTR_DECL ( ktcu_ptr, KaxTagChapterUID, el ) )
                            {
                                tag.i_tag_type = CHAPTER_UID;
                                ktcu_ptr->ReadData( es.I_O() );
                                tag.i_uid = static_cast<uint64>( *ktcu_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + ChapterUID: %" PRIu64, tag.i_uid);
                            }
                            else if( MKV_CHECKED_PTR_DECL ( ktau_ptr, KaxTagAttachmentUID, el ) )
                            {
                                tag.i_tag_type = ATTACHMENT_UID;
                                ktau_ptr->ReadData( es.I_O() );
                                tag.i_uid = static_cast<uint64>( *ktau_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + AttachmentUID: %" PRIu64, tag.i_uid);
                            }
                            else
                            {
                                msg_Dbg( &sys.demuxer, "|   |   + LoadTag Unknown (%s)", typeid( *el ).name() );
                            }
                        }
                        catch(...)
                        {
                            msg_Err( &sys.demuxer, "Error while reading tag");
                            break;
                        }
                    }
                    eparser.Up();
                }
                else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el ) )
                {
                    SimpleTag simple;

                    if (ParseSimpleTags(&simple, kts_ptr, target_type )) {
                      tag.simple_tags.push_back( simple );
                    }
                }
                else
                {
                    msg_Dbg( &sys.demuxer, "|   + LoadTag Unknown (%s)", typeid( *el ).name() );
                }
            }
            eparser.Up();
            this->tags.push_back(tag);
        }
        else
        {
            msg_Dbg( &sys.demuxer, "+ Unknown (%s)", typeid( *el ).name() );
        }
    }

    msg_Dbg( &sys.demuxer, "loading tags done." );
}
Exemple #9
0
bool matroska_segment_c::ParseSimpleTags( SimpleTag* pout_simple, KaxTagSimple *tag, int target_type )
{
    EbmlParser eparser ( &es, tag, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) );
    EbmlElement *el;
    size_t max_size = tag->GetSize();
    size_t size = 0;

    if( !sys.meta )
        sys.meta = vlc_meta_New();

    msg_Dbg( &sys.demuxer, "|   + Simple Tag ");
    try
    {
        while( ( el = eparser.Get() ) != NULL && size < max_size)
        {
            if( unlikely( !el->ValidateSize() ) )
            {
                msg_Err( &sys.demuxer, "Error %s too big ignoring the tag", typeid(*el).name() );
                delete ep;
                return false;
            }
            if( MKV_CHECKED_PTR_DECL ( ktn_ptr, KaxTagName, el ) )
            {
                ktn_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
                pout_simple->tag_name = UTFstring( *ktn_ptr ).GetUTF8().c_str();
            }
            else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagString, el ) )
            {
                kts_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
                pout_simple->value = UTFstring( *kts_ptr ).GetUTF8().c_str();
            }
            else if(  MKV_CHECKED_PTR_DECL ( ktl_ptr, KaxTagLangue, el ) )
            {
                ktl_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
                pout_simple->lang = *ktl_ptr;
            }
            else if(  MKV_CHECKED_PTR_DECL ( ktd_ptr, KaxTagDefault, el ) )
            {
                VLC_UNUSED(ktd_ptr); // TODO: we do not care about this value, but maybe we should?
            }
            /*Tags can be nested*/
            else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el) )
            {
                SimpleTag st; // ParseSimpleTags will write to this variable
                              // the SimpleTag is valid if ParseSimpleTags returns `true`

                if (ParseSimpleTags( &st, kts_ptr, target_type )) {
                  pout_simple->sub_tags.push_back( st );
                }
            }
            /*TODO Handle binary tags*/
            size += el->HeadSize() + el->GetSize();
        }
    }
    catch(...)
    {
        msg_Err( &sys.demuxer, "Error while reading Tag ");
        delete ep;
        return false;
    }

    if( pout_simple->tag_name.empty() )
    {
        msg_Warn( &sys.demuxer, "Invalid MKV SimpleTag found.");
        return false;
    }
    for( int i = 0; metadata_map[i].key; i++ )
    {
        if( pout_simple->tag_name == metadata_map[i].key &&
            (metadata_map[i].target_type == 0 || target_type == metadata_map[i].target_type ) )
        {
            vlc_meta_Set( sys.meta, metadata_map[i].type, pout_simple->value.c_str () );
            msg_Dbg( &sys.demuxer, "|   |   + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
            goto done;
        }
    }
    msg_Dbg( &sys.demuxer, "|   |   + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
    vlc_meta_AddExtra( sys.meta, pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
done:
    return true;
}
Exemple #10
0
/*****************************************************************************
 * Tools                                                                     *
 *****************************************************************************
 *  * LoadCues : load the cues element and update index
 *  * LoadTags : load ... the tags element
 *  * InformationCreate : create all information, load tags if present
 *****************************************************************************/
void matroska_segment_c::LoadCues( KaxCues *cues )
{
    EbmlElement *el;

    if( b_cues )
    {
        msg_Err( &sys.demuxer, "There can be only 1 Cues per section." );
        return;
    }

    EbmlParser eparser (&es, cues, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) );
    while( ( el = eparser.Get() ) != NULL )
    {
        if( MKV_IS_ID( el, KaxCuePoint ) )
        {
            uint64_t cue_position = -1;
            mtime_t  cue_mk_time = -1;

            unsigned int track_id = 0;
            bool b_invalid_cue = false;

            eparser.Down();
            while( ( el = eparser.Get() ) != NULL )
            {
                if ( MKV_CHECKED_PTR_DECL( kct_ptr, KaxCueTime, el ) )
                {
                    try
                    {
                        if( unlikely( !kct_ptr->ValidateSize() ) )
                        {
                            msg_Err( &sys.demuxer, "CueTime size too big");
                            b_invalid_cue = true;
                            break;
                        }
                        kct_ptr->ReadData( es.I_O() );
                    }
                    catch(...)
                    {
                        msg_Err( &sys.demuxer, "Error while reading CueTime" );
                        b_invalid_cue = true;
                        break;
                    }
                    cue_mk_time = static_cast<uint64>( *kct_ptr ) * i_timescale / INT64_C(1000);
                }
                else if( MKV_IS_ID( el, KaxCueTrackPositions ) )
                {
                    eparser.Down();
                    try
                    {
                        while( ( el = eparser.Get() ) != NULL )
                        {
                            if( unlikely( !el->ValidateSize() ) )
                            {
                                eparser.Up();
                                msg_Err( &sys.demuxer, "Error %s too big, aborting", typeid(*el).name() );
                                b_invalid_cue = true;
                                break;
                            }

                            if( MKV_CHECKED_PTR_DECL ( kct_ptr, KaxCueTrack, el ) )
                            {
                                kct_ptr->ReadData( es.I_O() );
                                track_id = static_cast<uint16>( *kct_ptr );
                            }
                            else if( MKV_CHECKED_PTR_DECL ( kccp_ptr, KaxCueClusterPosition, el ) )
                            {
                                kccp_ptr->ReadData( es.I_O() );
                                cue_position = segment->GetGlobalPosition( static_cast<uint64>( *kccp_ptr ) );

                                _seeker.add_cluster_position( cue_position );
                            }
                            else if( MKV_CHECKED_PTR_DECL ( kcbn_ptr, KaxCueBlockNumber, el ) )
                            {
                                VLC_UNUSED( kcbn_ptr );
                            }
#if LIBMATROSKA_VERSION >= 0x010401
                            else if( MKV_IS_ID( el, KaxCueRelativePosition ) )
                            {
                                b_invalid_cue = true; // since we do not support this type of cue: IGNORE
                            }
                            else if( MKV_IS_ID( el, KaxCueBlockNumber ) )
                            {
                                b_invalid_cue = true; // since we do not support this type of cue: IGNORE
                            }
                            else if( MKV_IS_ID( el, KaxCueReference ) )
                            {
                                b_invalid_cue = true; // since we do not support this type of cue: IGNORE
                            }
                            else if( MKV_IS_ID( el, KaxCueDuration ) )
                            {
                                /* For future use */
                            }
#endif
                            else
                            {
                                msg_Dbg( &sys.demuxer, "         * Unknown (%s)", typeid(*el).name() );
                            }
                        }
                    }
                    catch(...)
                    {
                        eparser.Up();
                        msg_Err( &sys.demuxer, "Error while reading %s", typeid(*el).name() );
                        b_invalid_cue = true;
                        break;
                    }
                    eparser.Up();
                }
                else
                {
                    msg_Dbg( &sys.demuxer, "     * Unknown (%s)", typeid(*el).name() );
                }
            }
            eparser.Up();

            if( track_id != 0 && cue_mk_time != -1 && cue_position != static_cast<uint64_t>( -1 ) ) {

                if( tracks.find( track_id ) != tracks.end() )
                {
                    int level = SegmentSeeker::Seekpoint::DISABLED;

                    if( ! b_invalid_cue )
                    {
                        level = SegmentSeeker::Seekpoint::QUESTIONABLE; // TODO: var_InheritBool( ..., "mkv-trust-cues" );
                    }

                    _seeker.add_seekpoint( track_id, level, cue_position, cue_mk_time );
                }
                else
                    msg_Warn( &sys.demuxer, "Found cue with invalid track id = %u", track_id );
            }
        }
        else
        {
            msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
        }
    }
    b_cues = true;
    msg_Dbg( &sys.demuxer, "|   - loading cues done." );
}
Exemple #11
0
uint64 KaxSegment::GetRelativePosition(const EbmlElement & Elt) const
{
	return GetRelativePosition(Elt.GetElementPosition());
}
/*!
 * \brief Parses field information from the specified EbmlElement.
 *
 * The specified atom should be a simple tag element. These elements
 * represents the fields of a MatroskaTag.
 *
 * \throws Throws std::ios_base::failure when an IO error occurs.
 * \throws Throws TagParser::Failure or a derived exception when a parsing
 *         error occurs.
 */
void MatroskaTagField::reparse(EbmlElement &simpleTagElement, Diagnostics &diag, bool parseNestedFields)
{
    string context("parsing Matroska tag field");
    simpleTagElement.parse(diag);
    bool tagDefaultFound = false;
    for (EbmlElement *child = simpleTagElement.firstChild(); child; child = child->nextSibling()) {
        try {
            child->parse(diag);
        } catch (const Failure &) {
            diag.emplace_back(DiagLevel::Critical, "Unable to parse children of \"SimpleTag\"-element.", context);
            break;
        }
        switch (child->id()) {
        case MatroskaIds::TagName:
            if (id().empty()) {
                setId(child->readString());
                context = "parsing Matroska tag field " + id();
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagName\"-elements. Surplus TagName elements will be ignored.", context);
            }
            break;
        case MatroskaIds::TagString:
        case MatroskaIds::TagBinary:
            if (value().isEmpty()) {
                unique_ptr<char[]> buffer = make_unique<char[]>(child->dataSize());
                child->stream().seekg(static_cast<streamoff>(child->dataOffset()));
                child->stream().read(buffer.get(), static_cast<streamoff>(child->dataSize()));
                switch (child->id()) {
                case MatroskaIds::TagString:
                    value().assignData(move(buffer), child->dataSize(), TagDataType::Text, TagTextEncoding::Utf8);
                    break;
                case MatroskaIds::TagBinary:
                    value().assignData(move(buffer), child->dataSize(), TagDataType::Undefined);
                    break;
                }
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagString\"/\"TagBinary\"-elements. Surplus \"TagName\"/\"TagBinary\"-elements will "
                    "be ignored.",
                    context);
            }
            break;
        case MatroskaIds::TagLanguage:
            if (value().language().empty() || value().language() == "und") {
                string lng = child->readString();
                if (lng != "und") {
                    value().setLanguage(lng);
                }
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagLanguage\"-elements. Surplus \"TagLanguage\"-elements will be ignored.", context);
            }
            break;
        case MatroskaIds::TagDefault:
            if (!tagDefaultFound) {
                setDefault(child->readUInteger() > 0);
                tagDefaultFound = true;
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "\"SimpleTag\"-element contains multiple \"TagDefault\" elements. Surplus \"TagDefault\"-elements will be ignored.", context);
            }
            break;
        case MatroskaIds::SimpleTag:
            if (parseNestedFields) {
                nestedFields().emplace_back();
                nestedFields().back().reparse(*child, diag, true);
            } else {
                diag.emplace_back(DiagLevel::Warning,
                    "Nested fields are currently not supported. Nested tags can not be displayed and will be discarded when rewriting the file.",
                    context);
            }
            break;
        case EbmlIds::Crc32:
        case EbmlIds::Void:
            break;
        default:
            diag.emplace_back(DiagLevel::Warning,
                argsToString(
                    "\"SimpleTag\"-element contains unknown element ", child->idToString(), " at ", child->startOffset(), ". It will be ignored."),
                context);
        }
    }
}
Exemple #13
0
void
kax_file_c::set_segment_end(EbmlElement const &segment) {
  m_segment_end = segment.IsFiniteSize() ? segment.GetElementPosition() + segment.HeadSize() + segment.GetSize() : m_in->get_size();
}
Exemple #14
0
/*!
	\brief Method to help reading a Master element and all subsequent children quickly
	\todo add an option to discard even unknown elements
	\todo handle when a mandatory element is not found
*/
void EbmlMaster::Read(EbmlStream & inDataStream, const EbmlSemanticContext & sContext, int & UpperEltFound, EbmlElement * & FoundElt, bool AllowDummyElt, ScopeMode ReadFully)
{
	if (ReadFully != SCOPE_NO_DATA)
	{
		EbmlElement * ElementLevelA;
		// remove all existing elements, including the mandatory ones...
		size_t Index;
		for (Index=0; Index<ElementList.size(); Index++) {
			if (!(*ElementList[Index]).IsLocked()) {
				delete ElementList[Index];
			}
		}
		ElementList.clear();
		uint64 MaxSizeToRead;

		if (IsFiniteSize())
			MaxSizeToRead = GetSize();
		else
			MaxSizeToRead = 0x7FFFFFFF;

		// read blocks and discard the ones we don't care about
		if (MaxSizeToRead > 0)
		{
			inDataStream.I_O().setFilePointer(GetSizePosition() + GetSizeLength(), seek_beginning);
			ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
			while (ElementLevelA != NULL && UpperEltFound <= 0 && MaxSizeToRead > 0) {
				if (IsFiniteSize())
					MaxSizeToRead = GetEndPosition() - ElementLevelA->GetEndPosition(); // even if it's the default value
				if (!AllowDummyElt && ElementLevelA->IsDummy()) {
					ElementLevelA->SkipData(inDataStream, sContext);
					delete ElementLevelA; // forget this unknown element
				} else {
					// more logical to do it afterward
					ElementList.push_back(ElementLevelA);

					ElementLevelA->Read(inDataStream, EBML_CONTEXT(ElementLevelA), UpperEltFound, FoundElt, AllowDummyElt, ReadFully);

					// just in case
					ElementLevelA->SkipData(inDataStream, EBML_CONTEXT(ElementLevelA));
				}

				if (UpperEltFound > 0) {
					UpperEltFound--;
					if (UpperEltFound > 0 || MaxSizeToRead <= 0)
						goto processCrc;
					ElementLevelA = FoundElt;
					continue;
				} 
				
				if (UpperEltFound < 0) {
					UpperEltFound++;
					if (UpperEltFound < 0)
						goto processCrc;
				}

				if (MaxSizeToRead <= 0)
					goto processCrc;// this level is finished
				
				ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
			}
			if (UpperEltFound > 0) {
				FoundElt = ElementLevelA;
			}
		}
	processCrc:
        EBML_MASTER_ITERATOR Itr, CrcItr;
        for (Itr = ElementList.begin(); Itr != ElementList.end();) {
			if ((EbmlId)(*(*Itr)) == EBML_ID(EbmlCrc32)) {
				bChecksumUsed = true;
				// remove the element
				Checksum = *(static_cast<EbmlCrc32*>(*Itr));
                CrcItr = Itr;
                break;
			}
            ++Itr;
		}
        if (bChecksumUsed)
        {
		    delete *CrcItr;
		    Remove(CrcItr);
        }
		SetValueIsSet();
	}
}