Exemplo n.º 1
0
EbmlElement *EbmlParser::Get( int n_call )
{
    int i_ulev = 0;
    EbmlElement *p_prev = NULL;

    if( mi_user_level != mi_level )
    {
        return NULL;
    }
    if( m_got )
    {
        EbmlElement *ret = m_got;
        m_got = NULL;

        return ret;
    }

    p_prev = m_el[mi_level];
    if( m_el[mi_level] )
    {
        m_el[mi_level]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level]) );

    }

    /* Ignore unknown level 0 or 1 elements */
    m_el[mi_level] = m_es->FindNextElement( EBML_CONTEXT(m_el[mi_level - 1]),
                                            i_ulev, UINT64_MAX,
                                            (  mb_dummy | (mi_level > 1) ), 1 );
    if( i_ulev > 0 )
    {
        if( p_prev )
        {
            if( !mb_keep )
            {
                if( MKV_IS_ID( p_prev, KaxBlockVirtual ) )
                    static_cast<KaxBlockVirtualWorkaround*>(p_prev)->Fix();
                delete p_prev;
            }
            mb_keep = false;
        }
        while( i_ulev > 0 )
        {
            if( mi_level == 1 )
            {
                mi_level = 0;
                return NULL;
            }

            delete m_el[mi_level - 1];
            m_got = m_el[mi_level -1] = m_el[mi_level];
            m_el[mi_level] = NULL;

            mi_level--;
            i_ulev--;
        }
        return NULL;
    }
    else if( m_el[mi_level] == NULL )
    {
        msg_Warn( p_demux,"MKV/Ebml Parser: m_el[mi_level] == NULL\n" );
    }
    else if( m_el[mi_level]->IsDummy() && !mb_dummy )
    {
        bool b_bad_position = false;
        /* We got a dummy element but don't want those...
         * perform a sanity check */
        if( !mi_level )
        {
            msg_Err(p_demux, "Got invalid lvl 0 element... Aborting");
            return NULL;
        }

        if( p_prev && p_prev->IsFiniteSize() &&
            p_prev->GetEndPosition() != m_el[mi_level]->GetElementPosition() &&
            mi_level > 1 )
        {
            msg_Err( p_demux, "Dummy Element at unexpected position... corrupted file?" );
            b_bad_position = true;
        }

        if( n_call < 10 && !b_bad_position && m_el[mi_level]->IsFiniteSize() &&
            ( !m_el[mi_level-1]->IsFiniteSize() ||
              m_el[mi_level]->GetEndPosition() <= m_el[mi_level-1]->GetEndPosition() ) )
        {
            /* The element fits inside its upper element */
            msg_Warn( p_demux, "Dummy element found %"PRIu64"... skipping it",
                      m_el[mi_level]->GetElementPosition() );
            return Get( ++n_call );
        }
        else
        {
            /* Too large, misplaced or 10 successive dummy elements */
            msg_Err( p_demux,
                     "Dummy element too large or misplaced at %"PRIu64"... skipping to next upper element",
                     m_el[mi_level]->GetElementPosition() );

            if( mi_level >= 1 &&
                m_el[mi_level]->GetElementPosition() >= m_el[mi_level-1]->GetEndPosition() )
            {
                msg_Err(p_demux, "This element is outside its known parent... upping level");
                delete m_el[mi_level - 1];
                m_got = m_el[mi_level -1] = m_el[mi_level];
                m_el[mi_level] = NULL;

                mi_level--;
                return NULL;
            }

            delete m_el[mi_level];
            m_el[mi_level] = NULL;
            m_el[mi_level - 1]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level - 1]) );
            return Get();
        }
    }

    if( p_prev )
    {
        if( !mb_keep )
        {
            if( MKV_IS_ID( p_prev, KaxBlockVirtual ) )
                static_cast<KaxBlockVirtualWorkaround*>(p_prev)->Fix();
            delete p_prev;
        }
        mb_keep = false;
    }
    return m_el[mi_level];
}
Exemplo n.º 2
0
EbmlElement *EbmlParser::Get( int n_call )
{
    int i_ulev = 0;
    EbmlElement *p_prev = NULL;

    if( mi_user_level != mi_level )
    {
        return NULL;
    }
    if( m_got )
    {
        EbmlElement *ret = m_got;
        m_got = NULL;

        return ret;
    }

    p_prev = m_el[mi_level];
    if( m_el[mi_level] )
    {
        m_el[mi_level]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level]) );

    }

    // If the parent is a segment, use the segment context when creating children
    // (to prolong their lifetime), otherwise just continue as normal
    EbmlSemanticContext e_context =
            EBML_CTX_MASTER( EBML_CONTEXT(m_el[mi_level - 1]) ) == EBML_CTX_MASTER( Context_KaxSegmentVLC )
            ? Context_KaxSegmentVLC
            : EBML_CONTEXT(m_el[mi_level - 1]);

    /* Ignore unknown level 0 or 1 elements */
    m_el[mi_level] = m_es->FindNextElement( e_context,
                                            i_ulev, UINT64_MAX,
                                            (  mb_dummy | (mi_level > 1) ), 1 );
    if( i_ulev > 0 )
    {
        if( p_prev )
        {
            if( !mb_keep )
            {
                if( MKV_IS_ID( p_prev, KaxBlockVirtual ) )
                    static_cast<KaxBlockVirtualWorkaround*>(p_prev)->Fix(); // !! WARNING : TODO !! this is undefined-behavior
                delete p_prev;
            }
            mb_keep = false;
        }
        while( i_ulev > 0 )
        {
            if( mi_level == 1 )
            {
                mi_level = 0;
                return NULL;
            }

            delete m_el[mi_level - 1];
            m_got = m_el[mi_level -1] = m_el[mi_level];
            m_el[mi_level] = NULL;

            mi_level--;
            i_ulev--;
        }
        return NULL;
    }
    else if( m_el[mi_level] == NULL )
    {
        msg_Dbg( p_demux,"MKV/Ebml Parser: m_el[mi_level] == NULL" );
    }
    else if( m_el[mi_level]->IsDummy() && !mb_dummy )
    {
        bool b_bad_position = false;
        /* We got a dummy element but don't want those...
         * perform a sanity check */
        if( !mi_level )
        {
            msg_Err(p_demux, "Got invalid lvl 0 element... Aborting");
            return NULL;
        }

        if( p_prev && p_prev->IsFiniteSize() &&
            p_prev->GetEndPosition() != m_el[mi_level]->GetElementPosition() &&
            mi_level > 1 )
        {
            msg_Err( p_demux, "Dummy Element at unexpected position... corrupted file?" );
            b_bad_position = true;
        }

        if( n_call < M_EL_MAXSIZE && !b_bad_position && m_el[mi_level]->IsFiniteSize() &&
            ( !m_el[mi_level-1]->IsFiniteSize() ||
              m_el[mi_level]->GetEndPosition() <= m_el[mi_level-1]->GetEndPosition() ) )
        {
            /* The element fits inside its upper element */
            msg_Warn( p_demux, "Dummy element found %" PRIu64 "... skipping it",
                      m_el[mi_level]->GetElementPosition() );
            return Get( ++n_call );
        }
        else
        {
            /* Too large, misplaced or M_EL_MAXSIZE successive dummy elements */
            msg_Err( p_demux,
                     "Dummy element too large or misplaced at %" PRIu64 "... skipping to next upper element",
                     m_el[mi_level]->GetElementPosition() );

            if( mi_level >= 1 &&
                m_el[mi_level]->GetElementPosition() >= m_el[mi_level-1]->GetEndPosition() )
            {
                msg_Err(p_demux, "This element is outside its known parent... upping level");
                delete m_el[mi_level - 1];
                m_got = m_el[mi_level -1] = m_el[mi_level];
                m_el[mi_level] = NULL;

                mi_level--;
                return NULL;
            }

            delete m_el[mi_level];
            delete p_prev;

            m_el[mi_level] = NULL;
            m_el[mi_level - 1]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level - 1]) );
            return Get();
        }
    }

    if( p_prev )
    {
        if( !mb_keep )
        {
            if( MKV_IS_ID( p_prev, KaxBlockVirtual ) )
                static_cast<KaxBlockVirtualWorkaround*>(p_prev)->Fix();
            delete p_prev;
        }
        mb_keep = false;
    }
    return m_el[mi_level];
}
Exemplo n.º 3
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();
	}
}