Beispiel #1
0
// 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;
}
Beispiel #2
0
// 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;
}
Beispiel #3
0
/*! 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;
}
Beispiel #4
0
//! 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);
}
Beispiel #5
0
/*! \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;
}