void MetadataDesc::validate() { if( m_sMetadataName.empty() ) { VMF_EXCEPTION(ValidateException, "Metadata name cannot be empty!" ); } // Check duplicate field names std::vector<std::string> vFieldNames; std::for_each( m_vFields.begin(), m_vFields.end(), [&]( FieldDesc field ) { vFieldNames.push_back( field.name ); }); std::sort( vFieldNames.begin(), vFieldNames.end() ); vFieldNames.erase( std::unique( vFieldNames.begin(), vFieldNames.end() ), vFieldNames.end() ); if( vFieldNames.size() < m_vFields.size() ) { VMF_EXCEPTION(ValidateException, "A structure cannot have duplicate field names!" ); } // Check single value case if( vFieldNames.empty() && vFieldNames.size() > 1 ) { VMF_EXCEPTION(ValidateException, "Anonymous field name cannot be used for metadata that has multiple fields!" ); } }
void MetadataStream::remove(const std::shared_ptr< MetadataSchema >& spSchema) { if( spSchema == nullptr ) { VMF_EXCEPTION(NullPointerException, "Metadata Schema is null." ); } std::string sSchemaName = spSchema->getName(); if( sSchemaName.empty() ) { VMF_EXCEPTION(IncorrectParamException, "Metadata Schema name cannot be empty!" ); } auto it = m_mapSchemas.find( sSchemaName ); if( it == m_mapSchemas.end()) { VMF_EXCEPTION(IncorrectParamException, "Metadata Schema doesn't exist!" ); } auto items = this->queryBySchema(sSchemaName); remove(items); auto removedItr = m_mapSchemas.find(sSchemaName); if (removedItr != m_mapSchemas.end()) m_mapSchemas.erase(removedItr); removedSchemas[sSchemaName] = spSchema; }
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 Metadata::setTimestamp(long long timestamp, long long duration) { if(timestamp < 0 && timestamp != UNDEFINED_TIMESTAMP) { VMF_EXCEPTION(IncorrectParamException, "Can't set metadata timestamp. Invalid timestamp value: " + to_string(timestamp)); } if(duration < 0) { VMF_EXCEPTION(IncorrectParamException, "Can't set metadata duration. Invalid duration value: " + to_string(duration)); } m_nTimestamp = timestamp; m_nDuration = duration; }
void Metadata::setFrameIndex( long long nFrameIndex, long long nNumOfFrames ) { if(nFrameIndex < 0 && nFrameIndex != UNDEFINED_FRAME_INDEX) { VMF_EXCEPTION(IncorrectParamException, "Can't set metadata frame index. Invalid frame index value: " + to_string(nFrameIndex)); } if(nNumOfFrames < 0) { VMF_EXCEPTION(IncorrectParamException, "Can't set metadata number of frames. Invalid number of frames value: " + to_string(nNumOfFrames)); } m_nFrameIndex = nFrameIndex; m_nNumOfFrames = nNumOfFrames; }
void MetadataStream::dataSourceCheck() { if (!dataSource) { VMF_EXCEPTION(InternalErrorException, "No files has been assosiated with this stream"); } }
void MetadataStream::VideoSegment::setResolution(long _width, long _height) { if(_width <= 0 || _height <= 0) VMF_EXCEPTION(IncorrectParamException, "Segment resoulution width and height must be positive"); width = _width; height = _height; }
MetadataSet Metadata::getReferencesByMetadata(const std::string& sMetadataName) const { MetadataSet mdSet; if (sMetadataName.empty()) { VMF_EXCEPTION(ValidateException, "MetadataName is empty!"); } else { std::for_each(m_vReferences.begin(), m_vReferences.end(), [&](const Reference& ref) { auto spMetadata = ref.getReferenceMetadata().lock(); if (spMetadata != nullptr) { if (spMetadata->getName() == sMetadataName) { mdSet.emplace_back(spMetadata); } } }); } return mdSet; }
void Initialize(std::shared_ptr<IDataSourceFactory> &dataSourceFactory) { if (!dataSourceFactory) { VMF_EXCEPTION(IncorrectParamException, "Unable to initialize by empty DataSourceFactory instance"); } ObjectFactory *instance = ObjectFactory::getInstance(); if (instance == NULL) { VMF_EXCEPTION(InternalErrorException, "Can't get Object factory instance"); } instance->setDataSourceFactory(dataSourceFactory); }
bool MetadataStream::open( const std::string& sFilePath, MetadataStream::OpenMode eMode ) { try { if (m_eMode != InMemory) return false; dataSource = ObjectFactory::getInstance()->getDataSource(); if (!dataSource) { VMF_EXCEPTION(InternalErrorException, "Failed to get datasource instance. Possible, call of vmf::initialize is missed"); } clear(); m_sFilePath = sFilePath; dataSource->openFile(m_sFilePath, eMode); dataSource->loadVideoSegments(videoSegments); dataSource->load(m_mapSchemas); m_eMode = eMode; m_sFilePath = sFilePath; nextId = dataSource->loadId(); m_sChecksumMedia = dataSource->loadChecksum(); return true; } catch(...) { return false; } }
IdType MetadataStream::add( std::shared_ptr< MetadataInternal >& spMetadataInternal) { if( !this->getSchema(spMetadataInternal->getDesc()->getSchemaName()) ) VMF_EXCEPTION(vmf::NotFoundException, "Metadata schema is not in the stream"); IdType id = spMetadataInternal->getId(); if(id != INVALID_ID) { if(this->getById(id) == nullptr) { if(nextId < id) nextId = id + 1; } else VMF_EXCEPTION(IncorrectParamException, "Metadata with such id is already in the stream"); } else { id = nextId++; spMetadataInternal->setId(id); } internalAdd(spMetadataInternal); addedIds.push_back(id); if(!spMetadataInternal->vRefs.empty()) { auto spItem = getById(id); for(auto ref = spMetadataInternal->vRefs.begin(); ref != spMetadataInternal->vRefs.end(); ref++) { auto referencedItem = getById(ref->first); if(referencedItem != nullptr) spItem->addReference(referencedItem, ref->second); else m_pendingReferences[ref->first].push_back(std::make_pair(id, ref->second)); } } auto pendingReferences = m_pendingReferences[id]; if(!pendingReferences.empty()) { for(auto pendingId = pendingReferences.begin(); pendingId != pendingReferences.end(); pendingId++) getById(pendingId->first)->addReference(spMetadataInternal, pendingId->second); m_pendingReferences[id].clear(); m_pendingReferences.erase(id); } return id; }
vmf::Variant Metadata::getFieldValue( const std::string& sName ) const { const_iterator it = const_cast<vmf::Metadata*>(this)->findField( sName ); if( it != this->end() ) return *it; FieldDesc fieldDesc; if( !m_spDesc->getFieldDesc( fieldDesc, sName ) ) { VMF_EXCEPTION(IncorrectParamException, "Metadata field not found in metadata description" ); } if(fieldDesc.optional) return vmf::Variant(); VMF_EXCEPTION(IncorrectParamException, "Field not found!"); }
MetadataSchema::MetadataSchema( const std::string& sName, const std::string& sAuthor ) : m_sName(sName), m_sAuthor(sAuthor) { if (sName.empty()) { VMF_EXCEPTION(IncorrectParamException, "Schema name can't be empty."); } }
void MetadataSchema::add( std::shared_ptr< MetadataDesc >& spDesc ) { if( spDesc == nullptr ) { VMF_EXCEPTION(NullPointerException, "Description pointer is empty!" ); } if( this->findMetadataDesc( spDesc->getMetadataName() ) != nullptr ) { VMF_EXCEPTION(IncorrectParamException, "Metadata with same name already exists!" ); } spDesc->validate(); spDesc->setSchemaName( this->m_sName ); this->push_back( spDesc ); }
MetadataStream::VideoSegment::VideoSegment( const std::string& _title, double _fps, long long _timeStart, long long _duration, long _width, long _height ) : title(_title), fps(_fps), timeStart(_timeStart), duration(_duration), width(_width), height(_height) { if (_title.empty()) VMF_EXCEPTION(IncorrectParamException, "Segment title can't be empty"); if (_fps <= 0) VMF_EXCEPTION(IncorrectParamException, "Segment fps must be positive"); if (_timeStart < 0) VMF_EXCEPTION(IncorrectParamException, "Segment start time must be positive"); if (_duration < 0) VMF_EXCEPTION(IncorrectParamException, "Segment duration must be positive"); if (_width < 0 || _height < 0) VMF_EXCEPTION(IncorrectParamException, "Segment resoulution width and height must be positive"); }
void Metadata::setFieldValue( const std::string& sFieldName, const vmf::Variant& value ) { // Check field against description if( m_spDesc == nullptr ) { VMF_EXCEPTION(NullPointerException, "Metadata description object is missing!" ); } FieldDesc fieldDesc; if( !m_spDesc->getFieldDesc( fieldDesc, sFieldName ) ) { VMF_EXCEPTION(IncorrectParamException, "Metadata field not found in metadata description" ); } iterator it = this->findField( sFieldName ); // Check field type if( fieldDesc.type == value.getType() ) { if( it != this->end() ) { *it = vmf::FieldValue( sFieldName, value ); } else { this->emplace_back(sFieldName, value); } } // If the field type is not the same, try to convert it to the right type else { vmf::Variant varNew( value ); // This line may throw exception varNew.convertTo( fieldDesc.type ); if( it != this->end() ) { *it = vmf::FieldValue( sFieldName, varNew ); } else { this->emplace_back( FieldValue( sFieldName, varNew ) ); } } }
void MetadataStream::addVideoSegment(const std::shared_ptr<VideoSegment>& newSegment) { if (!newSegment) VMF_EXCEPTION(NullPointerException, "Pointer to new segment is NULL"); if (newSegment->getTitle().empty()) VMF_EXCEPTION(IncorrectParamException, "Segment contains empty 'title' value"); if (newSegment->getDuration() < 0) VMF_EXCEPTION(IncorrectParamException, "Segment contains invalid 'duration' value"); if (newSegment->getTime() < 0) VMF_EXCEPTION(IncorrectParamException, "Segment contains invalid 'timeStart' value"); if (newSegment->getFPS() <= 0) VMF_EXCEPTION(IncorrectParamException, "Segment contains invalid 'FPS' value"); long height = 0, width = 0; newSegment->getResolution(height, width); if ((height < 0) || (width < 0)) VMF_EXCEPTION(IncorrectParamException, "Segment contains invalid resolution"); std::for_each(videoSegments.begin(), videoSegments.end(), [&](const std::shared_ptr<VideoSegment>& segment) { long long newTime = newSegment->getTime(), segmentTime = segment->getTime(); if (((segmentTime <= newTime) && ((segmentTime + segment->getDuration() - 1) >= newTime)) || ((newTime <= segmentTime) && ((newTime + newSegment->getDuration() - 1) >= segmentTime))) VMF_EXCEPTION(IncorrectParamException, "Input segment intersects a one of the already created segments"); }); videoSegments.push_back(newSegment); }
bool Metadata::operator < ( const Metadata& oMetadata ) const { if( this->m_Id == INVALID_ID && oMetadata.m_Id == INVALID_ID ) { VMF_EXCEPTION(IncorrectParamException, "Cannot compare metadata that has not been added to any stream!" ); } return m_Id < oMetadata.m_Id; }
bool MetadataStream::reopen( OpenMode eMode ) { dataSourceCheck(); if( m_eMode != InMemory ) VMF_EXCEPTION(vmf::IncorrectParamException, "The previous file has not been closed!"); if( m_sFilePath.empty()) VMF_EXCEPTION(vmf::IncorrectParamException, "The file path is emtpy!"); try { dataSource->openFile(m_sFilePath, eMode); m_eMode = eMode; return true; } catch(...) { // do nothing } return false; }
IdType MetadataStream::add( std::shared_ptr< Metadata >& spMetadata ) { if( !this->getSchema(spMetadata->getDesc()->getSchemaName()) ) VMF_EXCEPTION(vmf::NotFoundException, "Metadata schema is not in the stream"); IdType id = nextId++; spMetadata->setId(id); internalAdd(spMetadata); addedIds.push_back(id); return id; }
MetadataDesc::MetadataDesc( const std::string& sMetadataName, Variant::Type type ) : m_sMetadataName( sMetadataName ) { if (type == Variant::type_unknown) { VMF_EXCEPTION(IncorrectParamException, "Invalid metadata descriprion type."); } m_vFields.emplace_back( FieldDesc( "", type ) ); m_vRefDesc.emplace_back(std::make_shared<ReferenceDesc>("", false)); }
void MetadataDesc::declareCustomReference(const std::string& refName, bool isUnique) { for (auto it = m_vRefDesc.begin(); it != m_vRefDesc.end(); it++) { if ((*it)->name == refName) VMF_EXCEPTION(ValidateException, "This reference name already exist!"); } m_vRefDesc.emplace_back(std::make_shared<ReferenceDesc>(refName, isUnique, true)); return; }
void Uninitialize() { ObjectFactory *instance = ObjectFactory::getInstance(); if (instance == NULL) { VMF_EXCEPTION(InternalErrorException, "Can't get Object factory instance"); } std::shared_ptr<IDataSourceFactory> emptyDataSourceFactoryPtr; instance->setDataSourceFactory(emptyDataSourceFactoryPtr); }
void MetadataStream::addSchema( std::shared_ptr< MetadataSchema >& spSchema ) { if( spSchema == nullptr ) { VMF_EXCEPTION(NullPointerException, "Metadata Schema is null." ); } std::string sSchemaName = spSchema->getName(); if( sSchemaName.empty() ) { VMF_EXCEPTION(IncorrectParamException, "Metadata Schema name cannot be empty!" ); } auto it = m_mapSchemas.find( sSchemaName ); if( it != m_mapSchemas.end()) { VMF_EXCEPTION(IncorrectParamException, "Metadata Schema already exists!" ); } m_mapSchemas[ sSchemaName ] = spSchema; }
vmf_rawbuffer(const char* _data, const size_t& _size) : size(_size) { if(_data && _size > 0) { data = std::unique_ptr<char[]>(new char[size]); memcpy(data.get(), _data, _size); } else if(!_data && _size == 0) data = nullptr; else VMF_EXCEPTION(IncorrectParamException, "Raw buffer object can't be created. Empty data or invalid size."); }
void Metadata::addValue( const vmf::Variant& value ) { // Check field against description if( m_spDesc == nullptr ) { VMF_EXCEPTION(NullPointerException, "Metadata description object is missing!" ); } FieldDesc fieldDesc; if( !m_spDesc->getFieldDesc( fieldDesc ) ) { VMF_EXCEPTION(InternalErrorException, "Metadata field not found in metadata description" ); } // Check field type if( fieldDesc.type != value.getType() ) { VMF_EXCEPTION(TypeCastException, "Field type does not match!" ); } this->emplace_back( FieldValue( "", value ) ); }
void MetadataStream::internalAdd(const std::shared_ptr<Metadata>& spMetadata) { spMetadata->validate(); spMetadata->setStreamRef(this); // Make sure all referenced metadata are from the same stream auto vRefSet = spMetadata->getAllReferences(); std::for_each( vRefSet.begin(), vRefSet.end(), [&]( Reference& spRef ) { if(spRef.getReferenceMetadata().lock()->m_pStream != this) { VMF_EXCEPTION(IncorrectParamException, "Referenced metadata is from different metadata stream."); } }); m_oMetadataSet.push_back(spMetadata); }
bool MetadataStream::import( MetadataStream& srcStream, MetadataSet& srcSet, long long nTarFrameIndex, long long nSrcFrameIndex, long long nNumOfFrames, MetadataSet* pSetFailure ) { // Find all schemes used by the source metadata set std::vector< std::string > vSchemaNames; std::for_each( srcSet.begin(), srcSet.end(), [&vSchemaNames]( std::shared_ptr<Metadata>& spMetadata ) { vSchemaNames.push_back( spMetadata->getSchemaName() ); }); // Remove redundant schema names std::sort( vSchemaNames.begin(), vSchemaNames.end() ); vSchemaNames.erase( std::unique( vSchemaNames.begin(), vSchemaNames.end() ), vSchemaNames.end()); // Import all schemes used std::for_each( vSchemaNames.begin(), vSchemaNames.end(), [&]( std::string& sAppName ) { if( this->getSchema( sAppName ) == nullptr ) { auto it = srcStream.m_mapSchemas.find( sAppName ); if( it != srcStream.m_mapSchemas.end()) this->addSchema( it->second ); else { VMF_EXCEPTION(InternalErrorException, "Metadata schema missing in the source stream!" ); } } }); // This map stores Id pairs<old, new> from the srcSet and this set. std::map< IdType, IdType > mapIds; // Import metadata one by one. std::for_each( srcSet.begin(), srcSet.end(), [&]( std::shared_ptr<Metadata>& spMetadata ) { if( import( srcStream, spMetadata, mapIds, nTarFrameIndex, nSrcFrameIndex, nNumOfFrames ) == nullptr && pSetFailure != NULL ) { pSetFailure->push_back( spMetadata ); } }); return mapIds.size() > 0; }
Metadata::Metadata(const std::shared_ptr< MetadataDesc >& spDescription , bool useEncryption) : m_Id( INVALID_ID ) , m_nFrameIndex(UNDEFINED_FRAME_INDEX) , m_nNumOfFrames(UNDEFINED_FRAMES_NUMBER) , m_nTimestamp(UNDEFINED_TIMESTAMP) , m_nDuration(UNDEFINED_DURATION) , m_sName( "" ) , m_sSchemaName( "" ) , m_useEncryption(useEncryption) , m_encryptedData("") , m_spDesc( spDescription ) , m_pStream(nullptr) { if (!m_spDesc) { VMF_EXCEPTION(NullPointerException, "Metadata description is null."); } m_sName = m_spDesc->getMetadataName(); m_sSchemaName = m_spDesc->getSchemaName(); }
static std::shared_ptr<MetadataStream::VideoSegment> parseVideoSegmentFromNode(JSONNode& segmentNode) { auto segmentTitleIter = segmentNode.find(ATTR_SEGMENT_TITLE); auto segmentFPSIter = segmentNode.find(ATTR_SEGMENT_FPS); auto segmentTimeIter = segmentNode.find(ATTR_SEGMENT_TIME); auto segmentDurationIter = segmentNode.find(ATTR_SEGMENT_DURATION); auto segmentWidthIter = segmentNode.find(ATTR_SEGMENT_WIDTH); auto segmentHeightIter = segmentNode.find(ATTR_SEGMENT_HEIGHT); if(segmentTitleIter == segmentNode.end()) VMF_EXCEPTION(vmf::InternalErrorException, "JSON element has no title"); if(segmentFPSIter == segmentNode.end()) VMF_EXCEPTION(vmf::InternalErrorException, "JSON element has no fps value"); if(segmentTimeIter == segmentNode.end()) VMF_EXCEPTION(vmf::InternalErrorException, "JSON element has no time value"); std::string title = segmentTitleIter->as_string(); double fps = segmentFPSIter->as_float(); long long timestamp = segmentTimeIter->as_int(); if(title.empty()) VMF_EXCEPTION(vmf::InternalErrorException, "JSON element has invalid title"); if(fps <= 0) VMF_EXCEPTION(vmf::InternalErrorException, "JSON element has invalid fps value"); if(timestamp < 0) VMF_EXCEPTION(vmf::InternalErrorException, "JSON element has invalid time value"); std::shared_ptr<MetadataStream::VideoSegment> spSegment(new MetadataStream::VideoSegment(title, fps, timestamp)); if(segmentDurationIter != segmentNode.end()) { long long duration = segmentDurationIter->as_int(); if(duration > 0) spSegment->setDuration(duration); } if(segmentWidthIter != segmentNode.end() && segmentHeightIter != segmentNode.end()) { long width = segmentWidthIter->as_int(), height = segmentHeightIter->as_int(); if(width > 0 && height > 0) spSegment->setResolution(width, height); } return spSegment; }