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); }
int encrypt_custom(const string& videoFile, EncryptionScope scope) { cout << "Custom encryption usage sample:" << endl; MetadataStream mdStream; if (!mdStream.open(videoFile, MetadataStream::Update | MetadataStream::IgnoreUnknownCompressor | MetadataStream::IgnoreUnknownEncryptor)) { cerr << "Can't open file '" + videoFile + "'" << endl; exit(1); } std::shared_ptr<Encryptor> encryptor = std::make_shared<MyEncryptor>("thereisnospoon"); cout << "Generating metadata..." << endl; generateEncryptedMetadata(mdStream, scope); mdStream.setEncryptor(encryptor); cout << "Saving metadata using custom encryptor..." << endl; cout << "Encryption algorithm info: " << encryptor->getHint() << endl; mdStream.save(); mdStream.close(); cout << "Loading metadata back..." << endl; readAndDumpEncryptedMetadata(videoFile, encryptor); cout << "That's all!" << endl; return 0; }
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); } }
// 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; }
std::shared_ptr<Metadata> MetadataStream::import( MetadataStream& srcStream, std::shared_ptr< Metadata >& spMetadata, std::map< IdType, IdType >& mapIds, long long nTarFrameIndex, long long nSrcFrameIndex, long long nNumOfFrames ) { auto nSrcMetadataId = spMetadata->getId(); // Check to make sure the metadata belongs to the source stream if( nSrcMetadataId < 0 || srcStream.getById( nSrcMetadataId ) != spMetadata ) { VMF_EXCEPTION(IncorrectParamException, "The input metadata does not belong to the source stream!" ); } // Skip if it has already been imported if( mapIds.find( nSrcMetadataId ) != mapIds.end() ) { auto spNewMetadata = this->getById( mapIds[ nSrcMetadataId ] ); if( spNewMetadata == nullptr ) { VMF_EXCEPTION(InternalErrorException, "Unexpected exception!" ); } return spNewMetadata; } // Make a deep copy, add to the new stream, and add to the map std::shared_ptr< Metadata > spNewMetadata( new Metadata( *spMetadata )); if( !spNewMetadata->shiftFrameIndex( nTarFrameIndex, nSrcFrameIndex, nNumOfFrames )) { return nullptr; } auto nNewMetadataId = this->add( spNewMetadata ); mapIds[ nSrcMetadataId ] = nNewMetadataId; // Wire to the correct description auto spNewSchema = this->getSchema( spMetadata->getSchemaName() ); auto spNewDescriptor = spNewSchema == nullptr ? nullptr : spNewSchema->findMetadataDesc( spMetadata->getName() ); if( spNewDescriptor == nullptr ) { VMF_EXCEPTION(InternalErrorException, "Metadata schema or description was not found!" ); } spNewMetadata->setDescriptor( spNewDescriptor ); // Import all references recursively spNewMetadata->removeAllReferences(); auto vReferences = spMetadata->getAllReferences(); std::for_each( vReferences.begin(), vReferences.end(), [&]( Reference& reference ) { // Import the reference to the new stream std::shared_ptr<Metadata> md = reference.getReferenceMetadata().lock(); auto spNewReference = import( srcStream, md, mapIds, nTarFrameIndex, nSrcFrameIndex, nNumOfFrames ); // Add as reference if( spNewReference != nullptr ) spNewMetadata->addReference( spNewReference ); }); return spNewMetadata; }
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 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::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); } }
// 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 generateMetadata(MetadataStream& mdStream) { mdStream.remove(); mdStream.save(); mdStream.close(); mdStream.reopen(MetadataStream::OpenModeFlags::Update); // Create a GPS metadata field descriptions shared_ptr<MetadataSchema> gpsSchema(new MetadataSchema(GPS_SCHEMA_NAME)); UMF_METADATA_BEGIN(GPS_DESC); UMF_FIELD_REAL(GPS_COORD_LAT_FIELD); UMF_FIELD_REAL(GPS_COORD_LNG_FIELD); UMF_METADATA_END(gpsSchema); cout << "Adding metadata schema '" << GPS_SCHEMA_NAME << "':" << endl; // Add schema to metadata stream mdStream.addSchema(gpsSchema); shared_ptr<Metadata> gpsMetadata; // Let there be an UFO moving around some point on Earth const int nPoints = 1<<10; for(int i = 0; i < nPoints; i++) { float lat = float( 37.235 + cos(i/25.0*2.0*PI) * 0.001); float lng = float(-115.811 + sin(i/25.0*2.0*PI) * 0.001); long long time = i; if (i<3) cout << "\t[" << i << "] 'lat " << lat << " lng " << lng << '\'' << " time " << time << endl; else cout << '.'; // Create a metadata item gpsMetadata = shared_ptr<Metadata>(new Metadata(gpsSchema->findMetadataDesc(GPS_DESC))); // Fill item fields gpsMetadata->push_back(FieldValue(GPS_COORD_LAT_FIELD, lat)); gpsMetadata->push_back(FieldValue(GPS_COORD_LNG_FIELD, lng)); gpsMetadata->setTimestamp(time); // Add to metadata a new item mdStream.add(gpsMetadata); } cout << "\n\t" << nPoints << " items." << endl; }
int main(int argc, char **argv) { QApplication a(argc, argv); umf::initialize(); std::string appPath = argv[0]; #ifdef WIN32 char delim = '\\'; #else char delim = '/'; #endif size_t pos = appPath.find_last_of(delim); if (pos != std::string::npos) { workingPath = appPath.substr(0, pos); } if (QFile::exists(TEST_FILE)) QFile::remove(TEST_FILE); QFile::copy(VIDEO_FILE.c_str(), "global_test.avi"); const umf_string FILE_NAME = "global_test.avi"; const umf_string SCHEMA_NAME = "demo-unicode-schema"; const umf_string STRING_METADATA = "unicode-string-metadata"; { auto schema = make_shared<MetadataSchema>(SCHEMA_NAME); auto desc = make_shared<MetadataDesc>(STRING_METADATA, Variant::type_string); schema->add(desc); MetadataStream stream; if (!stream.open(FILE_NAME, MetadataStream::Update)) { cerr << "Failed to open file " << FILE_NAME << endl; return -1; } stream.addSchema(schema); auto metadata = make_shared<Metadata>(desc); // UTF-8 string with Russian text std::string str("\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82\x21"); metadata->addValue(str); stream.add(metadata); if (!stream.save()) { cerr << "Failed to save file " << FILE_NAME << endl; return -1; } stream.close(); } { MetadataStream stream; if (!stream.open(FILE_NAME, MetadataStream::ReadOnly)) { cerr << "Failed to open file " << FILE_NAME << endl; return -1; } if (!stream.load(SCHEMA_NAME)) { cerr << "Failed to load schema " << SCHEMA_NAME << endl; return -1; } auto stringMetadata = stream.queryByName(STRING_METADATA); auto savedMetadata = stringMetadata.at(0); std::string savedString = savedMetadata->at(0); QMessageBox::information(NULL, "UMF Demo Unicode", QString::fromUtf8(savedString.c_str())); } umf::terminate(); return 0; }
void generateEncryptedMetadata(MetadataStream &mdStream, EncryptionScope scope) { mdStream.remove(); mdStream.save(); mdStream.close(); mdStream.reopen(MetadataStream::OpenModeFlags::Update); // Create a GPS metadata field descriptions shared_ptr<MetadataSchema> gpsSchema(new MetadataSchema(GPS_SCHEMA_NAME)); UMF_METADATA_BEGIN(GPS_DESC); UMF_FIELD_REAL(GPS_COORD_LAT_FIELD); UMF_FIELD_REAL(GPS_COORD_LNG_FIELD); UMF_METADATA_END(gpsSchema); //set encryption for all fields/metadata/schema/stream std::shared_ptr< MetadataDesc > metadesc = gpsSchema->findMetadataDesc(GPS_DESC); FieldDesc& field = metadesc->getFieldDesc(GPS_COORD_LNG_FIELD); if(scope == EncryptionScope::Whole) { mdStream.setUseEncryption(true); } else if(scope == EncryptionScope::AllSchema) { gpsSchema->setUseEncryption(true); } else if(scope == EncryptionScope::AllMetaDesc) { metadesc->setUseEncryption(true); } else if(scope == EncryptionScope::AllFieldDesc) { field.useEncryption = true; } cout << "Adding metadata schema '" << GPS_SCHEMA_NAME << "':" << endl; // Add schema to metadata stream mdStream.addSchema(gpsSchema); shared_ptr<Metadata> gpsMetadata; // Let there be an UFO moving around some point on Earth const int nPoints = 1<<10; for(int i = 0; i < nPoints; i++) { float lat = float( 37.235 + cos(i/25.0*2.0*PI) * 0.001); float lng = float(-115.811 + sin(i/25.0*2.0*PI) * 0.001); long long time = i; if (i<3) cout << "\t[" << i << "] 'lat " << lat << " lng " << lng << '\'' << " time " << time << endl; else cout << '.'; // Create a metadata item gpsMetadata = shared_ptr<Metadata>(new Metadata(gpsSchema->findMetadataDesc(GPS_DESC))); //Encrypt specified fields/records or not bool encryptRecord = false, encryptField = false; if(i == 0) { if(scope == EncryptionScope::OneField) { encryptField = true; } if(scope == EncryptionScope::OneMetadata) { encryptRecord = true; } } // Fill item fields gpsMetadata->push_back(FieldValue(GPS_COORD_LAT_FIELD, lat, encryptField)); gpsMetadata->push_back(FieldValue(GPS_COORD_LNG_FIELD, lng)); gpsMetadata->setTimestamp(time); gpsMetadata->setUseEncryption(encryptRecord); // Add to metadata a new item mdStream.add(gpsMetadata); } cout << "\n\t" << nPoints << " items." << endl; }
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(); }
int main(int argc, char *argv[]) { initialize(); string appPath = argv[0]; #ifdef WIN32 char delim = '\\'; #else char delim = '/'; #endif size_t pos = appPath.find_last_of(delim); if (pos != string::npos) { workingPath = appPath.substr(0, pos + 1); } // Copy test video file to another location. copyFile(VIDEO_FILE, "global_test.avi"); cout << "VMF sample: read/write GPS location and time" << endl << endl; const string FILE_NAME = "global_test.avi"; const string META_SOURCE_NAME = "test-id"; const string GPS_DESC = "gps"; const string GPS_COORD_FIELD = "GPS"; const string GPS_TIME_FIELD = "Time"; const string GPS_SCHEMA_NAME = "gps_schema"; const string GPS_METADATA_ITEM1 = "lat=53.78,lng=132.46"; const string GPS_METADATA_ITEM2 = "lat=53.28,lng=131.87"; const string GPS_METADATA_ITEM3 = "lat=52.95,lng=131.41"; const string GPS_METADATA_ITEM4 = "lat=52.49,lng=130.98"; cout << "Adding metadata..." << endl; cout << "Opening file name '" << FILE_NAME << "'" << endl; // Open metadata stream MetadataStream mdStream; if (!mdStream.open(FILE_NAME, MetadataStream::ReadWrite)) { cerr << "Can't open file " << FILE_NAME << endl; exit(1); } // Create a GPS metadata field descriptions vector<FieldDesc> fieldDesc; fieldDesc.push_back(FieldDesc(GPS_COORD_FIELD)); // GPS coordinate as string fieldDesc.push_back(FieldDesc(GPS_TIME_FIELD)); // Associated time as string // Create GPS metadata description shared_ptr<MetadataDesc> gpsDesc(new MetadataDesc(GPS_DESC, fieldDesc)); // Create GPS metadata schema shared_ptr<MetadataSchema> gpsSchema(new MetadataSchema(GPS_SCHEMA_NAME)); // Add description to the schema gpsSchema->add(gpsDesc); string t = "21.02.2013 18:35"; cout << "Add metadata schema '" << GPS_SCHEMA_NAME << "'" << endl; // Add schema to metadata stream mdStream.addSchema(gpsSchema); shared_ptr<Metadata> gpsMetadata; t = "21.02.2013 18:45"; cout << "Adding metadata's item '" << GPS_METADATA_ITEM1 << "' with associated time " << t << endl; // Create a metadata item gpsMetadata = shared_ptr<Metadata>(new Metadata(gpsDesc)); // Fill item fields gpsMetadata->push_back(FieldValue(GPS_COORD_FIELD, GPS_METADATA_ITEM1)); gpsMetadata->push_back(FieldValue(GPS_TIME_FIELD, t)); // Add to metadata a new item mdStream.add(gpsMetadata); t = "21.02.2013 19:28"; cout << "Adding metadata's item '" << GPS_METADATA_ITEM2 << "' with associated time " << t << endl; gpsMetadata = shared_ptr<Metadata>(new Metadata(gpsDesc)); gpsMetadata->push_back(FieldValue(GPS_COORD_FIELD, GPS_METADATA_ITEM2)); gpsMetadata->push_back(FieldValue(GPS_TIME_FIELD, t)); mdStream.add(gpsMetadata); t = "21.02.2013 21:02"; cout << "Adding metadata's item '" << GPS_METADATA_ITEM3 << "' with associated time " << t << endl; gpsMetadata = shared_ptr<Metadata>(new Metadata(gpsDesc)); gpsMetadata->push_back(FieldValue(GPS_COORD_FIELD, GPS_METADATA_ITEM3)); gpsMetadata->push_back(FieldValue(GPS_TIME_FIELD, t)); mdStream.add(gpsMetadata); t = "21.02.2013 23:19"; cout << "Adding metadata's item '" << GPS_METADATA_ITEM4 << "' with associated time " << t << endl; gpsMetadata = shared_ptr<Metadata>(new Metadata(gpsDesc)); gpsMetadata->push_back(FieldValue(GPS_COORD_FIELD, GPS_METADATA_ITEM4)); gpsMetadata->push_back(FieldValue(GPS_TIME_FIELD, t)); mdStream.add(gpsMetadata); cout << "Save metadata" << endl << endl; // Save metadata to video file and close metadata stream mdStream.save(); mdStream.close(); cout << "Loading metadata..." << endl; cout << "Opening file name '" << FILE_NAME << "'" << endl; // Open new metadata stream to load and print saved metadata MetadataStream loadStream; if (!loadStream.open(FILE_NAME, MetadataStream::ReadOnly)) { cerr << "Can't open file " << FILE_NAME << endl; exit(1); } cout << "Loading schema '" << GPS_SCHEMA_NAME << "'" << endl; if (!loadStream.load(GPS_SCHEMA_NAME)) { cerr << "Can't load schema " << GPS_SCHEMA_NAME << endl; exit(1); } // Select all metadata items from loaded schema auto dataSet = loadStream.queryBySchema(GPS_SCHEMA_NAME); // and print them to console for (size_t i = 0; i < dataSet.size(); i++) { cout << "Getting item " << i << endl; auto metadataItem = dataSet[i]; string coord = metadataItem->getFieldValue(GPS_COORD_FIELD); cout << "\tGPS coordinates are: " << coord << endl; string time = metadataItem->getFieldValue(GPS_TIME_FIELD); cout << "\tAssociated time is: " << time << endl; } // Close metadata stream loadStream.close(); // Uninitialize VMF library to free allocated resources vmf::terminate(); return 0; }
void XMPDataSource::saveXMPstructs() { std::shared_ptr<SXMPMeta> tmpXMP = xmp; //Sometimes compressed&encoded data is bigger than the source data //but there's no need to compare their sizes and write the smallest one. //Because due to RDF's verbosity it happens only when the source data is small. //That's why the economy wouldn't be significant. if(compressor) { string buffer; XMP_OptionBits options = kXMP_ReadOnlyPacket | kXMP_UseCompactFormat; tmpXMP->SerializeToBuffer(&buffer, options, 0, NULL); vmf_rawbuffer compressed; compressor->compress(buffer, compressed); string encoded; XMPUtils::EncodeToBase64 (compressed.data(), compressed.size(), &encoded); //save compressed data as VMF metadata with corresponding schema MetadataStream cStream; cStream.addSchema(schemaCompression); shared_ptr<Metadata> cMetadata; cMetadata = make_shared<Metadata>(schemaCompression->findMetadataDesc(COMPRESSED_DATA_DESC_NAME)); cMetadata->push_back(FieldValue(COMPRESSION_ALGO_PROP_NAME, compressor->getId())); cMetadata->push_back(FieldValue(COMPRESSED_DATA_PROP_NAME, encoded)); cStream.add(cMetadata); tmpXMP = make_shared<SXMPMeta>(); std::shared_ptr<XMPMetadataSource> cMetaSource; std::shared_ptr<XMPSchemaSource> cSchemaSource; cSchemaSource = make_shared<XMPSchemaSource>(tmpXMP); cMetaSource = make_shared<XMPMetadataSource>(tmpXMP); if (!cMetaSource || !cSchemaSource) { VMF_EXCEPTION(DataStorageException, "Failed to create compressed metadata source or schema source"); } try { cMetaSource->saveSchema(schemaCompression, cStream.getAll()); cSchemaSource->save(schemaCompression); } catch(const XMP_Error& e) { VMF_EXCEPTION(DataStorageException, e.GetErrMsg()); } catch(const std::exception& e) { VMF_EXCEPTION(DataStorageException, e.what()); } IdType cNextId = 1; tmpXMP->SetProperty_Int64(VMF_NS, VMF_GLOBAL_NEXT_ID, cNextId); } //existing encryptor should mean that we need an encryption if(encryptor) { string buffer; XMP_OptionBits options = kXMP_ReadOnlyPacket | kXMP_UseCompactFormat; tmpXMP->SerializeToBuffer(&buffer, options, 0, NULL); vmf_rawbuffer encrypted; encryptor->encrypt(buffer, encrypted); string encoded; XMPUtils::EncodeToBase64(encrypted.data(), encrypted.size(), &encoded); //save encrypted data as VMF metadata with corresponding schema MetadataStream eStream; eStream.addSchema(schemaEncryption); shared_ptr<Metadata> eMetadata; eMetadata = make_shared<Metadata>(schemaEncryption->findMetadataDesc(ENCRYPTED_DATA_DESC_NAME)); eMetadata->push_back(FieldValue(ENCRYPTION_HINT_PROP_NAME, encryptor->getHint())); eMetadata->push_back(FieldValue(ENCRYPTED_DATA_PROP_NAME, encoded)); eStream.add(eMetadata); tmpXMP = make_shared<SXMPMeta>(); std::shared_ptr<XMPMetadataSource> eMetaSource; std::shared_ptr<XMPSchemaSource> eSchemaSource; eSchemaSource = make_shared<XMPSchemaSource>(tmpXMP); eMetaSource = make_shared<XMPMetadataSource>(tmpXMP); if(!eMetaSource || !eSchemaSource) { VMF_EXCEPTION(DataStorageException, "Failed to create compressed metadata source or schema source"); } try { eMetaSource->saveSchema(schemaEncryption, eStream.getAll()); eSchemaSource->save(schemaEncryption); } catch(const XMP_Error& e) { VMF_EXCEPTION(DataStorageException, e.GetErrMsg()); } catch(const std::exception& e) { VMF_EXCEPTION(DataStorageException, e.what()); } IdType eNextId = 1; tmpXMP->SetProperty_Int64(VMF_NS, VMF_GLOBAL_NEXT_ID, eNextId); } if(xmpFile.CanPutXMP(*tmpXMP)) { xmpFile.PutXMP(*tmpXMP); } else { VMF_EXCEPTION(InternalErrorException, "Can't write XMP data to file"); } }
void XMPDataSource::loadXMPstructs() { std::shared_ptr<SXMPMeta> tmpXMP = make_shared<SXMPMeta>(); xmpFile.GetXMP(tmpXMP.get()); std::shared_ptr<XMPMetadataSource> tmpMetaSource; std::shared_ptr<XMPSchemaSource> tmpSchemaSource; std::shared_ptr<XMPStatSource> tmpStatSource; tmpSchemaSource = make_shared<XMPSchemaSource>(tmpXMP); tmpMetaSource = make_shared<XMPMetadataSource>(tmpXMP); tmpStatSource = make_shared<XMPStatSource>(tmpXMP); if(!tmpMetaSource || !tmpSchemaSource || !tmpStatSource) { VMF_EXCEPTION(DataStorageException, "Failed to create metadata source or schema source"); } //load standard VMF metadata and decompress them if there is a corresponding schema //or pass them further try { //load standard VMF metadata and decrypt them if there is a corresponding schema //or pass them further std::map<vmf_string, std::shared_ptr<MetadataSchema> > eSchemas; tmpSchemaSource->load(eSchemas); auto itEncryption = eSchemas.find(ENCRYPTED_DATA_SCHEMA_NAME); if(itEncryption != eSchemas.end()) { MetadataStream eStream; eStream.addSchema(itEncryption->second); tmpMetaSource->loadSchema(ENCRYPTED_DATA_SCHEMA_NAME, eStream); MetadataSet eSet = eStream.queryBySchema(ENCRYPTED_DATA_SCHEMA_NAME); std::shared_ptr<Metadata> eItem = eSet[0]; vmf_string hint = eItem->getFieldValue(ENCRYPTION_HINT_PROP_NAME); vmf_string encodedB64 = eItem->getFieldValue(ENCRYPTED_DATA_PROP_NAME); bool ignoreBad = (openMode & MetadataStream::OpenModeFlags::IgnoreUnknownEncryptor) != 0; if(!encryptor) { if(!ignoreBad) { VMF_EXCEPTION(IncorrectParamException, "No decryption algorithm provided for encrypted data"); } } else { string decodedFromB64; XMPUtils::DecodeFromBase64(encodedB64.data(), encodedB64.length(), &decodedFromB64); vmf_rawbuffer encrypted(decodedFromB64.c_str(), decodedFromB64.size()); string theData; try { encryptor->decrypt(encrypted, theData); } catch(Exception& ee) { //if we've failed with decryption (whatever the reason was) //and we're allowed to ignore that if(!ignoreBad) { string message = "Decryption failed: " + string(ee.what()) + ", hint: " + hint; VMF_EXCEPTION(IncorrectParamException, message); } } //replace tmp XMP entities tmpXMP->ParseFromBuffer(theData.c_str(), theData.size(), 0); tmpSchemaSource = make_shared<XMPSchemaSource>(tmpXMP); tmpMetaSource = make_shared<XMPMetadataSource>(tmpXMP); tmpStatSource = make_shared<XMPStatSource>(tmpXMP); if(!tmpMetaSource || !tmpSchemaSource || !tmpStatSource) { VMF_EXCEPTION(DataStorageException, "Failed to create metadata source, schema source or stat source"); } } } //load standard VMF metadata and decompress them if there is a corresponding schema //or pass them further std::map<vmf_string, std::shared_ptr<MetadataSchema> > cSchemas; tmpSchemaSource->load(cSchemas); auto itCompression = cSchemas.find(COMPRESSED_DATA_SCHEMA_NAME); if(itCompression != cSchemas.end()) { MetadataStream cStream; cStream.addSchema(itCompression->second); tmpMetaSource->loadSchema(COMPRESSED_DATA_SCHEMA_NAME, cStream); MetadataSet cSet = cStream.queryBySchema(COMPRESSED_DATA_SCHEMA_NAME); std::shared_ptr<Metadata> cItem = cSet[0]; vmf_string algo = cItem->getFieldValue(COMPRESSION_ALGO_PROP_NAME); vmf_string encoded = cItem->getFieldValue(COMPRESSED_DATA_PROP_NAME); bool ignoreBad = (openMode & MetadataStream::OpenModeFlags::IgnoreUnknownCompressor) != 0; try { std::shared_ptr<Compressor> decompressor = Compressor::create(algo); string decoded; XMPUtils::DecodeFromBase64(encoded.data(), encoded.length(), &decoded); vmf_rawbuffer compressed(decoded.c_str(), decoded.size()); string theData; decompressor->decompress(compressed, theData); //replace tmp XMP entities tmpXMP->ParseFromBuffer(theData.c_str(), theData.size(), 0); tmpSchemaSource = make_shared<XMPSchemaSource>(tmpXMP); tmpMetaSource = make_shared<XMPMetadataSource>(tmpXMP); tmpStatSource = make_shared<XMPStatSource>(tmpXMP); if(!tmpMetaSource || !tmpSchemaSource || !tmpStatSource) { VMF_EXCEPTION(DataStorageException, "Failed to create metadata source, schema source or stat source"); } } catch(IncorrectParamException& ce) { //if there's no such compressor and we're allowed to ignore that if(!ignoreBad) { VMF_EXCEPTION(IncorrectParamException, ce.what()); } } catch(InternalErrorException& ce) { //if there was an error during decompression if(!ignoreBad) { VMF_EXCEPTION(IncorrectParamException, ce.what()); } } } } catch(const XMP_Error& e) { VMF_EXCEPTION(DataStorageException, e.GetErrMsg()); } catch(const std::exception& e) { VMF_EXCEPTION(DataStorageException, e.what()); } xmp = tmpXMP; schemaSource = tmpSchemaSource; metadataSource = tmpMetaSource; statSource = tmpStatSource; }