コード例 #1
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
/*! Moves the file pointer for the parent file to the start of the index data in this partition
 *  \note If there is no index table data in this partition the pointer will not be moved
 */
bool mxflib::Partition::SeekIndex(void)
{
	Int64 IndexSize = GetInt64(IndexByteCount_UL);
	if(IndexSize == 0) return false;

	MXFFilePtr ParentFile = Object->GetParentFile();

	if(!ParentFile)
	{
		error("Call to Partition::SeekIndex() on a partition that is not read from a file\n");
		return false;
	}

	Int64 MetadataSize = GetInt64(HeaderByteCount_UL);

	// Find the start of the index table
	// DRAGONS: not the most efficient way - we could store a pointer to the end of the metadata
	ParentFile->Seek(Object->GetLocation() + 16);
	Length Len = ParentFile->ReadBER();
	Position Location = ParentFile->Tell() + Len;

	if((sizeof(size_t) < 8) && IndexSize > 0xffffffff)
	{
		error("Maximum read size on this platform is 4Gbytes - However, requested to read index data at 0x%s which has size of 0x%s\n",
			   Int64toHexString(Location,8).c_str(), Int64toHexString(IndexSize,8).c_str());

		return false;
	}

	ParentFile->Seek(Location);
	ULPtr FirstUL = ParentFile->ReadKey();
	if(!FirstUL)
	{
		error("Error reading first KLV after %s at 0x%s in %s\n", FullName().c_str(), 
			  Int64toHexString(GetLocation(),8).c_str(), GetSource().c_str());
		return false;
	}

	MDOTypePtr FirstType = MDOType::Find(FirstUL);
	if(FirstType->IsA(KLVFill_UL))
	{
		// Skip over the filler
		Len = ParentFile->ReadBER();
		Location = ParentFile->Tell() + Len;
	}

	// Move to the start of the index table segments
	ParentFile->Seek(Location + MetadataSize);

	return true;
}
コード例 #2
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
// skip over a KLV packet
UInt64 mxflib::Partition::Skip( UInt64 start )
{
	if( !start ) return 0;

	MXFFilePtr PF = Object->GetParentFile();

	PF->Seek( start );
	ULPtr FirstUL = PF->ReadKey();
	if(!FirstUL) return 0;

	// do the skip
	Length Len = PF->ReadBER();
	PF->Seek( PF->Tell() + Len );

	UInt64 ret = PF->Tell();

	// check in case we've hit the next Partition Pack
	ULPtr NextUL = PF->ReadKey();
	if(!NextUL) return 0;

	// Is this a partition pack?
	if(IsPartitionKey(NextUL->GetValue())) return 0;

	return ret;
}
コード例 #3
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
// goto start of body...set the member variables _BodyLocation, _NextBodyLocation
// DRAGONS: Need to document return value!!
bool mxflib::Partition::StartElements()
{
	_BodyLocation = 0;

	if(!Object->GetParentFile()) { error("Call to Partition::StartElements() on a non-file partition\n"); return false; }

	MXFFilePtr PF = Object->GetParentFile();

	UInt64 MetadataSize = GetInt64(HeaderByteCount_UL);
	UInt64 IndexSize = GetInt64(IndexByteCount_UL);

	// skip over Partition Pack (and any leading Fill on Header)
	PF->Seek( Object->GetLocation() + 16 );
	Length Len = PF->ReadBER();
	_NextBodyLocation = SkipFill( PF->Tell() + Len );
	if( !_NextBodyLocation ) return false;

	// skip over Metadata (and any leading Fill on Index)
	_NextBodyLocation = SkipFill( _NextBodyLocation + MetadataSize );
	if( !_NextBodyLocation ) return false;

	// skip over Index (and any leading Fill on Body)
	_NextBodyLocation = SkipFill( _NextBodyLocation + IndexSize );

	return _NextBodyLocation != 0;
}
コード例 #4
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
/*! Moves the file pointer for the parent file to the start of the essence container in this partition
 *  \note If there is no essence in this partition the pointer will be moved to the start of the following partition (or the start of the RIP if this is the footer)
 */
bool mxflib::Partition::SeekEssence(void)
{
	MXFFilePtr File = Object->GetParentFile();
	if(!File) { error("Call to Partition::SeekEssence() on a non-file partition\n"); return false; }

	Position BodyLocation = 0;

	Length MetadataSize = GetInt64(HeaderByteCount_UL);
	Length IndexSize = GetInt64(IndexByteCount_UL);

	// Skip over Partition Pack (and any trailing filler)
	File->Seek( GetUInt64(ThisPartition_UL) + 16 );
	Length Len = File->ReadBER();
	BodyLocation = SkipFill( File->Tell() + Len );
	if(!BodyLocation) return false;

	// Skip over Metadata (and any trailing filler)
	BodyLocation += MetadataSize;

	// Skip over Index (and any trailing filler)
	BodyLocation += IndexSize;

	// Perform the seek
	File->Seek(BodyLocation);

	return true;
}
コード例 #5
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
//! Read any index table segments from this partition's source file
MDObjectListPtr mxflib::Partition::ReadIndex(void)
{
	UInt64 IndexSize = GetInt64(IndexByteCount_UL);
	if(IndexSize == 0) return new MDObjectList;

	MXFFilePtr ParentFile = Object->GetParentFile();

	if(!ParentFile)
	{
		error("Call to Partition::ReadIndex() on a partition that is not read from a file\n");
		return new MDObjectList;
	}

	UInt64 MetadataSize = GetInt64(HeaderByteCount_UL);

	// Find the start of the index table
	// DRAGONS: not the most efficient way - we could store a pointer to the end of the metadata
	ParentFile->Seek(Object->GetLocation() + 16);
	Length Len = ParentFile->ReadBER();
	Position Location = ParentFile->Tell() + Len;

	ParentFile->Seek(Location);
	ULPtr FirstUL = ParentFile->ReadKey();
	if(!FirstUL)
	{
		error("Error reading first KLV after %s at 0x%s in %s\n", FullName().c_str(), 
			  Int64toHexString(GetLocation(),8).c_str(), GetSource().c_str());
		return new MDObjectList;
	}

	MDOTypePtr FirstType = MDOType::Find(FirstUL);
	if(FirstType->IsA(KLVFill_UL))
	{
		// Skip over the filler
		Len = ParentFile->ReadBER();
		Location = ParentFile->Tell() + Len;
	}

	// Move to the start of the index table segments
	ParentFile->Seek(Location + MetadataSize);

	return ReadIndex(ParentFile, IndexSize);
}
コード例 #6
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
// skip over any KLVFill
// DRAGONS: does not iterate - only copes with single KLVFill
UInt64 mxflib::Partition::SkipFill( UInt64 start )
{
	if( !start ) return 0;

	MXFFilePtr PF = Object->GetParentFile();

	PF->Seek( start );
	ULPtr FirstUL = PF->ReadKey();
	if(!FirstUL) return 0;

	if(FirstUL->Matches(KLVFill_UL))
	{
		// Skip over the KLVFill
		Length Len = PF->ReadBER();
		PF->Seek( PF->Tell() + Len );
	}
	else
	{
		// was not KLVFill, so stay where we are
		PF->Seek( start );
	}

	UInt64 ret = PF->Tell();

	// check in case we've hit the next Partition Pack
	ULPtr NextUL = PF->ReadKey();
	if(!NextUL) return 0;

	// Is this a partition pack?
	if(IsPartitionKey(NextUL->GetValue()))
	{
		UInt8 byte14 = (NextUL->GetValue())[13];
		if( byte14 == 2 || byte14 == 3 || byte14 == 4 )	return 0;
		// we've found a Partition Pack - end of Body -- DRAGONS:?? Not true!!

		if( byte14 == 0x11 )	return 0;
		// we've found a RIP - end of Body
	}

	return ret;
}
コード例 #7
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
/*!  \return The number of bytes read (<b>including</b> any preceeding filler)
 *   \return 0 if no header metadata in this partition
 */
Length mxflib::Partition::ReadMetadata(void)
{
	Length MetadataSize = GetInt64(HeaderByteCount_UL);
	if(MetadataSize == 0) return 0;

	MXFFilePtr ParentFile = Object->GetParentFile();

	if(!ParentFile)
	{
		error("Call to Partition::ReadMetadata() on a partition that is not read from a file\n");
		return 0;
	}

	// Find the start of the metadata 
	// DRAGONS: not the most efficient way - we could store a pointer to the end of the pack
	ParentFile->Seek(Object->GetLocation() + 16);
	Length Len = ParentFile->ReadBER();
	ParentFile->Seek(ParentFile->Tell() + Len);

	return ReadMetadata(ParentFile, MetadataSize);
}
コード例 #8
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
/*! \note The value of "Size" does not include the size of any filler before
 *        the primer, but the return value does
 *  \return The number of bytes read (<b>including</b> any preceeding filler)
 */
Length mxflib::Partition::ReadMetadata(MXFFilePtr File, Length Size)
{
	Length Bytes = 0;
	Length FillerBytes = 0;

	// Clear any existing metadata, including the primer
	ClearMetadata(false);

	// Quick return for NULL metadata
	if(Size == 0) return 0;

	// Record the position of the current item
	Position Location = File->Tell();

	// Check for a leading filler item
	{
		ULPtr FirstUL = File->ReadKey();
		if(!FirstUL)
		{
			error("Error reading first KLV after %s at 0x%s in %s\n", FullName().c_str(), 
				  Int64toHexString(GetLocation(),8).c_str(), GetSource().c_str());
			return 0;
		}

		if(FirstUL->Matches(KLVFill_UL))
		{
			// Skip over the filler, recording how far we went
			Position NewLocation = File->ReadBER();
			NewLocation += File->Tell();
			FillerBytes = NewLocation - Location;
			Location = NewLocation;
		}
	}

	// Sanity check the size for this platform
	// TODO: Should we fix this so that we can read larger metadata - but if so where in memory would we put it if its > 4GB on a 32-bit machine?
	if((sizeof(size_t) < 8) && Size > 0xffffffff)
	{
		error("Maximum read size on this platform is 4Gbytes - However, requested to read metadata at 0x%s which has size of 0x%s\n",
			   Int64toHexString(Location,8).c_str(), Int64toHexString(Size,8).c_str());

		return 0;
	}

	// Read enough bytes for the metadata
	File->Seek(Location);
	DataChunkPtr Data = File->Read(static_cast<size_t>(Size));

	if(Data->Size != static_cast<size_t>(Size))
	{
		error("Header Metadata starting at 0x%s should contain 0x%s bytes, but only 0x%s could be read\n",
			  Int64toHexString(Location,8).c_str(), Int64toHexString(Size,8).c_str(), Int64toHexString(Data->Size,8).c_str());

		Size = static_cast<Length>(Data->Size);
	}

	// Start of data buffer
	const UInt8 *BuffPtr = Data->Data;

	while(Size)
	{
		Length BytesAtItemStart = Bytes;
		if(Size < 16)
		{
			error("Less than 16-bytes of header metadata available after reading 0x%s bytes at 0x%s in file \"%s\"\n", 
				 Int64toHexString(Bytes, 8).c_str(), Int64toHexString(File->Tell(),8).c_str(), File->Name.c_str() );
			break;
		}

/*		// Sanity check the keys
		if((BuffPtr[0] != 6) || (BuffPtr[1] != 0x0e))
		{
			error("Invalid KLV key found at 0x%s in file \"%s\"\n", Int64toHexString(File->Tell(),8).c_str(), File->Name.c_str() );
			break;
		}
*/
		// Build an object (it may come back as an "unknown")
		ULPtr NewUL = new UL(BuffPtr);

		/* If we are loading metadictionaries, we do so when we first read the Preface key */
		if(Feature(FeatureLoadMetadict))
		{
			if(NewUL->Matches(Preface_UL))
			{
				LoadMetadict();
			}
		}

		MDObjectPtr NewItem = new MDObject(NewUL);
		mxflib_assert(NewItem);

		BuffPtr += 16;
		Size -= 16;
		Bytes += 16;

		if(Size < 1)
		{
			error("Incomplete BER length at 0x%s in file \"%s\"\n", Int64toHexString(File->Tell(),8).c_str(), File->Name.c_str() );
			break;
		}

		Length Len = *BuffPtr++;
		Size--;
		Bytes++;
		if(Len >= 0x80)
		{
			UInt32 i = (UInt32)Len & 0x7f;
			if(Size < i)
			{
				error("Incomplete BER length at 0x%s in \"%s\"\n", Int64toHexString(File->Tell(),8).c_str(), File->Name.c_str() );
				break;
			}

			Len = 0;
			while(i--) 
			{
				Len = ((Len<<8) + *(BuffPtr++));
				Size--;
				Bytes++;
			}
		}

		// DRAGONS: KLV Size limit!!
		if(Len > 0xffffffff)
		{
			error("Current implementation KLV size limit of 0xffffffff bytes exceeded at 0x%s in file \"%s\"\n", 
				  Int64toHexString(Location + Bytes,8).c_str(), File->Name.c_str() );
			break;
		}

		if(Size < Len)
		{
			error("KLV length is %s but available data size is only %s after reading 0x%s of header metadata at 0x%s in \"%s\"\n", 
				  UInt64toString(Len).c_str(), UInt64toString(Size).c_str(), Int64toHexString(Bytes, 8).c_str(),
				  Int64toHexString(Location + Bytes,8).c_str(), File->Name.c_str() );

			// Try reading what we have
			Len = Size;
		}

		// Check for the primer until we have found it
		if(!PartitionPrimer)
		{
			if(NewItem->IsA(Primer_UL))
			{
				PartitionPrimer = new Primer;
				UInt32 ThisBytes = PartitionPrimer->ReadValue(BuffPtr, (UInt32)Len);
				Size -= ThisBytes;
				Bytes += ThisBytes;
				BuffPtr += ThisBytes;

				// Skip further processing for the primer
				continue;
			}
		}

		// Skip any filler items
		if(NewItem->IsA(KLVFill_UL))
		{
			Size -= Len;
			Bytes += Len;
			BuffPtr += Len;
			
			// Don't add the filler
			continue;
		}
		
		if(Len)
		{
			NewItem->SetParent(File, BytesAtItemStart + Location,(UInt32)( Bytes - BytesAtItemStart));

			NewItem->ReadValue(BuffPtr,(UInt32) Len, PartitionPrimer);

			// Skip total length, not just the length actually consumed
			Size -= Len;
			Bytes += Len;
			BuffPtr += Len;
		}

		AddMetadata(NewItem);
	}


	return Bytes + FillerBytes;
}