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); } }
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::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; }