// schemaName == "" means all schemas (i.e. all metadata in the stream) // setName == "" means the whole schema with descriptions // schemaName and setName specified means removal all the metadata items from the specified set void removeMetadata(const string& path, const string& schemaName = "", const string& setName = "") { cout << "\nRemoving metadata: " << (schemaName.empty() ? string("*") : schemaName + '/' + (setName.empty() ? string("*") : setName) ) << endl; MetadataStream ms; if (!ms.open(path, MetadataStream::ReadWrite)) throw std::runtime_error("Can't open MetadataStream"); vector<string> schemas; if(schemaName.empty()) { // remove all metadata ms.remove(); } else { schemas.push_back(schemaName); for (unsigned int sNum = 0; sNum < schemas.size(); sNum++) { auto sName = schemas[sNum]; cout << "\t* (" << sNum << ") [schema]: " << sName << endl; if(!ms.load(sName)) throw std::runtime_error(string("Error loading schema: ") + sName); vector<shared_ptr<MetadataDesc>>mDescs; if(setName.empty()) { // remove the whole schema with descriptions ms.remove( ms.getSchema(sName) ); } else { mDescs.push_back(ms.getSchema(sName)->findMetadataDesc(setName)); for (unsigned int setNum = 0; setNum < mDescs.size(); setNum++) { auto mDesc = mDescs[setNum]; string setName = mDesc->getMetadataName(); MetadataSet set = ms.queryByName(setName); cout << "\t\t* (" << sNum << "." << setNum << ") [set]: " << setName << "(" << set.size() << " items)" << endl; ms.remove(set); set.clear(); } } } } cout << "Saving stream..." << endl; ms.save(); cout << "Done." << endl; }
void printMetadataStructure(const string& path) { cout << "\nPrinting metadata structure.\n" << "[stream]: " << path << endl; MetadataStream ms; if (!ms.open(path, MetadataStream::ReadOnly)) throw std::runtime_error("Can't open MetadataStream"); auto sNames = ms.getAllSchemaNames(); for (unsigned int sNum = 0; sNum < sNames.size(); sNum++) { auto sName = sNames[sNum]; cout << "\t* (" << sNum << ") [schema]: " << sName << endl; if(!ms.load(sName)) // we need to load schema to get items count throw std::runtime_error(string("Error loading schema: ") + sName); auto mDescs = ms.getSchema(sName)->getAll(); for (unsigned int setNum = 0; setNum < mDescs.size(); setNum++) { auto mDesc = mDescs[setNum]; string setName = mDesc->getMetadataName(); auto setSize = ms.queryByName(setName).size(); string fieldsString; const char * separator = ""; auto fields = mDesc->getFields(); for (auto fd = fields.begin(); fd != fields.end(); fd++) { fieldsString += separator + fd->name; separator = ","; } cout << "\t\t* (" << sNum << "." << setNum << ") [set]: " << setName << "(" << setSize << " items)" << " {" << fieldsString << "}" << endl; } } }
void XMPMetadataSource::loadReference(const MetaString& thisRefPath, const shared_ptr<Metadata>& md, MetadataStream& stream) { XMP_Int64 id; MetaString tmpPath; MetaString refName; SXMPUtils::ComposeStructFieldPath(VMF_NS, thisRefPath.c_str(), VMF_NS, REF_NAME, &tmpPath); if (!xmp->GetProperty(VMF_NS, tmpPath.c_str(), &refName, nullptr)) refName = ""; SXMPUtils::ComposeStructFieldPath(VMF_NS, thisRefPath.c_str(), VMF_NS, REF_ID, &tmpPath); if (!xmp->GetProperty_Int64(VMF_NS, tmpPath.c_str(), &id, nullptr)) { VMF_EXCEPTION(DataStorageException, "Broken reference by path" + thisRefPath); } IdType realId = id; shared_ptr<Metadata> refTo = stream.getById(realId); if (!refTo) { auto it = idMap.find(realId); if (it == idMap.end()) { VMF_EXCEPTION(DataStorageException, "Undefined reference by path " + thisRefPath); } InternalPath path = it->second; std::shared_ptr<MetadataSchema> refSchemaDesc = stream.getSchema(path.schema); std::shared_ptr<MetadataDesc> refMetadataDesc = refSchemaDesc->findMetadataDesc(path.metadata); loadMetadata(path.path, refMetadataDesc, stream); refTo = stream.getById(realId); } md->addReference(refTo, refName); }
// setName == "" means all sets in the specified schema // schemaName == "" means all schemas (i.e. all metadata) void dumpMetadata(const string& path, const string& schemaName = "", const string& setName = "") { cout << "\nDumping metadata: " << (schemaName.empty() ? string("*") : schemaName + '/' + (setName.empty() ? string("*") : setName) ) << endl; MetadataStream ms; if (!ms.open(path, MetadataStream::ReadOnly)) throw std::runtime_error("Can't open MetadataStream"); vector<string> schemas; if(schemaName.empty()) ms.getAllSchemaNames().swap(schemas); else schemas.push_back(schemaName); for (unsigned int sNum = 0; sNum < schemas.size(); sNum++) { auto sName = schemas[sNum]; cout << "* (" << sNum << ") [schema]: " << sName << endl; if(!ms.load(sName)) throw std::runtime_error(string("Error loading schema: " + sName).c_str()); vector<shared_ptr<MetadataDesc>>mDescs; if(setName.empty()) ms.getSchema(sName)->getAll().swap(mDescs); else mDescs.push_back(ms.getSchema(sName)->findMetadataDesc(setName)); for (unsigned int setNum = 0; setNum < mDescs.size(); setNum++) { auto mDesc = mDescs[setNum]; string setName = mDesc->getMetadataName(); MetadataSet set = ms.queryByName(setName); cout << "\t* (" << sNum << "." << setNum << ") [set]: " << setName << "(" << set.size() << " items)" << endl; if(set.empty()) continue; vector<string> fields(set[0]->getFieldNames()); int itemNum = 0; for (auto item = set.begin(); item != set.end(); item++) { cout << "\t\t* (" << sNum << "." << setNum << "." << ++itemNum << ") { "; const char * separator = ""; for (auto f = fields.begin(); f != fields.end(); f++) { cout << separator << *f << "="; try { cout << (*item)->getFieldValue(*f).toString(); } catch(vmf::Exception& e) { cout << '<' << e.what() << '>'; } separator = ", "; } cout << " }" << endl; } } } }
void XMPMetadataSource::loadMetadata(const MetaString& pathToCurrentMetadata, const shared_ptr<MetadataDesc>& description, MetadataStream& stream) { IdType id; loadMetadataId(pathToCurrentMetadata, id); shared_ptr<Metadata> thisMetadata = stream.getById(id); if (thisMetadata) { // already loaded return; } long long frameIndex; loadMetadataFrameIndex(pathToCurrentMetadata, frameIndex); long long numOfFrames; loadMetadataNumOfFrames(pathToCurrentMetadata, numOfFrames); long long timestamp; loadMetadataTime(pathToCurrentMetadata, timestamp); long long duration; loadMetadataDuration(pathToCurrentMetadata, duration); shared_ptr<MetadataAccessor> metadataAccessor(new MetadataAccessor(description)); metadataAccessor->setFrameIndex(frameIndex, numOfFrames); metadataAccessor->setTimestamp(timestamp, duration); metadataAccessor->setId(id); MetaString fieldsPath; SXMPUtils::ComposeStructFieldPath(VMF_NS, pathToCurrentMetadata.c_str(), VMF_NS, METADATA_FIELDS, &fieldsPath); shared_ptr<MetadataSchema> thisSchemaDesc = stream.getSchema(description->getSchemaName()); shared_ptr<MetadataDesc> thisPropertyDesc = thisSchemaDesc->findMetadataDesc(description->getMetadataName()); SXMPIterator fieldsIterator(*xmp, VMF_NS, fieldsPath.c_str(), kXMP_IterJustChildren); MetaString currentFieldPath; while(fieldsIterator.Next(NULL, ¤tFieldPath)) { loadField(currentFieldPath, metadataAccessor, thisPropertyDesc); } MetadataStreamAccessor* streamAccessor = (MetadataStreamAccessor*) &stream; streamAccessor->internalAdd(metadataAccessor); // Load refs only after adding to steam to stop recursive loading when there are circular references MetaString pathToRefs; SXMPUtils::ComposeStructFieldPath(VMF_NS, pathToCurrentMetadata.c_str(), VMF_NS, METADATA_REFERENCES, &pathToRefs); SXMPIterator refsIterator(*xmp, VMF_NS, pathToRefs.c_str(), kXMP_IterJustChildren); MetaString currentRefPath; while(refsIterator.Next(NULL, ¤tRefPath)) { loadReference(currentRefPath, metadataAccessor, stream); } }
void XMPMetadataSource::loadPropertyByPath(const MetaString& pathToProperty, const MetaString& schemaName, MetadataStream& stream) { shared_ptr<MetadataSchema> schema(stream.getSchema(schemaName)); MetaString metadataName; loadPropertyName(pathToProperty, metadataName); MetaString pathToMetadataSet; SXMPUtils::ComposeStructFieldPath(VMF_NS, pathToProperty.c_str(), VMF_NS, PROPERTY_SET, &pathToMetadataSet); shared_ptr<MetadataDesc> description(schema->findMetadataDesc(metadataName)); SXMPIterator mIter(*xmp, VMF_NS, pathToMetadataSet.c_str(), kXMP_IterJustChildren); MetaString pathToCurrentMetadata; while(mIter.Next(nullptr, &pathToCurrentMetadata)) { loadMetadata(pathToCurrentMetadata, description, stream); } //unsorted stream fails on save stream.sortById(); }
void XMPMetadataSource::saveSchema(const MetaString& schemaName, const MetadataStream& stream) { shared_ptr<MetadataSchema> thisSchemaDescription = stream.getSchema(schemaName); MetaString thisSchemaPath = findSchema(schemaName); if (thisSchemaPath.empty()) { xmp->AppendArrayItem(VMF_NS, VMF_GLOBAL_SCHEMAS_ARRAY, kXMP_PropValueIsArray, NULL, kXMP_PropValueIsStruct); SXMPUtils::ComposeArrayItemPath(VMF_NS, VMF_GLOBAL_SCHEMAS_ARRAY, kXMP_ArrayLastItem, &thisSchemaPath); xmp->SetStructField(VMF_NS, thisSchemaPath.c_str(), VMF_NS, SCHEMA_NAME, schemaName); xmp->SetStructField(VMF_NS, thisSchemaPath.c_str(), VMF_NS, SCHEMA_SET, nullptr, kXMP_PropValueIsArray); } MetadataSet thisSchemaSet = stream.queryBySchema(schemaName); vector< shared_ptr<MetadataDesc> > thisSchemaProperties = thisSchemaDescription->getAll(); for(auto descIter = thisSchemaProperties.begin(); descIter != thisSchemaProperties.end(); ++descIter) { MetaString metadataName = (*descIter)->getMetadataName(); MetadataSet currentPropertySet(thisSchemaSet.queryByName(metadataName)); saveProperty(currentPropertySet, thisSchemaPath, metadataName); } }
void readAndDumpEncryptedMetadata(const umf_string& videoFile, std::shared_ptr<Encryptor> encryptor) { cout << "Opening file name '" << videoFile << "'" << endl; // Open new metadata stream to load and print saved metadata MetadataStream loadStream; loadStream.setEncryptor(encryptor); if (!loadStream.open(videoFile, MetadataStream::ReadOnly)) { cerr << "Can't open file " << videoFile << endl; exit(1); } if(loadStream.getUseEncryption()) { cout << "The whole stream is encrypted" << endl; } // Get all schemas vector<string> schemas = loadStream.getAllSchemaNames(); // and dump all the related data to console for(size_t sNum = 0; sNum < schemas.size(); sNum++) { string sName = schemas[sNum]; std::shared_ptr<MetadataSchema> schemaPtr = loadStream.getSchema(sName); bool schemaEncrypted = schemaPtr->getUseEncryption(); cout << "* (" << sNum << ") [schema]: " << sName; if(schemaEncrypted) { cout << ", encrypted"; } cout << endl; if(!loadStream.load(sName)) { cerr << "Error loading schema " << sName << endl; exit(1); } vector< shared_ptr<MetadataDesc> > mDescs = schemaPtr->getAll(); for(size_t setNum = 0; setNum < mDescs.size(); setNum++) { shared_ptr<MetadataDesc> mDesc = mDescs[setNum]; string setName = mDesc->getMetadataName(); bool metadescEncrypted = mDesc->getUseEncryption(); MetadataSet mdSet = loadStream.queryByName(setName); cout << "\t* (" << sNum << "." << setNum << ") [set]: "; cout << setName << "(" << mdSet.size() << " items)"; if(mdSet.empty()) continue; vector<string> fields(mdSet[0]->getFieldNames()); cout << " {"; const char * separator = ""; for(FieldDesc fDesc : mDesc->getFields()) { cout << separator << fDesc.name; if(fDesc.useEncryption) { cout << " encrypted"; } separator = ", "; } cout << "}"; if(metadescEncrypted) { cout << ", encrypted"; } cout << endl; int itemNum = 0; for(const std::shared_ptr<Metadata>& item : mdSet) { if (itemNum++ <= 3) { cout << "\t\t* (" << sNum << "." << setNum << "." << itemNum << ") { "; separator = ""; for (const string& f : fields) { cout << separator << f << "="; try { cout << item->getFieldValue(f).toString(); } catch (umf::Exception& e) { cout << '<' << e.what() << '>'; } if(item->findField(f)->getUseEncryption()) { cout << " encrypted"; } separator = ", "; } cout << " }"; long long t = item->getTime(); if (t >= 0) cout << ", time " << t; if(item->getUseEncryption()) cout << ", encrypted"; cout << endl; } else cout << '.'; } cout << "\n\t\t" << itemNum << " items." << endl; } } // Close metadata stream loadStream.close(); }