Example #1
0
//! 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;
}