Exemple #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;
}
Exemple #2
0
uint64 EbmlMaster::UpdateSize(bool bWithDefault, bool bForceRender)
{
	SetSize_(0);

	if (!IsFiniteSize())
		return (0-1);

	if (!bForceRender) {
		assert(CheckMandatory());
    }
	
	size_t Index;
	
	for (Index = 0; Index < ElementList.size(); Index++) {
		if (!bWithDefault && (ElementList[Index])->IsDefaultValue())
			continue;
		(ElementList[Index])->UpdateSize(bWithDefault, bForceRender);
		uint64 SizeToAdd = (ElementList[Index])->ElementSize(bWithDefault);
#if defined(LIBEBML_DEBUG)
		if (static_cast<int64>(SizeToAdd) == (0-1))
			return (0-1);
#endif // LIBEBML_DEBUG
		SetSize_(GetSize() + SizeToAdd);
	}
	if (bChecksumUsed) {
		SetSize_(GetSize() + Checksum.ElementSize());
	}

	return GetSize();
}
Exemple #3
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 #4
0
/*!
       \return Returns the lacing type that produces the smallest footprint.
*/
LacingType KaxInternalBlock::GetBestLacingType() const {
	int XiphLacingSize, EbmlLacingSize, i;
	bool SameSize = true;

	if (myBuffers.size() <= 1)
		return LACING_NONE;

	XiphLacingSize = 1; // Number of laces is stored in 1 byte.
	EbmlLacingSize = 1;
	for (i = 0; i < (int)myBuffers.size() - 1; i++) {
		if (myBuffers[i]->Size() != myBuffers[i + 1]->Size())
			SameSize = false;
		XiphLacingSize += myBuffers[i]->Size() / 255 + 1;
	}
	EbmlLacingSize += CodedSizeLength(myBuffers[0]->Size(), 0, IsFiniteSize());
	for (i = 1; i < (int)myBuffers.size() - 1; i++)
		EbmlLacingSize += CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i - 1]->Size()), 0);
	if (SameSize)
		return LACING_FIXED;
	else if (XiphLacingSize < EbmlLacingSize)
		return LACING_XIPH;
	else
		return LACING_EBML;
}
Exemple #5
0
/*!
	\todo more optimisation is possible (render the Block head and don't copy the buffer in memory, care should be taken with the allocation of Data)
	\todo the actual timecode to write should be retrieved from the Cluster from here
*/
filepos_t KaxInternalBlock::RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault)
{
	if (myBuffers.size() == 0) {
		return 0;
	} else {
		assert(TrackNumber < 0x4000);
		binary BlockHead[5], *cursor = BlockHead;
		unsigned int i;

		if (myBuffers.size() == 1) {
			SetSize_(4);
			mLacing = LACING_NONE;
		} else {
			if (mLacing == LACING_NONE)
				mLacing = LACING_EBML; // supposedly the best of all
			SetSize_(4 + 1); // 1 for the lacing head (number of laced elements)
		}
		if (TrackNumber > 0x80)
			SetSize_(GetSize() + 1);

		// write Block Head
		if (TrackNumber < 0x80) {
			*cursor++ = TrackNumber | 0x80; // set the first bit to 1 
		} else {
			*cursor++ = (TrackNumber >> 8) | 0x40; // set the second bit to 1
			*cursor++ = TrackNumber & 0xFF;
		}

		assert(ParentCluster != NULL);
		int16 ActualTimecode = ParentCluster->GetBlockLocalTimecode(Timecode);
		big_int16 b16(ActualTimecode);
		b16.Fill(cursor);
		cursor += 2;

		*cursor = 0; // flags

		if (mLacing == LACING_AUTO) {
			mLacing = GetBestLacingType();
		}

		// invisible flag
		if (mInvisible)
			*cursor = 0x08;

		if (bIsSimple) {
			if (bIsKeyframe)
				*cursor |= 0x80;
			if (bIsDiscardable)
				*cursor |= 0x01;
		}
		
		// lacing flag
		switch (mLacing)
		{
		case LACING_XIPH:
			*cursor++ |= 0x02;
			break;
		case LACING_EBML:
			*cursor++ |= 0x06;
			break;
		case LACING_FIXED:
			*cursor++ |= 0x04;
			break;
		case LACING_NONE:
			break;
	    default:
			assert(0);
		}

		output.writeFully(BlockHead, 4 + ((TrackNumber > 0x80) ? 1 : 0));

		binary tmpValue;
		switch (mLacing)
		{
		case LACING_XIPH:
			// number of laces
			tmpValue = myBuffers.size()-1;
			output.writeFully(&tmpValue, 1);

			// set the size of each member in the lace
			for (i=0; i<myBuffers.size()-1; i++) {
				tmpValue = 0xFF;
				uint16 tmpSize = myBuffers[i]->Size();
				while (tmpSize >= 0xFF) {
					output.writeFully(&tmpValue, 1);
					SetSize_(GetSize() + 1);
					tmpSize -= 0xFF;
				}
				tmpValue = binary(tmpSize);
				output.writeFully(&tmpValue, 1);
				SetSize_(GetSize() + 1);
			}
			break;
		case LACING_EBML:
			// number of laces
			tmpValue = myBuffers.size()-1;
			output.writeFully(&tmpValue, 1);

			{
				int64 _Size;
				int _CodedSize;
				binary _FinalHead[8]; // 64 bits max coded size

				_Size = myBuffers[0]->Size();

				_CodedSize = CodedSizeLength(_Size, 0, IsFiniteSize());

				// first size in the lace is not a signed
				CodedValueLength(_Size, _CodedSize, _FinalHead);
				output.writeFully(_FinalHead, _CodedSize);
				SetSize_(GetSize() + _CodedSize);

				// set the size of each member in the lace
				for (i=1; i<myBuffers.size()-1; i++) {
					_Size = int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size());
					_CodedSize = CodedSizeLengthSigned(_Size, 0);
					CodedValueLengthSigned(_Size, _CodedSize, _FinalHead);
					output.writeFully(_FinalHead, _CodedSize);
					SetSize_(GetSize() + _CodedSize);
				}
			}
			break;
		case LACING_FIXED:
			// number of laces
			tmpValue = myBuffers.size()-1;
			output.writeFully(&tmpValue, 1);
			break;
		case LACING_NONE:
			break;
	    default:
			assert(0);
		}

		// put the data of each frame
		for (i=0; i<myBuffers.size(); i++) {
			output.writeFully(myBuffers[i]->Buffer(), myBuffers[i]->Size());
			SetSize_(GetSize() + myBuffers[i]->Size());
		}
	}

	return GetSize();
}
Exemple #6
0
filepos_t KaxInternalBlock::UpdateSize(bool bSaveDefault, bool bForceRender)
{
	LacingType LacingHere;
    assert(EbmlBinary::GetBuffer() == NULL); // Data is not used for KaxInternalBlock
	assert(TrackNumber < 0x4000); // no more allowed for the moment
	unsigned int i;

	// compute the final size of the data
	switch (myBuffers.size()) {
		case 0:
			SetSize_(0);
			break;
		case 1:
			SetSize_(4 + myBuffers[0]->Size());
			break;
		default:
			SetSize_(4 + 1); // 1 for the lacing head
			if (mLacing == LACING_AUTO)
				LacingHere = GetBestLacingType();
			else
				LacingHere = mLacing;
			switch (LacingHere)
			{
			case LACING_XIPH:
				for (i=0; i<myBuffers.size()-1; i++) {
					SetSize_(GetSize() + myBuffers[i]->Size() + (myBuffers[i]->Size() / 0xFF + 1));
				}
				break;
			case LACING_EBML:
				SetSize_(GetSize() + myBuffers[0]->Size() + CodedSizeLength(myBuffers[0]->Size(), 0, IsFiniteSize()));
				for (i=1; i<myBuffers.size()-1; i++) {
					SetSize_(GetSize() + myBuffers[i]->Size() + CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size()), 0));
				}
				break;
			case LACING_FIXED:
				for (i=0; i<myBuffers.size()-1; i++) {
					SetSize_(GetSize() + myBuffers[i]->Size());
				}
				break;
			default:
				assert(0);
			}
			// Size of the last frame (not in lace)
			SetSize_(GetSize() + myBuffers[i]->Size());
			break;
	}

	if (TrackNumber >= 0x80)
		SetSize_(GetSize() + 1); // the size will be coded with one more octet

	return GetSize();
}
Exemple #7
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();
	}
}