/*! \ret true if all OK */ bool mxflib::Partition::ReadIndex(IndexTablePtr Table) { bool Ret = true; MDObjectListPtr Segments = ReadIndex(); MDObjectList::iterator it = Segments->begin(); while(it != Segments->end()) { // Set error flag if any add fails if(!Table->AddSegment(*it)) Ret = false; it++; } return Ret; }
//! 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; }