// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #include "mutableprojectdefinition.hpp" #include "libvideostitch-base/logmanager.hpp" #include "libvideostitch/inputFactory.hpp" #include "libvideostitch/logging.hpp" #include "libvideostitch/parse.hpp" #include "version.hpp" MutableProjectDefinition::MutableProjectDefinition(VideoStitch::Core::PanoDefinition* pano, VideoStitch::Core::AudioPipeDefinition* audioPipe, VideoStitch::Core::StereoRigDefinition* rig, int bufferFrames, VideoStitch::Core::ImageMergerFactory* mergerFactory, VideoStitch::Core::ImageWarperFactory* warperFactory, VideoStitch::Core::ImageFlowFactory* flowFactory, QString libVersion) : pano(pano), audioPipe(audioPipe), rig(rig), bufferFrames(bufferFrames), mergerFactory(mergerFactory), flowFactory(flowFactory), warperFactory(warperFactory), libVersion(libVersion) {} MutableProjectDefinition::MutableProjectDefinition(const MutableProjectDefinition& that) : pano(that.pano->clone()), audioPipe(that.audioPipe ? that.audioPipe->clone() : nullptr), rig(that.rig ? that.rig->clone() : nullptr), bufferFrames(that.bufferFrames), mergerFactory(that.mergerFactory->clone()), flowFactory(that.flowFactory->clone()), warperFactory(that.warperFactory->clone()), libVersion(that.libVersion) {} MutableProjectDefinition::~MutableProjectDefinition() { delete pano; delete audioPipe; delete rig; delete mergerFactory; delete warperFactory; delete flowFactory; } bool MutableProjectDefinition::hasFileFormatChanged() const { if (libVersion.isEmpty()) { return true; } QString newLibVersion = LIB_VIDEOSTITCH_VERSION; QString simplifiedNewVersion = newLibVersion.left(newLibVersion.indexOf("-")); QString simplifiedVersion = libVersion.left(libVersion.indexOf("-")); return QString::compare(simplifiedVersion, simplifiedNewVersion) < 0; } void MutableProjectDefinition::updateFileFormat() { libVersion = LIB_VIDEOSTITCH_VERSION; } MutableProjectDefinition* MutableProjectDefinition::create(const VideoStitch::Ptv::Value& value) { // Make sure value is an object. if (!VideoStitch::Parse::checkType("ProjectDefinition", value, VideoStitch::Ptv::Value::OBJECT)) { return nullptr; } std::string versionStr; VideoStitch::Parse::populateString("ProjectDefinition", value, "lib_version", versionStr, false); int bufferFrames = 1; if (VideoStitch::Parse::populateInt("ProjectDefinition", value, "buffer_frames", bufferFrames, false) == VideoStitch::Parse::PopulateResult_WrongType) { return nullptr; } const VideoStitch::Ptv::Value* tmp = value.has("merger"); if (!tmp) { VideoStitch::Logger::get(VideoStitch::Logger::Warning) << "Missing field 'merger' for BaseProjectDefinition." << std::endl; return nullptr; } VideoStitch::Potential mergerFactory = VideoStitch::Core::ImageMergerFactory::createMergerFactory(*tmp); // TODOLATERSTATUS: propagate and display failure if (!mergerFactory.ok()) { return nullptr; } tmp = value.has("warper"); VideoStitch::Potential warperFactory = VideoStitch::Core::ImageWarperFactory::createWarperFactory(tmp); if (!warperFactory.ok()) { return nullptr; } tmp = value.has("flow"); VideoStitch::Potential flowFactory = VideoStitch::Core::ImageFlowFactory::createFlowFactory(tmp); if (!flowFactory.ok()) { return nullptr; } tmp = value.has("pano"); if (!tmp) { VideoStitch::Logger::get(VideoStitch::Logger::Warning) << "Missing field 'pano' for BaseProjectDefinition." << std::endl; return nullptr; } VideoStitch::Core::PanoDefinition* pano = VideoStitch::Core::PanoDefinition::create(*tmp); if (!pano) { VideoStitch::Logger::get(VideoStitch::Logger::Error) << "Error: failed to create pano definition" << std::endl; return nullptr; } // probe inputs std::unique_ptr factory( new VideoStitch::Input::DefaultReaderFactory(0, NO_LAST_FRAME)); std::unique_ptr val(VideoStitch::Ptv::Value::emptyObject()); for (int inputId = 0; inputId < pano->numInputs(); ++inputId) { VideoStitch::Core::InputDefinition& input = pano->getInput(inputId); val->asString() = pano->getInput(inputId).getReaderConfig().asString(); VideoStitch::Input::ProbeResult result = factory->probe(*val); if (result.valid) { input.setIsAudioEnabled(result.hasAudio); input.setIsVideoEnabled(result.hasVideo); } } tmp = value.has("rig"); VideoStitch::Core::StereoRigDefinition* rig = nullptr; if (!tmp) { VideoStitch::Logger::get(VideoStitch::Logger::Warning) << "Missing field 'rig' for BaseProjectDefinition." << std::endl; } else { rig = VideoStitch::Core::StereoRigDefinition::create(*tmp); if (!rig) { return nullptr; } } VideoStitch::Core::AudioPipeDefinition* audioPipe = nullptr; tmp = value.has("audio_pipe"); if (tmp && pano->numAudioInputs() > 0) { audioPipe = VideoStitch::Core::AudioPipeDefinition::create(*tmp); if (audioPipe->numAudioInputs() != pano->numAudioInputs() || audioPipe->numAudioMixes() == 0 || !audioPipe->readersAreConsistent(pano)) { delete audioPipe; audioPipe = VideoStitch::Core::AudioPipeDefinition::createAudioPipeFromPanoInputs(pano); } } else if (pano->numAudioInputs() > 0) { audioPipe = VideoStitch::Core::AudioPipeDefinition::createAudioPipeFromPanoInputs(pano); } else { audioPipe = VideoStitch::Core::AudioPipeDefinition::createDefault(); } audioPipe->setSamplingRate(48000); return new MutableProjectDefinition(pano, audioPipe, rig, bufferFrames, mergerFactory.release(), warperFactory.release(), flowFactory.release(), QString::fromStdString(versionStr)); } VideoStitch::Ptv::Value* MutableProjectDefinition::serialize() const { VideoStitch::Ptv::Value* root = VideoStitch::Ptv::Value::emptyObject(); root->get("lib_version")->asString() = LIB_VIDEOSTITCH_VERSION; root->get("buffer_frames")->asInt() = bufferFrames; if (mergerFactory != nullptr) { delete root->push("merger", mergerFactory->serialize()); } if (warperFactory != nullptr) { delete root->push("warper", warperFactory->serialize()); } if (flowFactory != nullptr) { delete root->push("flow", flowFactory->serialize()); } if (pano != nullptr) { delete root->push("pano", pano->serialize()); } if (rig != nullptr) { delete root->push("rig", rig->serialize()); } if (audioPipe != nullptr && audioPipe->numAudioInputs() > 0) { delete root->push("audio_pipe", audioPipe->serialize()); } return root; } void MutableProjectDefinition::setAudioPipe(VideoStitch::Core::AudioPipeDefinition* audioPipeDefinition) { delete audioPipe; audioPipe = audioPipeDefinition; } void MutableProjectDefinition::setPano(VideoStitch::Core::PanoDefinition* panoDefinition) { delete pano; pano = panoDefinition; } void MutableProjectDefinition::setRig(VideoStitch::Core::StereoRigDefinition* rigDefinition) { delete rig; rig = rigDefinition; } void MutableProjectDefinition::setMergerFactory(VideoStitch::Core::ImageMergerFactory* merger) { delete mergerFactory; mergerFactory = merger; } void MutableProjectDefinition::setWarperFactory(VideoStitch::Core::ImageWarperFactory* warper) { delete warperFactory; warperFactory = warper; } void MutableProjectDefinition::setFlowFactory(VideoStitch::Core::ImageFlowFactory* flow) { delete flowFactory; flowFactory = flow; }