From becc3d0953a2aa72c13c7ea979a3ce3cf638ae26 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Sat, 16 Apr 2022 19:52:52 +0200 Subject: [PATCH] Clone Source loading fixed and simplified Fixed loading order. Removed the option of origin selection for Clone: not meaningful anymore with chain of clones. --- CloneSource.cpp | 39 ++++------------- CloneSource.h | 11 ----- FrameBuffer.cpp | 12 +++++- ImGuiVisitor.cpp | 18 +++++--- InfoVisitor.cpp | 3 +- SessionCreator.cpp | 103 ++++++++++++++++++++++++--------------------- SessionVisitor.cpp | 1 - defines.h | 2 +- 8 files changed, 88 insertions(+), 101 deletions(-) diff --git a/CloneSource.cpp b/CloneSource.cpp index 5952269..d70659f 100644 --- a/CloneSource.cpp +++ b/CloneSource.cpp @@ -31,11 +31,9 @@ #include "CloneSource.h" -const char* CloneSource::cloning_provenance_label[2] = { "Original texture", "Post-processed image" }; - CloneSource::CloneSource(Source *origin, uint64_t id) : Source(id), origin_(origin), cloningsurface_(nullptr), - garbage_image_(nullptr), delay_(0.0), paused_(false), provenance_(CLONE_TEXTURE) + garbage_image_(nullptr), delay_(0.0), paused_(false) { // initial name copies the origin name: diplucates are namanged in session name_ = origin->name(); @@ -72,22 +70,9 @@ CloneSource::~CloneSource() g_free(timer_); } -CloneSource *CloneSource::clone(uint64_t id) -{ - // do not clone a clone : clone the original instead - if (origin_) - return origin_->clone(id); - else - return nullptr; -} - void CloneSource::init() { - if (origin_ && origin_->mode_ > Source::UNINITIALIZED) { - - // internal surface to draw the original texture - cloningsurface_ = new Surface; - cloningsurface_->setTextureIndex( origin()->texture() ); + if (origin_ && origin_->mode_ > Source::UNINITIALIZED && origin_->renderbuffer_) { // frame buffers where to draw frames from the origin source glm::vec3 res = origin_->frame()->resolution(); @@ -102,7 +87,7 @@ void CloneSource::init() texturesurface_->setTextureIndex( images_.front()->texture() ); // create render Frame buffer matching size of images - FrameBuffer *renderbuffer = new FrameBuffer( res, true); + FrameBuffer *renderbuffer = new FrameBuffer( res, true ); // set the renderbuffer of the source and attach rendering nodes attach(renderbuffer); @@ -149,7 +134,7 @@ void CloneSource::update(float dt) if (origin_) { - if (!paused_ && cloningsurface_ != nullptr) { + if (!paused_) { // if temporary FBO was pending to be deleted, delete it now if (garbage_image_ != nullptr) { @@ -192,15 +177,8 @@ void CloneSource::update(float dt) } } - // CLONE_RENDER : blit rendered framebuffer in the newest image (back) - if (provenance_ == CLONE_RENDER) - origin_->frame()->blit(images_.back()); - // CLONE_TEXTURE : render origin texture in the the newest image (back) - else { - images_.back()->begin(); - cloningsurface_->draw(glm::identity(), images_.back()->projection()); - images_.back()->end(); - } + // blit rendered framebuffer in the newest image (back) + origin_->frame()->blit(images_.back()); // update the source surface to be rendered with the oldest image (front) texturesurface_->setTextureIndex( images_.front()->texture() ); @@ -242,7 +220,6 @@ void CloneSource::replay() { // clear to_delete_ FBO if pending if (garbage_image_ != nullptr) { - g_printerr(" REPLAY delete garbage %d \n", garbage_image_->opengl_id()); delete garbage_image_; garbage_image_ = nullptr; } @@ -279,10 +256,10 @@ guint64 CloneSource::playtime () const uint CloneSource::texture() const { - if (cloningsurface_ != nullptr && !images_.empty()) + if (!images_.empty()) return images_.front()->texture(); else - return Resource::getTextureTransparent(); + return Resource::getTextureBlack(); } void CloneSource::accept(Visitor& v) diff --git a/CloneSource.h b/CloneSource.h index 137486c..b99b4d9 100644 --- a/CloneSource.h +++ b/CloneSource.h @@ -25,20 +25,10 @@ public: void accept (Visitor& v) override; // implementation of cloning mechanism - CloneSource *clone(uint64_t id = 0) override; inline void detach() { origin_ = nullptr; } inline Source *origin() const { return origin_; } // Clone properties - typedef enum { - CLONE_TEXTURE = 0, - CLONE_RENDER - } CloneSourceProvenance; - static const char* cloning_provenance_label[2]; - - void setCloningProvenance(CloneSourceProvenance m) { provenance_ = m; } - CloneSourceProvenance cloningProvenance() const { return provenance_; } - void setDelay(double second); double delay() const { return delay_; } @@ -65,7 +55,6 @@ protected: // control bool paused_; - CloneSourceProvenance provenance_; // connecting line class DotLine *connection_; diff --git a/FrameBuffer.cpp b/FrameBuffer.cpp index b086aec..9944211 100644 --- a/FrameBuffer.cpp +++ b/FrameBuffer.cpp @@ -270,8 +270,12 @@ void FrameBuffer::release() void FrameBuffer::readPixels(uint8_t *target_data) { - if (!framebufferid_) + if (!framebufferid_) { +#ifdef FRAMEBUFFER_DEBUG + g_printerr("FrameBuffer readPixels failed\n"); +#endif return; + } if (use_multi_sampling_) glBindFramebuffer(GL_READ_FRAMEBUFFER, intermediate_framebufferid_); @@ -289,8 +293,12 @@ void FrameBuffer::readPixels(uint8_t *target_data) bool FrameBuffer::blit(FrameBuffer *destination) { - if (!framebufferid_ || !destination || (use_alpha_ != destination->use_alpha_) ) + if (!framebufferid_ || !destination || (use_alpha_ != destination->use_alpha_) ){ +#ifdef FRAMEBUFFER_DEBUG + g_printerr("FrameBuffer blit failed\n"); +#endif return false; + } if (!destination->framebufferid_) destination->init(); diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 2e91d35..eed2ae3 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -763,20 +763,26 @@ void ImGuiVisitor::visit (CloneSource& s) UserInterface::manager().showSourceEditor(&s); ImGui::SetCursorPos(pos); - if ( ImGui::Button(s.origin()->name().c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) + std::string label = std::string(s.origin()->initials()) + " - " + s.origin()->name(); + if ( ImGui::Button(label.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) Mixer::manager().setCurrentSource(s.origin()); ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("Origin"); - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - int m = (int) s.cloningProvenance(); - if (ImGui::Combo("Render", &m, CloneSource::cloning_provenance_label, IM_ARRAYSIZE(CloneSource::cloning_provenance_label)) ) - s.setCloningProvenance((CloneSource::CloneSourceProvenance)m); - + if (ImGuiToolkit::IconButton(10, 15)) { + s.setDelay(0.f); + Action::manager().store("Delay None"); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); float d = s.delay(); if (ImGui::SliderFloat("Delay", &d, 0.f, 2.f, d < 0.01f ? "None" : "%.2f s")) s.setDelay(d); + if (ImGui::IsItemDeactivatedAfterEdit()) { + std::ostringstream oss; + oss << "Delay " << std::setprecision(3) << d << " s"; + Action::manager().store(oss.str()); + } } diff --git a/InfoVisitor.cpp b/InfoVisitor.cpp index faba430..b4fe5d7 100644 --- a/InfoVisitor.cpp +++ b/InfoVisitor.cpp @@ -235,8 +235,7 @@ void InfoVisitor::visit (CloneSource& s) } else { if (s.origin()) - oss << "Clone of '" << s.origin()->name() << "' "; - oss << CloneSource::cloning_provenance_label[s.cloningProvenance()] << std::endl; + oss << "Clone of '" << s.origin()->name() << "' " << std::endl; oss << (s.frame()->use_alpha() ? "RGBA, " : "RGB, "); oss << (int)(s.delay()*1000.0) << " ms delay " << std::endl; oss << s.frame()->width() << " x " << s.frame()->height(); diff --git a/SessionCreator.cpp b/SessionCreator.cpp index b61aca0..9d27398 100644 --- a/SessionCreator.cpp +++ b/SessionCreator.cpp @@ -375,6 +375,10 @@ void SessionLoader::load(XMLElement *sessionNode) sessionNode->QueryFloatAttribute("activationThreshold", &t); session_->setActivationThreshold(t); + + std::list cloneNodesToAdd; + std::list possible_xml_ids; + // // source lists // @@ -389,6 +393,7 @@ void SessionLoader::load(XMLElement *sessionNode) // check if a source with the given id exists in the session uint64_t id_xml_ = 0; xmlCurrent_->QueryUnsigned64Attribute("id", &id_xml_); + possible_xml_ids.push_front(id_xml_); SourceList::iterator sit = session_->find(id_xml_); // no source with this id exists @@ -427,7 +432,10 @@ void SessionLoader::load(XMLElement *sessionNode) else if ( std::string(pType) == "SrtReceiverSource") { load_source = new SrtReceiverSource(id_xml_); } - else if ( std::string(pType) != "CloneSource") { + else if ( std::string(pType) == "CloneSource") { + cloneNodesToAdd.push_front(xmlCurrent_); + } + else { Log::Info("Unknown source type '%s' ignored.", pType); } @@ -450,54 +458,60 @@ void SessionLoader::load(XMLElement *sessionNode) sources_id_[id_xml_] = load_source; } - // create clones after all sources, to be able to clone a source created above - sourceNode = sessionNode->FirstChildElement("Source"); - for( ; sourceNode ; sourceNode = sourceNode->NextSiblingElement()) - { - xmlCurrent_ = sourceNode; + // take all node elements for Clones to add + while ( !cloneNodesToAdd.empty() ) { - // verify type of node - const char *pType = xmlCurrent_->Attribute("type"); - if ( pType && std::string(pType) == "CloneSource") { + // take out Clone's XML element + xmlCurrent_ = cloneNodesToAdd.front(); + cloneNodesToAdd.pop_front(); - // check if a source with same id exists - uint64_t id_xml_ = 0; - xmlCurrent_->QueryUnsigned64Attribute("id", &id_xml_); - SourceList::iterator sit = session_->find(id_xml_); + // check if a clone source with same id exists + uint64_t id_xml_ = 0; + xmlCurrent_->QueryUnsigned64Attribute("id", &id_xml_); + SourceList::iterator sit = session_->find(id_xml_); - // no source clone with this id exists - if ( sit == session_->end() ) { + // no source clone with this id exists + if ( sit == session_->end() ) { - // clone from given origin - XMLElement* originNode = xmlCurrent_->FirstChildElement("origin"); - if (originNode) { - uint64_t id_origin_ = 0; - originNode->QueryUnsigned64Attribute("id", &id_origin_); - SourceList::iterator origin; - if (id_origin_ > 0) - origin = session_->find(id_origin_); - else { - const char *text = originNode->GetText(); - if (text) - origin = session_->find( std::string(text) ); - else - origin = session_->end(); - } - // found the orign source - if (origin != session_->end()) { - // create a new source of type Clone - CloneSource *clone_source = (*origin)->clone(id_xml_); + // try to get clone from given origin + XMLElement* originNode = xmlCurrent_->FirstChildElement("origin"); + if (originNode) { - // add source to session - session_->addSource(clone_source); + // find origin by id + uint64_t id_origin_ = 0; + originNode->QueryUnsigned64Attribute("id", &id_origin_); + SourceList::iterator origin; + if (id_origin_ > 0) + origin = session_->find(id_origin_); + // legacy: find origin by name + else { + const char *text = originNode->GetText(); + if (text) + origin = session_->find( std::string(text) ); + else + origin = session_->end(); + } - // apply config to source - clone_source->accept(*this); - clone_source->touch(); + // found the orign source! + if (origin != session_->end()) { + // create a new source of type Clone + CloneSource *clone_source = (*origin)->clone(id_xml_); - // remember - sources_id_[id_xml_] = clone_source; - } + // add clone source to session + session_->addSource(clone_source); + + // apply config to clone source + clone_source->accept(*this); + clone_source->touch(); + + // remember + sources_id_[id_xml_] = clone_source; + } + // origin not found, retry later + else { + // sanity check: only retry later if the id is possible. + if ( std::find(possible_xml_ids.begin(), possible_xml_ids.end(),id_origin_) != possible_xml_ids.end() ) + cloneNodesToAdd.push_back(xmlCurrent_); } } } @@ -1200,11 +1214,6 @@ void SessionLoader::visit (SrtReceiverSource& s) void SessionLoader::visit (CloneSource& s) { - // set attributes - int p = 0; - xmlCurrent_->QueryIntAttribute("provenance", &p); - s.setCloningProvenance((CloneSource::CloneSourceProvenance)p); - double d = 0.0; xmlCurrent_->QueryDoubleAttribute("delay", &d); s.setDelay(d); diff --git a/SessionVisitor.cpp b/SessionVisitor.cpp index 1d3de56..30013bc 100644 --- a/SessionVisitor.cpp +++ b/SessionVisitor.cpp @@ -687,7 +687,6 @@ void SessionVisitor::visit (CloneSource& s) xmlCurrent_->SetAttribute("type", "CloneSource"); if (s.origin()) { - xmlCurrent_->SetAttribute("provenance", (int) s.cloningProvenance()); xmlCurrent_->SetAttribute("delay", (double) s.delay()); XMLElement *origin = xmlDoc_->NewElement("origin"); diff --git a/defines.h b/defines.h index 887b680..60f15fa 100644 --- a/defines.h +++ b/defines.h @@ -5,7 +5,7 @@ #define APP_TITLE "Video Live Mixer" #define APP_SETTINGS "vimix.xml" #define XML_VERSION_MAJOR 0 -#define XML_VERSION_MINOR 2 +#define XML_VERSION_MINOR 3 #define MAX_RECENT_HISTORY 20 #define MAX_SESSION_LEVEL 3