コード例 #1
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;
}
コード例 #2
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
// goto _NextBodyLocation
KLVObjectPtr mxflib::Partition::NextElement()
{
	_BodyLocation = _NextBodyLocation;

	// skip the present Object
	_NextBodyLocation = Skip( _NextBodyLocation );

	// skip any trailing KLVFill
	_NextBodyLocation = SkipFill( _NextBodyLocation );

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

	MXFFilePtr PF = Object->GetParentFile();

	// construct a new Object
	if( !_BodyLocation ) return 0;
	else
	{
		PF->Seek( _BodyLocation );
		
		KLVObjectPtr pObj = PF->ReadKLV();

		return pObj; 
	}
}
コード例 #3
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;
}
コード例 #4
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;
}
コード例 #5
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;
}
コード例 #6
0
ファイル: partition.cpp プロジェクト: MOXfiles/mxflib
//! Read any index table segments from a file
MDObjectListPtr mxflib::Partition::ReadIndex(MXFFilePtr File, UInt64 Size)
{
	MDObjectListPtr Ret = new MDObjectList;

	while(Size)
	{
		UInt64 Location = File->Tell();
		UInt64 Bytes;

		MDObjectPtr NewIndex = File->ReadObject(NULL);
		if(NewIndex)
		{
			if((NewIndex->Name() == "IndexTableSegment") || (NewIndex->Name() == "V10IndexTableSegment"))
			{
				Ret->push_back(NewIndex);
				Bytes = File->Tell() - Location;
			}
			else if( NewIndex->IsA(KLVFill_UL) )
			{
				// Skip over the filler
				Bytes = File->Tell() - Location;
			}
			else
			{
				error("Expected to find an IndexTableSegment - found %s at %s\n", 
					  NewIndex->FullName().c_str(), NewIndex->GetSourceLocation().c_str());
				break;
			}
		}
		else
		{
			error("Error reading IndexTableSegment at 0x%s in %s\n", 
				   Int64toHexString(Location,8).c_str(), File->Name.c_str());
			break;
		}

		if(Bytes > Size) break;

		Size -= Bytes;
	}

	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
//! 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);
}
コード例 #9
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;
}
コード例 #10
0
ファイル: esp_wavepcm.cpp プロジェクト: Dheeraj-B/mxflib
/*! If frame or line mapping is used the parameter Count is used to
 *	determine how many items are read. In frame wrapping it is in
 *	units of EditRate, as specified in the call to Use(), which may
 *  not be the frame rate of this essence stream
 *	\note This is the only safe option for clip wrapping
 *	\return Count of bytes transferred
 */
Length mxflib::WAVE_PCM_EssenceSubParser::Write(FileHandle InFile, UInt32 Stream, MXFFilePtr OutFile, UInt64 Count /*=1*/ /*, IndexTablePtr Index*/ /*=NULL*/)
{
	const unsigned int BUFFERSIZE = 32768;
	UInt8 *Buffer = new UInt8[BUFFERSIZE];

	// Move to the current position
	if(BytePosition == 0) BytePosition = DataStart;
	FileSeek(InFile, BytePosition);
	
	// Scan the stream and find out how many bytes to transfer
	// Either use the cached value, or scan the stream and find out how many bytes to read
	if((CachedDataSize == static_cast<size_t>(-1)) || (CachedCount != Count)) ReadInternal(InFile, Stream, Count);
	size_t Bytes = CachedDataSize;
	Length Ret = static_cast<Length>(Bytes);

	// Clear the cached size
	CachedDataSize = static_cast<size_t>(-1);

	while(Bytes)
	{
		size_t ChunkSize;
		
		// Number of bytes to transfer in this chunk
		if(Bytes < BUFFERSIZE) ChunkSize = Bytes; else ChunkSize = BUFFERSIZE;

		FileRead(InFile, Buffer, ChunkSize);
		OutFile->Write(Buffer, ChunkSize);

		Bytes -= ChunkSize;
	}

	// Update the file pointer
	BytePosition = FileTell(InFile);

	// Free the buffer
	delete[] Buffer;

	return Ret; 
}
コード例 #11
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;
}
コード例 #12
0
ファイル: mxfdump.cpp プロジェクト: Dheeraj-B/mxflib
//! Do the main processing (less any pause before exit)
int main_process(int argc, char *argv[])
{
	printf("Dump an MXF file using MXFLib\n");

	std::string DictName = "dict.xml";
	std::list<std::string> SuppDicts;
	int num_options = 0;
	for(int i=1; i<argc; i++)
	{
		if(argv[i][0] == '-')
		{
			num_options++;
			if((argv[i][1] == 'a') || (argv[i][1] == 'A'))
				SortedDump = true;
			else if((argv[i][1] == 'v') || (argv[i][1] == 'V'))
				DebugMode = true;
			else if((argv[i][1] == 'i') || (argv[i][1] == 'I'))
				FullIndex = true;
			else if((argv[i][1] == 'c') || (argv[i][1] == 'C'))
			{
				if(argv[i][2] == '0')
					DumpIDs = false;
				else
					CheckDump = true;
			}
			else if((argv[i][1] == 'b') || (argv[i][1] == 'B'))
				FullBody = true;
//			else if((argv[i][1] == 'g') || (argv[i][1] == 'G'))
//				FollowGlobals = true;
			else if((argv[i][1] == 'l') || (argv[i][1] == 'L'))
				DumpLocation = true;
#ifdef OPTION3ENABLED
			else if((argv[i][1] == 'o') || (argv[i][1] == 'O'))
				ShowBaseline = true;
#endif // OPTION3ENABLED
			else if((argv[i][1] == 'd') || (argv[i][1] == 'D'))
			{
				int Start = 2;
				if((Start == 2) && ((argv[i][Start] == 'd') || (argv[i][Start] == 'D'))) Start++;
				if((argv[i][Start] == '=') || (argv[i][Start] == ':')) Start++;
				if(argv[i][Start]) SuppDicts.push_back(&argv[i][Start]);
				else if(argc > (i+1))
				{
					SuppDicts.push_back(argv[++i]);
					num_options++;
				}
			}
			else if((argv[i][1] == 'u') || (argv[i][1] == 'U'))
			{
				MDObject::SetParseDark(true);
			}
			else if((argv[i][1] == 'x') || (argv[i][1] == 'X'))
			{
				if(argv[i][2] == '0') SetLabelFormat(LabelFormatHex);
				else if(argv[i][2] == '1') SetLabelFormat(LabelFormatTextHex);
				else SetLabelFormat(LabelFormatTextHexMask);
			}
			else if(tolower(argv[i][1]) == 't')
			{
				SetFeature(FeatureLoadMetadict);
				printf("Loading metadictionary contents from file\n");
				if(argv[i][2] == '1')
				{
					BootstrapDict = true;
					printf("Starting with only a minimum compiled-in dictionary\n");
				}
			}
			else if((argv[i][1] == 'm') || (argv[i][1] == 'M'))
			{
				int Start = 2;
				if((argv[i][Start] == '=') || (argv[i][Start] == ':')) Start++;
				if(argv[i][Start]) DictName = &argv[i][Start];
				else if(argc > (i+1))
				{
					DictName = argv[++i];
					num_options++;
				}
#ifdef COMPILED_DICT
				UseCompiledDict = false;
#endif // COMPILED_DICT
			}
			else if((argv[i][1] == 'z') || (argv[i][1] == 'Z'))
				PauseBeforeExit = true;
		}
	}

	if (argc - num_options < 2)
	{
		printf("\nUsage:   %s [options] <filename>\n\n", argv[0]);
		printf("Options: -a         Dump sub-items alpha-sorted\n");
		printf("         -b         Dump body partitions (rather than just header and footer)\n");
		printf("         -c         Check dump (produce simple counts for automated testing)\n");
		printf("         -c0        Don't dump UUID, UMID and Timestamp values (for comparing files)\n");
		printf("         -dd <dict> Load supplementary dictionary (also -d for legacy)\n");
		printf("         -g         Follow global references (if linked)\n");
		printf("         -i         Dump full index tables (can be lengthy)\n");
		printf("         -l         Show the location (byte offset) of metadata items dumped\n");
#ifdef COMPILED_DICT
		printf("         -m <dict>  Specify main dictionary (instead of compile-time version)\n");
#else
		printf("         -m <dict>  Specify main dictionary (instead of dict.xml)\n");
#endif // COMPILED_DICT
#ifdef OPTION3ENABLED
		printf("         -o         Show baseline UL for sets with ObjectClass property\n");
#endif // OPTION3ENABLED
		printf("         -t         Load metadictionary contents from file\n");
		printf("         -t1        Load metadictionary and start from a minimal subset\n");
		printf("         -u         Attempt to parse unknown or 'dark' sets\n");
		printf("         -v         Verbose mode - shows lots of debug info\n");
		printf("         -x0        Always show labels as hex data\n");
		printf("         -x1        Append hex data to labels\n");
		printf("         -x2 or -x  Append hex data to labels if 'fuzzy' matching used\n");
		printf("         -z         Pause for input before final exit\n");
		return 1;
	}

	if(BootstrapDict)
	{
		printf("- using a minimal compile-time dictionary and extending from metadictionary\n");
		LoadDictionary(BootDict);
	}
	else
	{
		if( UseCompiledDict )
		{
			printf("- using compile-time dictionary\n");
			LoadDictionary(DictData);
		}
		else
		{
			printf("- using dictionary %s\n", DictName.c_str());
			LoadDictionary(DictName);
		}
	}

	std::list<std::string>::iterator DictIt = SuppDicts.begin();
	while(DictIt != SuppDicts.end())
	{
		LoadDictionary(*DictIt);
		DictIt++;
	}

	// If we are NOT dumping IDs replace thier traits
	if(!DumpIDs)
	{
		UpdateTraitsMapping("Internal-UUID", new MessageTraits("{UUID}"));
		UpdateTraitsMapping("UUID", new MessageTraits("{UUID}"));
		UpdateTraitsMapping("UMID", new MessageTraits("{UMID}"));
		UpdateTraitsMapping("Timestamp", new MessageTraits("{Timestamp}"));
	}

	MXFFilePtr TestFile = new MXFFile;
	if (! TestFile->Open(argv[num_options+1], true))
	{
		perror(argv[num_options+1]);
		return 1;
	}

	// Get a RIP (however possible)
	TestFile->GetRIP();

	unsigned int PartitionNumber = 0;
	RIP::iterator it = TestFile->FileRIP.begin();
	while(it != TestFile->FileRIP.end())
	{
		PartitionNumber++;
		if(CheckDump)
			printf("\nPartition for BodySID 0x%04x\n", (*it).second->BodySID);
		else
			printf("\nPartition at 0x%s is for BodySID 0x%04x\n", Int64toHexString((*it).second->ByteOffset,8).c_str(), (*it).second->BodySID);

		// Only dump header and footer unless asked for all partitions
		if(FullBody || (PartitionNumber == 1) || (PartitionNumber == TestFile->FileRIP.size()))
		{
			TestFile->Seek((*it).second->ByteOffset);
			PartitionPtr ThisPartition = TestFile->ReadPartition();
			if(ThisPartition)
			{
				if(CheckDump)
				{
					if(ThisPartition->ReadMetadata() == 0)
					{
						printf("No header metadata in this partition\n");
					}
					else
					{
						printf(" Top level count = %d\n", (int)ThisPartition->TopLevelMetadata.size());
						printf(" Set/Pack count = %d\n", (int)ThisPartition->AllMetadata.size());
						
						size_t Count = 0;
						MDObjectList::iterator it = ThisPartition->AllMetadata.begin();
						while(it != ThisPartition->AllMetadata.end())
						{
							Count += (*it)->size();
							it++;
						}

						printf(" Sub item count = %d\n", (int)Count);
					}

					// Read any index table segments!
					MDObjectListPtr Segments = ThisPartition->ReadIndex();
					if(Segments->empty())
					{
						printf("No index table in this partition\n");
					}
					else
					{
						IndexTablePtr Table = new IndexTable;

						MDObjectList::iterator it = Segments->begin();

						while(it != Segments->end())
						{
							// Summarize this new segment
							
							UInt32 Streams = 1;
							MDObjectPtr DeltaEntryArray = (*it)[DeltaEntryArray_UL];
							if(DeltaEntryArray && DeltaEntryArray->GetType()->size())
							{
								Streams = static_cast<UInt32>(DeltaEntryArray->size() / DeltaEntryArray->GetType()->size());
								if(Streams == 0) Streams = 1;	// Fix for bad DeltaEntryArray
							}

							Position Start = (*it)->GetInt64(IndexStartPosition_UL);
							Length Duration = (*it)->GetInt64(IndexDuration_UL);
							UInt32 IndexSID = (*it)->GetUInt(IndexSID_UL);
							UInt32 BodySID = (*it)->GetUInt(BodySID_UL);
							
							if(Duration == 0) printf("CBR Index Table Segment (covering whole Essence Container) :\n");
							else printf("\nIndex Table Segment (first edit unit = %s, duration = %s) :\n", Int64toString(Start).c_str(), Int64toString(Duration).c_str());

							printf("  Indexing BodySID 0x%04x from IndexSID 0x%04x\n", BodySID, IndexSID);

							it++;
						}
					}
				}
				else
				{
					// Don't dump the last partition unless it is a footer or we are dumping all
					// DRAGONS: What is the PartitionNumber != RIP-Size thing about?
					if(FullBody || (PartitionNumber == 1) || (PartitionNumber != TestFile->FileRIP.size()) 
								|| (ThisPartition->IsA(CompleteFooter_UL)) || (ThisPartition->IsA(Footer_UL)) )
					{
						DumpObject(ThisPartition->Object,"");

						if(ThisPartition->ReadMetadata() == 0)
						{
							printf("No header metadata in this partition\n");
						}
						else
						{
							printf("\nHeader Metadata:\n");
							
							MDObjectList::iterator it2 = ThisPartition->TopLevelMetadata.begin();
							while(it2 != ThisPartition->TopLevelMetadata.end())
							{
								DumpObject(*it2,"  ");
								it2++;
							}
							printf("\n");
						}

						// Read any index table segments!
						MDObjectListPtr Segments = ThisPartition->ReadIndex();
						if(Segments->empty())
						{
							printf("No index table in this partition\n");
						}
						else
						{
							IndexTablePtr Table = new IndexTable;

							MDObjectList::iterator it = Segments->begin();

							while(it != Segments->end())
							{
								Table->AddSegment(*it);
							
								// Demonstrate this new segment
								
								UInt32 Streams = 1;
								MDObjectPtr DeltaEntryArray = (*it)[DeltaEntryArray_UL];
								if(DeltaEntryArray)
								{
									Streams = static_cast<UInt32>(DeltaEntryArray->size());
									if(Streams == 0) Streams = 1;	// Fix for bad DeltaEntryArray
								}

								Position Start = (*it)->GetInt64(IndexStartPosition_UL);
								Length Duration = (*it)->GetInt64(IndexDuration_UL);
								UInt32 IndexSID = (*it)->GetUInt(IndexSID_UL);
								UInt32 BodySID = (*it)->GetUInt(BodySID_UL);
								
								if(Duration == 0) printf("CBR Index Table Segment (covering whole Essence Container) :\n");
								else printf("\nIndex Table Segment (first edit unit = %s, duration = %s) :\n", Int64toString(Start).c_str(), Int64toString(Duration).c_str());

								printf("  Indexing BodySID 0x%04x from IndexSID 0x%04x\n", BodySID, IndexSID);

								if(Duration < 1) Duration = 6;		// Could be CBR
								if(!FullIndex && Duration > 35) Duration = 35;	// Don't go mad!

								int i;
								printf( "\n Bytestream Order:\n" );
								for(i=0; i<Duration; i++)
								{
									UInt32 j;
									for(j=0; j<Streams; j++)
									{
										IndexPosPtr Pos = Table->Lookup(Start + i,j,false);
										printf("  EditUnit %3s for stream %d is at 0x%s", Int64toString(Start + i).c_str(), j, Int64toHexString(Pos->Location,8).c_str());
										printf(", TempOffset=%d", Pos->TemporalOffset);
										printf(", Flags=%02x", Pos->Flags);
										if(Pos->Exact) printf("  *Exact*\n"); else printf("\n");
									}
								}

								printf( "\n Presentation Order:\n" );
								for(i=0; i<Duration; i++)
								{
									UInt32 j;
									for(j=0; j<Streams; j++)
									{
										IndexPosPtr Pos = Table->Lookup(Start + i,j);
										printf("  EditUnit %3s for stream %d is at 0x%s", Int64toString(Start + i).c_str(), j, Int64toHexString(Pos->Location,8).c_str());
										printf(", TempOffset=%d", Pos->TemporalOffset);
										printf(", Flags=%02x", Pos->Flags);
	///									printf(", Keyframe is at 0x%s", Int64toHexString(Pos->KeyLocation,8).c_str() );

										if(Pos->Exact) printf("  *Exact*\n");
										else if(Pos->OtherPos) printf(" (Location of un-reordered position %s)\n", Int64toString(Pos->ThisPos).c_str());
										else printf("\n");
									}
								}

								it++;
							}
						}
					}
				}
			}
		}

		it++;
	}

	if(TestFile->ReadRIP())
	{
		printf("\nRead RIP\n");
		PartitionInfoMap::iterator it = TestFile->FileRIP.begin();
		while(it != TestFile->FileRIP.end())
		{
			if(CheckDump)
				printf("  BodySID 0x%04x", (*it).second->BodySID);
			else
				printf("  BodySID 0x%04x is at 0x%s", (*it).second->BodySID, Int64toHexString((*it).second->ByteOffset,8).c_str());

			if((*it).second->ThePartition)
				printf(" type %s\n", (*it).second->ThePartition->Name().c_str());
			else
				printf(" and is not loaded\n");

			it++;
		}
	}

	if(TestFile->ScanRIP())
	{
		printf("\nScanned RIP\n");
		PartitionInfoMap::iterator it = TestFile->FileRIP.begin();
		while(it != TestFile->FileRIP.end())
		{
			if(CheckDump)
				printf("  BodySID 0x%04x", (*it).second->BodySID);
			else
				printf("  BodySID 0x%04x is at 0x%s", (*it).second->BodySID, Int64toHexString((*it).second->ByteOffset,8).c_str());

			if((*it).second->ThePartition)
				printf(" type %s\n", (*it).second->ThePartition->Name().c_str());
			else
				printf(" and is not loaded\n");

			it++;
		}
	}

/*	if(TestFile->BuildRIP())
	{
		printf("\nBuilt RIP\n");
		PartitionInfoList::iterator it = TestFile->FileRIP.begin();
		while(it != TestFile->FileRIP.end())
		{
			printf("  BodySID 0x%04x is at 0x%s", (*it)->BodySID, Int64toHexString((*it)->ByteOffset,8).c_str());

			if((*it)->ThePartition)
				printf(" type %s\n", (*it)->ThePartition->Name().c_str());
			else
				printf(" and is not loaded\n");

			it++;
		}
	}
*/
	TestFile->Close();

/*	PrimerPtr NewPrimer = new Primer;

	unsigned char Key[16] = { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x04, 0x04, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 };
	
	Tag ThisTag = NewPrimer->Lookup(new UL(Key));
	printf("Tag    = %s\n", Tag2String(ThisTag).c_str());

	Key[11] = 5;
	ThisTag = NewPrimer->Lookup(new UL(Key));
	printf("NewTag = %s\n", Tag2String(ThisTag).c_str());

	ThisTag = NewPrimer->Lookup(new UL(Key));
	printf("NewTag = %s\n", Tag2String(ThisTag).c_str());

	Key[12] = 1;
	ThisTag = NewPrimer->Lookup(new UL(Key));
	printf("NewTag = %s\n", Tag2String(ThisTag).c_str());
*/

	return 0;
}