uint64 KaxInternalBlock::ReadInternalHead(IOCallback & input) { binary Buffer[5], *cursor = Buffer; uint64 Result = input.read(cursor, 4); if (Result != 4) return Result; // update internal values TrackNumber = *cursor++; if ((TrackNumber & 0x80) == 0) { // there is extra data if ((TrackNumber & 0x40) == 0) { // We don't support track numbers that large ! return Result; } Result += input.read(&Buffer[4], 1); TrackNumber = (TrackNumber & 0x3F) << 8; TrackNumber += *cursor++; } else { TrackNumber &= 0x7F; } big_int16 b16; b16.Eval(cursor); assert(ParentCluster != NULL); Timecode = ParentCluster->GetBlockGlobalTimecode(int16(b16)); bLocalTimecodeUsed = false; cursor += 2; return Result; }
filepos_t EbmlString::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { if (GetSize() == 0) { Value = ""; SetValueIsSet(); } else { char *Buffer = new char[GetSize() + 1]; if (Buffer == NULL) { // unable to store the data, skip it input.setFilePointer(GetSize(), seek_current); } else { input.readFully(Buffer, GetSize()); if (Buffer[GetSize()-1] != '\0') { Buffer[GetSize()] = '\0'; } Value = Buffer; delete [] Buffer; SetValueIsSet(); } } } return GetSize(); }
uint64 EbmlString::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { if (Size == 0) { Value = ""; bValueIsSet = true; } else { char *Buffer = new char[Size + 1]; if (Buffer == NULL) { // unable to store the data, skip it input.setFilePointer(Size, seek_current); } else { input.readFully(Buffer, Size); if (Buffer[Size-1] != '\0') { Buffer[Size] = '\0'; } Value = Buffer; delete [] Buffer; bValueIsSet = true; } } } return Size; }
uint32 EbmlVoid::RenderData(IOCallback & output, bool bForceRender, bool bKeepIntact) { // write dummy data by 4KB chunks static binary DummyBuf[4*1024]; uint64 SizeToWrite = Size; while (SizeToWrite > 4*1024) { output.writeFully(DummyBuf, 4*1024); SizeToWrite -= 4*1024; } output.writeFully(DummyBuf, SizeToWrite); return Size; }
filepos_t EbmlVoid::RenderData(IOCallback & output, bool bForceRender, bool bWithDefault) { // write dummy data by 4KB chunks static binary DummyBuf[4*1024]; uint64 SizeToWrite = GetSize(); while (SizeToWrite > 4*1024) { output.writeFully(DummyBuf, 4*1024); SizeToWrite -= 4*1024; } output.writeFully(DummyBuf, SizeToWrite); return GetSize(); }
/*! \todo remove the hack for possible endianess pb (test on little & big endian) */ uint64 EbmlFloat::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { binary Buffer[20]; assert(Size <= 20); input.readFully(Buffer, Size); if (Size == 4) { big_int32 TmpRead; TmpRead.Eval(Buffer); int32 tmpp = int32(TmpRead); float val; memcpy(&val, &tmpp, 4); Value = val; bValueIsSet = true; } else if (Size == 8) { big_int64 TmpRead; TmpRead.Eval(Buffer); int64 tmpp = int64(TmpRead); double val; memcpy(&val, &tmpp, 8); Value = val; bValueIsSet = true; } } return Size; }
/*! \todo handle exception on errors \todo write all the Mandatory elements in the Context, otherwise assert */ filepos_t EbmlMaster::RenderData(IOCallback & output, bool bForceRender, bool bWithDefault) { filepos_t Result = 0; size_t Index; if (!bForceRender) { assert(CheckMandatory()); } if (!bChecksumUsed) { // old school for (Index = 0; Index < ElementList.size(); Index++) { if (!bWithDefault && (ElementList[Index])->IsDefaultValue()) continue; Result += (ElementList[Index])->Render(output, bWithDefault, false ,bForceRender); } } else { // new school MemIOCallback TmpBuf(GetSize() - 6); for (Index = 0; Index < ElementList.size(); Index++) { if (!bWithDefault && (ElementList[Index])->IsDefaultValue()) continue; (ElementList[Index])->Render(TmpBuf, bWithDefault, false ,bForceRender); } Checksum.FillCRC32(TmpBuf.GetDataBuffer(), TmpBuf.GetDataBufferSize()); Result += Checksum.Render(output, true, false ,bForceRender); output.writeFully(TmpBuf.GetDataBuffer(), TmpBuf.GetDataBufferSize()); Result += TmpBuf.GetDataBufferSize(); } return Result; }
/*! \todo remove the hack for possible endianess pb (test on little & big endian) */ filepos_t EbmlFloat::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { binary Buffer[20]; assert(GetSize() <= 20); input.readFully(Buffer, GetSize()); if (GetSize() == 4) { big_int32 TmpRead; TmpRead.Eval(Buffer); int32 tmpp = int32(TmpRead); float val; memcpy(&val, &tmpp, 4); Value = val; SetValueIsSet(); } else if (GetSize() == 8) { big_int64 TmpRead; TmpRead.Eval(Buffer); int64 tmpp = int64(TmpRead); double val; memcpy(&val, &tmpp, 8); Value = val; SetValueIsSet(); } } return GetSize(); }
filepos_t EbmlCrc32::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { binary *Buffer = new binary[GetSize()]; if (Buffer == NULL) { // impossible to read, skip it input.setFilePointer(GetSize(), seek_current); } else { input.readFully(Buffer, GetSize()); memcpy((void *)&m_crc_final, Buffer, 4); delete [] Buffer; SetValueIsSet(); } } return GetSize(); }
uint32 MemIOCallback::write(IOCallback & IOToRead, size_t Size) { if (dataBufferMemorySize < dataBufferPos + Size) { //We need more memory! dataBuffer = (binary *)realloc((void *)dataBuffer, dataBufferPos + Size); } IOToRead.readFully(&dataBuffer[dataBufferPos], Size); dataBufferTotalSize = Size; return Size; }
/*! \todo handle exception on errors \todo handle 10 bits precision */ uint32 EbmlFloat::RenderData(IOCallback & output, bool bForceRender, bool bKeepIntact) { assert(Size == 4 || Size == 8); if (Size == 4) { float val = Value; int Tmp; memcpy(&Tmp, &val, 4); big_int32 TmpToWrite(Tmp); output.writeFully(&TmpToWrite.endian(), Size); } else if (Size == 8) { double val = Value; int64 Tmp; memcpy(&Tmp, &val, 8); big_int64 TmpToWrite(Tmp); output.writeFully(&TmpToWrite.endian(), Size); } return Size; }
/*! \todo handle exception on errors */ filepos_t EbmlString::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */) { filepos_t Result; output.writeFully(Value.c_str(), Value.length()); Result = Value.length(); if (Result < GetDefaultSize()) { // pad the rest with 0 binary *Pad = new (std::nothrow) binary[GetDefaultSize() - Result]; if (Pad == NULL) { return Result; } memset(Pad, 0x00, GetDefaultSize() - Result); output.writeFully(Pad, GetDefaultSize() - Result); Result = GetDefaultSize(); delete [] Pad; } return Result; }
filepos_t EbmlDate::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */) { if (GetSize() != 0) { assert(GetSize() == 8); big_int64 b64(myDate); output.writeFully(&b64.endian(),GetSize()); } return GetSize(); }
/*! \todo handle exception on errors \todo handle 10 bits precision */ filepos_t EbmlFloat::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */) { assert(GetSize() == 4 || GetSize() == 8); if (GetSize() == 4) { float val = Value; int Tmp; memcpy(&Tmp, &val, 4); big_int32 TmpToWrite(Tmp); output.writeFully(&TmpToWrite.endian(), GetSize()); } else if (GetSize() == 8) { double val = Value; int64 Tmp; memcpy(&Tmp, &val, 8); big_int64 TmpToWrite(Tmp); output.writeFully(&TmpToWrite.endian(), GetSize()); } return GetSize(); }
/*! \todo handle exception on errors */ uint32 EbmlString::RenderData(IOCallback & output, bool bForceRender, bool bKeepIntact) { uint32 Result; output.writeFully(Value.c_str(), Value.length()); Result = Value.length(); if (Result < DefaultSize) { // pad the rest with 0 binary *Pad = new binary[DefaultSize - Result]; if (Pad == NULL) { return Result; } memset(Pad, 0x00, DefaultSize - Result); output.writeFully(Pad, DefaultSize - Result); Result = DefaultSize; delete [] Pad; } return Result; }
filepos_t EbmlCrc32::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */) { filepos_t Result = 4; if (Result != 0) { output.writeFully(&m_crc_final, Result); } if (Result < GetDefaultSize()) { // pad the rest with 0 binary *Pad = new binary[GetDefaultSize() - Result]; if (Pad != NULL) { memset(Pad, 0x00, GetDefaultSize() - Result); output.writeFully(Pad, GetDefaultSize() - Result); Result = GetDefaultSize(); delete [] Pad; } } return Result; }
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(); }
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(); }
filepos_t EbmlBinary::ReadData(IOCallback & input, ScopeMode ReadFully) { if (Data != NULL) free(Data); if (ReadFully == SCOPE_NO_DATA || !GetSize()) { Data = NULL; return GetSize(); } Data = (binary *)malloc(GetSize()); if (Data == NULL) throw CRTError(std::string("Error allocating data")); SetValueIsSet(); return input.read(Data, GetSize()); }
filepos_t EbmlUInteger::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { binary Buffer[8]; input.readFully(Buffer, GetSize()); Value = 0; for (unsigned int i=0; i<GetSize(); i++) { Value <<= 8; Value |= Buffer[i]; } SetValueIsSet(); } return GetSize(); }
/*! \todo handle exception on errors */ filepos_t EbmlUInteger::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */) { binary FinalData[8]; // we don't handle more than 64 bits integers if (GetSizeLength() > 8) return 0; // integer bigger coded on more than 64 bits are not supported uint64 TempValue = Value; for (unsigned int i=0; i<GetSize();i++) { FinalData[GetSize()-i-1] = TempValue & 0xFF; TempValue >>= 8; } output.writeFully(FinalData,GetSize()); return GetSize(); }
filepos_t EbmlDate::ReadData(IOCallback & input, ScopeMode ReadFully) { if ((ReadFully == SCOPE_NO_DATA) || (GetSize() == 0)) return GetSize(); assert(GetSize() == 8); binary Buffer[8]; input.readFully(Buffer, GetSize()); big_int64 b64; b64.Eval(Buffer); myDate = b64; SetValueIsSet(); return GetSize(); }
/*! \todo handle exception on errors */ uint32 EbmlUInteger::RenderData(IOCallback & output, bool bForceRender, bool bKeepIntact) { binary FinalData[8]; // we don't handle more than 64 bits integers if (SizeLength > 8) return 0; // integer bigger coded on more than 64 bits are not supported uint64 TempValue = Value; for (unsigned int i=0; i<Size;i++) { FinalData[Size-i-1] = TempValue & 0xFF; TempValue >>= 8; } output.writeFully(FinalData,Size); return Size; }
uint64 EbmlUInteger::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { binary Buffer[8]; input.readFully(Buffer, Size); Value = 0; for (unsigned int i=0; i<Size; i++) { Value <<= 8; Value |= Buffer[i]; } bValueIsSet = true; } return Size; }
filepos_t EbmlSInteger::ReadData(IOCallback & input, ScopeMode ReadFully) { if (ReadFully != SCOPE_NO_DATA) { binary Buffer[8]; input.readFully(Buffer, GetSize()); if (Buffer[0] & 0x80) Value = -1; // this is a negative value else Value = 0; // this is a positive value for (unsigned int i=0; i<GetSize(); i++) { Value <<= 8; Value |= Buffer[i]; } SetValueIsSet(); } return GetSize(); }
filepos_t EbmlBinary::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */) { output.writeFully(Data,GetSize()); return GetSize(); }
/*! \todo better zero copy handling */ filepos_t KaxInternalBlock::ReadData(IOCallback & input, ScopeMode ReadFully) { filepos_t Result; FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below if (ReadFully == SCOPE_ALL_DATA) { Result = EbmlBinary::ReadData(input, ReadFully); binary *cursor = EbmlBinary::GetBuffer(); uint8 BlockHeadSize = 4; // update internal values TrackNumber = *cursor++; if ((TrackNumber & 0x80) == 0) { // there is extra data if ((TrackNumber & 0x40) == 0) { // We don't support track numbers that large ! return Result; } TrackNumber = (TrackNumber & 0x3F) << 8; TrackNumber += *cursor++; BlockHeadSize++; } else { TrackNumber &= 0x7F; } big_int16 b16; b16.Eval(cursor); LocalTimecode = int16(b16); bLocalTimecodeUsed = true; cursor += 2; if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) { bIsKeyframe = (*cursor & 0x80) != 0; bIsDiscardable = (*cursor & 0x01) != 0; } mInvisible = (*cursor & 0x08) >> 3; mLacing = LacingType((*cursor++ & 0x06) >> 1); // put all Frames in the list if (mLacing == LACING_NONE) { FirstFrameLocation += cursor - EbmlBinary::GetBuffer(); DataBuffer * soloFrame = new DataBuffer(cursor, GetSize() - BlockHeadSize); myBuffers.push_back(soloFrame); SizeList.resize(1); SizeList[0] = GetSize() - BlockHeadSize; } else { // read the number of frames in the lace uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame uint8 FrameNum = *cursor++; // number of frames in the lace - 1 // read the list of frame sizes uint8 Index; int32 FrameSize; uint32 SizeRead; uint64 SizeUnknown; SizeList.resize(FrameNum + 1); switch (mLacing) { case LACING_XIPH: for (Index=0; Index<FrameNum; Index++) { // get the size of the frame FrameSize = 0; do { FrameSize += uint8(*cursor); LastBufferSize--; } while (*cursor++ == 0xFF); SizeList[Index] = FrameSize; LastBufferSize -= FrameSize; } SizeList[Index] = LastBufferSize; break; case LACING_EBML: SizeRead = LastBufferSize; FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown); SizeList[0] = FrameSize; cursor += SizeRead; LastBufferSize -= FrameSize + SizeRead; for (Index=1; Index<FrameNum; Index++) { // get the size of the frame SizeRead = LastBufferSize; FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown); SizeList[Index] = FrameSize; cursor += SizeRead; LastBufferSize -= FrameSize + SizeRead; } SizeList[Index] = LastBufferSize; break; case LACING_FIXED: for (Index=0; Index<=FrameNum; Index++) { // get the size of the frame SizeList[Index] = LastBufferSize / (FrameNum + 1); } break; default: // other lacing not supported assert(0); } FirstFrameLocation += cursor - EbmlBinary::GetBuffer(); for (Index=0; Index<=FrameNum; Index++) { DataBuffer * lacedFrame = new DataBuffer(cursor, SizeList[Index]); myBuffers.push_back(lacedFrame); cursor += SizeList[Index]; } } SetValueIsSet(); }
/*! \todo this code is very suspicious ! */ filepos_t EbmlMaster::ReadData(IOCallback & input, ScopeMode ReadFully) { input.setFilePointer(GetSize(), seek_current); return GetSize(); }
/*! \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(); }
/*! \todo better zero copy handling */ filepos_t KaxInternalBlock::ReadData(IOCallback & input, ScopeMode ReadFully) { filepos_t Result; FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below SetValueIsSet(false); try { if (ReadFully == SCOPE_ALL_DATA) { Result = EbmlBinary::ReadData(input, ReadFully); if (Result != GetSize()) throw SafeReadIOCallback::EndOfStreamX(GetSize() - Result); binary *BufferStart = EbmlBinary::GetBuffer(); SafeReadIOCallback Mem(*this); uint8 BlockHeadSize = 4; // update internal values TrackNumber = Mem.GetUInt8(); if ((TrackNumber & 0x80) == 0) { // there is extra data if ((TrackNumber & 0x40) == 0) { // We don't support track numbers that large ! throw SafeReadIOCallback::EndOfStreamX(0); } TrackNumber = (TrackNumber & 0x3F) << 8; TrackNumber += Mem.GetUInt8(); BlockHeadSize++; } else { TrackNumber &= 0x7F; } LocalTimecode = int16(Mem.GetUInt16BE()); bLocalTimecodeUsed = true; uint8 Flags = Mem.GetUInt8(); if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) { bIsKeyframe = (Flags & 0x80) != 0; bIsDiscardable = (Flags & 0x01) != 0; } mInvisible = (Flags & 0x08) >> 3; mLacing = LacingType((Flags & 0x06) >> 1); // put all Frames in the list if (mLacing == LACING_NONE) { FirstFrameLocation += Mem.GetPosition(); DataBuffer * soloFrame = new DataBuffer(BufferStart + Mem.GetPosition(), GetSize() - BlockHeadSize); myBuffers.push_back(soloFrame); SizeList.resize(1); SizeList[0] = GetSize() - BlockHeadSize; } else { // read the number of frames in the lace uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame uint8 FrameNum = Mem.GetUInt8(); // number of frames in the lace - 1 // read the list of frame sizes uint8 Index; int32 FrameSize; uint32 SizeRead; uint64 SizeUnknown; SizeList.resize(FrameNum + 1); switch (mLacing) { case LACING_XIPH: for (Index=0; Index<FrameNum; Index++) { // get the size of the frame FrameSize = 0; uint8 Value; do { Value = Mem.GetUInt8(); FrameSize += Value; LastBufferSize--; } while (Value == 0xFF); SizeList[Index] = FrameSize; LastBufferSize -= FrameSize; } SizeList[Index] = LastBufferSize; break; case LACING_EBML: SizeRead = LastBufferSize; FrameSize = ReadCodedSizeValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown); SizeList[0] = FrameSize; Mem.Skip(SizeRead); LastBufferSize -= FrameSize + SizeRead; for (Index=1; Index<FrameNum; Index++) { // get the size of the frame SizeRead = LastBufferSize; FrameSize += ReadCodedSizeSignedValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown); SizeList[Index] = FrameSize; Mem.Skip(SizeRead); LastBufferSize -= FrameSize + SizeRead; } if (Index <= FrameNum) // Safety check if FrameNum == 0 SizeList[Index] = LastBufferSize; break; case LACING_FIXED: for (Index=0; Index<=FrameNum; Index++) { // get the size of the frame SizeList[Index] = LastBufferSize / (FrameNum + 1); } break; default: // other lacing not supported assert(0); } FirstFrameLocation += Mem.GetPosition(); for (Index=0; Index<=FrameNum; Index++) { DataBuffer * lacedFrame = new DataBuffer(BufferStart + Mem.GetPosition(), SizeList[Index]); myBuffers.push_back(lacedFrame); Mem.Skip(SizeList[Index]); } } binary *BufferEnd = BufferStart + GetSize(); size_t NumFrames = myBuffers.size(); // Sanity checks for frame pointers and boundaries. for (size_t Index = 0; Index < NumFrames; ++Index) { binary *FrameStart = myBuffers[Index]->Buffer(); binary *FrameEnd = FrameStart + myBuffers[Index]->Size(); binary *ExpectedEnd = (Index + 1) < NumFrames ? myBuffers[Index + 1]->Buffer() : BufferEnd; if ((FrameStart < BufferStart) || (FrameEnd > BufferEnd) || (FrameEnd != ExpectedEnd)) throw SafeReadIOCallback::EndOfStreamX(0); } SetValueIsSet(); } else if (ReadFully == SCOPE_PARTIAL_DATA) { binary _TempHead[5]; Result = input.read(_TempHead, 5); if (Result != 5) throw SafeReadIOCallback::EndOfStreamX(0); binary *cursor = _TempHead; binary *_tmpBuf; uint8 BlockHeadSize = 4; // update internal values TrackNumber = *cursor++; if ((TrackNumber & 0x80) == 0) { // there is extra data if ((TrackNumber & 0x40) == 0) { // We don't support track numbers that large ! return Result; } TrackNumber = (TrackNumber & 0x3F) << 8; TrackNumber += *cursor++; BlockHeadSize++; } else { TrackNumber &= 0x7F; } big_int16 b16; b16.Eval(cursor); LocalTimecode = int16(b16); bLocalTimecodeUsed = true; cursor += 2; if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) { bIsKeyframe = (*cursor & 0x80) != 0; bIsDiscardable = (*cursor & 0x01) != 0; } mInvisible = (*cursor & 0x08) >> 3; mLacing = LacingType((*cursor++ & 0x06) >> 1); if (cursor == &_TempHead[4]) { _TempHead[0] = _TempHead[4]; } else { Result += input.read(_TempHead, 1); } FirstFrameLocation += cursor - _TempHead; // put all Frames in the list if (mLacing != LACING_NONE) { // read the number of frames in the lace uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame uint8 FrameNum = _TempHead[0]; // number of frames in the lace - 1 // read the list of frame sizes uint8 Index; int32 FrameSize; uint32 SizeRead; uint64 SizeUnknown; SizeList.resize(FrameNum + 1); switch (mLacing) { case LACING_XIPH: for (Index=0; Index<FrameNum; Index++) { // get the size of the frame FrameSize = 0; do { Result += input.read(_TempHead, 1); FrameSize += uint8(_TempHead[0]); LastBufferSize--; FirstFrameLocation++; } while (_TempHead[0] == 0xFF); FirstFrameLocation++; SizeList[Index] = FrameSize; LastBufferSize -= FrameSize; } SizeList[Index] = LastBufferSize; break; case LACING_EBML: SizeRead = LastBufferSize; cursor = _tmpBuf = new binary[FrameNum*4]; /// \warning assume the mean size will be coded in less than 4 bytes Result += input.read(cursor, FrameNum*4); FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown); SizeList[0] = FrameSize; cursor += SizeRead; LastBufferSize -= FrameSize + SizeRead; for (Index=1; Index<FrameNum; Index++) { // get the size of the frame SizeRead = LastBufferSize; FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown); SizeList[Index] = FrameSize; cursor += SizeRead; LastBufferSize -= FrameSize + SizeRead; } FirstFrameLocation += cursor - _tmpBuf; SizeList[Index] = LastBufferSize; delete [] _tmpBuf; break; case LACING_FIXED: for (Index=0; Index<=FrameNum; Index++) { // get the size of the frame SizeList[Index] = LastBufferSize / (FrameNum + 1); } break; default: // other lacing not supported assert(0); } } else { SizeList.resize(1); SizeList[0] = GetSize() - BlockHeadSize; } SetValueIsSet(false); Result = GetSize(); } else {