From 7109b94484f3571111af2f476760a73662aea12e Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Fri, 25 Sep 2020 21:20:24 +0200 Subject: [PATCH] Cleanup DeviceSource and PatternSource (no feature change) --- DeviceSource.cpp | 125 +++++++++++++++++++++++++++------------------ DeviceSource.h | 101 +++++++++++++++++++----------------- ImGuiVisitor.cpp | 2 +- Mixer.cpp | 4 +- PatternSource.cpp | 18 +++---- PatternSource.h | 8 +-- SessionCreator.cpp | 20 ++++---- 7 files changed, 153 insertions(+), 125 deletions(-) diff --git a/DeviceSource.cpp b/DeviceSource.cpp index 02d11ad..3c25243 100644 --- a/DeviceSource.cpp +++ b/DeviceSource.cpp @@ -29,17 +29,20 @@ Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer us case GST_MESSAGE_DEVICE_ADDED: { gst_message_parse_device_added (message, &device); name = gst_device_get_display_name (device); - manager().names_.push_back(name); + manager().src_name_.push_back(name); g_free (name); std::ostringstream pipe; pipe << gst_structure_get_string(gst_device_get_properties(device), "device.api"); pipe << "src name=devsrc device="; pipe << gst_structure_get_string(gst_device_get_properties(device), "device.path"); - manager().pipelines_.push_back(pipe.str()); + manager().src_description_.push_back(pipe.str()); - stru = gst_structure_to_string( gst_device_get_properties(device) ); - g_print("New device %s \n", stru); + DeviceConfigSet confs = getDeviceConfigs(pipe.str()); + manager().src_config_.push_back(confs); + +// stru = gst_structure_to_string( gst_device_get_properties(device) ); +// g_print("New device %s \n", stru); gst_object_unref (device); } @@ -48,7 +51,7 @@ Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer us gst_message_parse_device_removed (message, &device); name = gst_device_get_display_name (device); manager().remove(name); - g_print("Device removed: %s\n", name); +// g_print("Device removed: %s\n", name); g_free (name); gst_object_unref (device); @@ -63,19 +66,22 @@ Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer us void Device::remove(const char *device) { - std::vector< std::string >::iterator nameit = names_.begin(); - std::vector< std::string >::iterator pipeit = pipelines_.begin(); - while (nameit != names_.end()){ + std::vector< std::string >::iterator nameit = src_name_.begin(); + std::vector< std::string >::iterator descit = src_description_.begin(); + std::vector< DeviceConfigSet >::iterator coit = src_config_.begin(); + while (nameit != src_name_.end()){ if ( (*nameit).compare(device) == 0 ) { - names_.erase(nameit); - pipelines_.erase(pipeit); + src_name_.erase(nameit); + src_description_.erase(descit); + src_config_.erase(coit); break; } nameit++; - pipeit++; + descit++; + coit++; } } @@ -107,15 +113,17 @@ Device::Device() GstDevice *device = (GstDevice *) tmp->data; gchar *name = gst_device_get_display_name (device); - names_.push_back(name); + src_name_.push_back(name); g_free (name); std::ostringstream pipe; pipe << gst_structure_get_string(gst_device_get_properties(device), "device.api"); pipe << "src name=devsrc device="; pipe << gst_structure_get_string(gst_device_get_properties(device), "device.path"); - pipelines_.push_back(pipe.str()); + src_description_.push_back(pipe.str()); + DeviceConfigSet confs = getDeviceConfigs(pipe.str()); + src_config_.push_back(confs); } g_list_free(devices); @@ -124,41 +132,47 @@ Device::Device() int Device::numDevices() const { - return names_.size(); + return src_name_.size(); } bool Device::exists(const std::string &device) const { - std::vector< std::string >::const_iterator d = std::find(names_.begin(), names_.end(), device); - return d != names_.end(); + std::vector< std::string >::const_iterator d = std::find(src_name_.begin(), src_name_.end(), device); + return d != src_name_.end(); } std::string Device::name(int index) const { - if (index > -1 && index < names_.size()) - return names_[index]; + if (index > -1 && index < src_name_.size()) + return src_name_[index]; else return ""; } -std::string Device::pipeline(int index) const +std::string Device::description(int index) const { - if (index > -1 && index < pipelines_.size()) - return pipelines_[index]; + if (index > -1 && index < src_description_.size()) + return src_description_[index]; else return ""; } -std::string Device::pipeline(const std::string &device) const +DeviceConfigSet Device::config(int index) const { - std::string pip = ""; - std::vector< std::string >::const_iterator p = std::find(names_.begin(), names_.end(), device); - if (p != names_.end()) - { - int index = std::distance(names_.begin(), p); - pip = pipelines_[index]; - } - return pip; + if (index > -1 && index < src_config_.size()) + return src_config_[index]; + else + return DeviceConfigSet(); +} + +int Device::index(const std::string &device) const +{ + int i = -1; + std::vector< std::string >::const_iterator p = std::find(src_name_.begin(), src_name_.end(), device); + if (p != src_name_.end()) + i = std::distance(src_name_.begin(), p); + + return i; } @@ -187,28 +201,35 @@ void DeviceSource::setDevice(const std::string &devicename) device_ = devicename; Log::Notify("Creating Source with device '%s'", device_.c_str()); - std::ostringstream pipeline; - pipeline << Device::manager().pipeline(device_); + int index = Device::manager().index(device_); + if (index > -1) { - DeviceInfoSet confs = getDeviceConfigs(pipeline.str()); - DeviceInfoSet::reverse_iterator best = confs.rbegin(); + // start filling in the gstreamer pipeline + std::ostringstream pipeline; + pipeline << Device::manager().description(index); - pipeline << " ! " << (*best).format; - pipeline << ",framerate=" << (*best).fps_numerator << "/" << (*best).fps_denominator; - pipeline << ",width=" << (*best).width; - pipeline << ",height=" << (*best).height; + // test the device and get config + DeviceConfigSet confs = Device::manager().config(index); + // for( DeviceInfoSet::iterator it = confs.begin(); it != confs.end(); it++ ){ + // Log::Info("config possible : %s %dx%d @ %d fps", (*it).format.c_str(), (*it).width, (*it).height, (*it).fps_numerator); + // } + DeviceConfigSet::reverse_iterator best = confs.rbegin(); - if ( (*best).format.find("jpeg") != std::string::npos ) - pipeline << " ! jpegdec"; + pipeline << " ! " << (*best).format; + pipeline << ",framerate=" << (*best).fps_numerator << "/" << (*best).fps_denominator; + pipeline << ",width=" << (*best).width; + pipeline << ",height=" << (*best).height; -// for( DeviceInfoSet::iterator it = confs.begin(); it != confs.end(); it++ ){ -// Log::Info("config possible : %s %dx%d @ %d fps", (*it).format.c_str(), (*it).width, (*it).height, (*it).fps_numerator); -// } + if ( (*best).format.find("jpeg") != std::string::npos ) + pipeline << " ! jpegdec"; - pipeline << " ! videoconvert"; + pipeline << " ! videoconvert"; - stream_->open( pipeline.str(), (*best).width, (*best).height); - stream_->play(true); + stream_->open( pipeline.str(), (*best).width, (*best).height); + stream_->play(true); + } + else + Log::Warning("No such device '%s'", device_.c_str()); } void DeviceSource::accept(Visitor& v) @@ -223,12 +244,12 @@ bool DeviceSource::failed() const } -DeviceInfoSet DeviceSource::getDeviceConfigs(const std::string &pipeline) +DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description) { - DeviceInfoSet configs; + DeviceConfigSet configs; // create dummy pipeline to be tested - std::string description = pipeline; + std::string description = src_description; description += " ! fakesink name=sink"; // parse pipeline descriptor @@ -261,7 +282,7 @@ DeviceInfoSet DeviceSource::getDeviceConfigs(const std::string &pipeline) int C = gst_caps_get_size(device_caps); for (int c = 0; c < C; ++c) { GstStructure *decice_cap_struct = gst_caps_get_structure (device_caps, c); - DeviceInfo config; + DeviceConfig config; // NAME : typically video/x-raw or image/jpeg config.format = gst_structure_get_name (decice_cap_struct); @@ -299,6 +320,8 @@ DeviceInfoSet DeviceSource::getDeviceConfigs(const std::string &pipeline) } } } + + // WIDTH and HEIGHT if ( gst_structure_has_field (decice_cap_struct, "width")) gst_structure_get_int (decice_cap_struct, "width", &config.width); if ( gst_structure_has_field (decice_cap_struct, "height")) @@ -307,6 +330,8 @@ DeviceInfoSet DeviceSource::getDeviceConfigs(const std::string &pipeline) // gchar *capstext = gst_structure_to_string (decice_cap_struct); // Log::Info("DeviceSource found cap struct %s", capstext); // g_free(capstext); + + // add this config configs.insert(config); } diff --git a/DeviceSource.h b/DeviceSource.h index 6b55073..3487a3d 100644 --- a/DeviceSource.h +++ b/DeviceSource.h @@ -7,6 +7,50 @@ #include "GstToolkit.h" #include "StreamSource.h" +struct DeviceConfig { + gint width; + gint height; + gint fps_numerator; + gint fps_denominator; + std::string format; + + DeviceConfig() { + width = 0; + height = 0; + fps_numerator = 1; + fps_denominator = 1; + format = ""; + } + + inline DeviceConfig& operator = (const DeviceConfig& b) + { + if (this != &b) { + this->width = b.width; + this->height = b.height; + this->fps_numerator = b.fps_numerator; + this->fps_denominator = b.fps_denominator; + this->format = b.format; + } + return *this; + } + + inline bool operator < (const DeviceConfig b) const + { + return ( this->fps_numerator * this->height < b.fps_numerator * b.height ); + } +}; + +struct better_device_comparator +{ + inline bool operator () (const DeviceConfig a, const DeviceConfig b) const + { + return (a < b); + } +}; + +typedef std::set DeviceConfigSet; + + class Device { Device(); @@ -24,65 +68,27 @@ public: int numDevices () const; std::string name (int index) const; - std::string pipeline (int index) const; + std::string description (int index) const; + DeviceConfigSet config (int index) const; bool exists (const std::string &device) const; - std::string pipeline (const std::string &device) const; + int index (const std::string &device) const; static gboolean callback_device_monitor (GstBus *, GstMessage *, gpointer); private: void remove(const char *device); - std::vector< std::string > names_; - std::vector< std::string > pipelines_; + std::vector< std::string > src_name_; + std::vector< std::string > src_description_; + + std::vector< DeviceConfigSet > src_config_; + static DeviceConfigSet getDeviceConfigs(const std::string &src_description); + GstDeviceMonitor *monitor_; }; -struct DeviceInfo { - gint width; - gint height; - gint fps_numerator; - gint fps_denominator; - std::string format; - - DeviceInfo() { - width = 0; - height = 0; - fps_numerator = 1; - fps_denominator = 1; - format = ""; - } - - inline DeviceInfo& operator = (const DeviceInfo& b) - { - if (this != &b) { - this->width = b.width; - this->height = b.height; - this->fps_numerator = b.fps_numerator; - this->fps_denominator = b.fps_denominator; - this->format = b.format; - } - return *this; - } - - inline bool operator < (const DeviceInfo b) const - { - return ( this->fps_numerator * this->height < b.fps_numerator * b.height ); - } -}; - -struct better_device_comparator -{ - inline bool operator () (const DeviceInfo a, const DeviceInfo b) const - { - return (a < b); - } -}; - -typedef std::set DeviceInfoSet; - class DeviceSource : public StreamSource { public: @@ -102,7 +108,6 @@ public: private: std::string device_; - DeviceInfoSet getDeviceConfigs(const std::string &pipeline); }; diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 2e1ca60..5083bd9 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -364,7 +364,7 @@ void ImGuiVisitor::visit (PatternSource& s) { for (int p = 0; p < Pattern::pattern_types.size(); ++p){ if (ImGui::Selectable( Pattern::pattern_types[p].c_str() )) { - s.setPattern(p); + s.setPattern(p, s.pattern()->resolution()); } } ImGui::EndCombo(); diff --git a/Mixer.cpp b/Mixer.cpp index ff45929..2f4eaf9 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -282,8 +282,8 @@ Source * Mixer::createSourceStream(const std::string &gstreamerpipeline) Source * Mixer::createSourcePattern(int pattern, glm::ivec2 res) { // ready to create a source - PatternSource *s = new PatternSource(res); - s->setPattern(pattern); + PatternSource *s = new PatternSource; + s->setPattern(pattern, res); // propose a new name based on pattern name renameSource(s, Pattern::pattern_types[pattern]); diff --git a/PatternSource.cpp b/PatternSource.cpp index 30c7279..32d8f1d 100644 --- a/PatternSource.cpp +++ b/PatternSource.cpp @@ -90,11 +90,9 @@ std::vector Pattern::pattern_types = { "100% Black", "Clock" }; -Pattern::Pattern(glm::ivec2 res) : Stream() +Pattern::Pattern() : Stream() { - width_ = res.x; - height_ = res.y; } glm::ivec2 Pattern::resolution() @@ -103,7 +101,7 @@ glm::ivec2 Pattern::resolution() } -void Pattern::open( uint pattern ) +void Pattern::open( uint pattern, glm::ivec2 res ) { type_ = CLAMP(pattern, 0, 25); std::string gstreamer_pattern = pattern_internal_[type_]; @@ -127,24 +125,24 @@ void Pattern::open( uint pattern ) single_frame_ = type_ < 15; // (private) open stream - Stream::open(gstreamer_pattern); + Stream::open(gstreamer_pattern, res.x, res.y); } -PatternSource::PatternSource(glm::ivec2 resolution) : StreamSource() +PatternSource::PatternSource() : StreamSource() { // create stream - stream_ = (Stream *) new Pattern(resolution); + stream_ = (Stream *) new Pattern; // set icons overlays_[View::MIXING]->attach( new Symbol(Symbol::PATTERN, glm::vec3(0.8f, 0.8f, 0.01f)) ); overlays_[View::LAYER]->attach( new Symbol(Symbol::PATTERN, glm::vec3(0.8f, 0.8f, 0.01f)) ); } -void PatternSource::setPattern(int id) +void PatternSource::setPattern(int type, glm::ivec2 resolution) { - Log::Notify("Creating Source with pattern '%s'", Pattern::pattern_types[id].c_str()); + Log::Notify("Creating Source with pattern '%s'", Pattern::pattern_types[type].c_str()); - pattern()->open( (uint) id ); + pattern()->open( (uint) type, resolution ); stream_->play(true); } diff --git a/PatternSource.h b/PatternSource.h index 9fde443..87ab0f6 100644 --- a/PatternSource.h +++ b/PatternSource.h @@ -10,8 +10,8 @@ class Pattern : public Stream public: static std::vector pattern_types; - Pattern(glm::ivec2 res); - void open( uint pattern ); + Pattern(); + void open( uint pattern, glm::ivec2 res); glm::ivec2 resolution(); inline uint type() const { return type_; } @@ -23,7 +23,7 @@ private: class PatternSource : public StreamSource { public: - PatternSource(glm::ivec2 resolution); + PatternSource(); // Source interface void accept (Visitor& v) override; @@ -33,7 +33,7 @@ public: // specific interface Pattern *pattern() const; - void setPattern(int id); + void setPattern(int type, glm::ivec2 resolution); }; diff --git a/SessionCreator.cpp b/SessionCreator.cpp index 0be39e1..42a5870 100644 --- a/SessionCreator.cpp +++ b/SessionCreator.cpp @@ -99,12 +99,12 @@ void SessionCreator::loadSession(XMLElement *sessionNode) if (!pType) continue; if ( std::string(pType) == "MediaSource") { - MediaSource *new_media_source = new MediaSource(); + MediaSource *new_media_source = new MediaSource; new_media_source->accept(*this); session_->addSource(new_media_source); } else if ( std::string(pType) == "SessionSource") { - SessionSource *new_session_source = new SessionSource(); + SessionSource *new_session_source = new SessionSource; new_session_source->accept(*this); session_->addSource(new_session_source); } @@ -114,13 +114,7 @@ void SessionCreator::loadSession(XMLElement *sessionNode) session_->addSource(new_render_source); } else if ( std::string(pType) == "PatternSource") { - - glm::ivec2 resolution(800, 600); - XMLElement* res = xmlCurrent_->FirstChildElement("resolution"); - if (res) - tinyxml2::XMLElementToGLM( res->FirstChildElement("ivec2"), resolution); - - PatternSource *new_pattern_source = new PatternSource(resolution); + PatternSource *new_pattern_source = new PatternSource; new_pattern_source->accept(*this); session_->addSource(new_pattern_source); } @@ -345,7 +339,13 @@ void SessionCreator::visit (SessionSource& s) void SessionCreator::visit (PatternSource& s) { uint p = xmlCurrent_->UnsignedAttribute("pattern"); - s.setPattern(p); + + glm::ivec2 resolution(800, 600); + XMLElement* res = xmlCurrent_->FirstChildElement("resolution"); + if (res) + tinyxml2::XMLElementToGLM( res->FirstChildElement("ivec2"), resolution); + + s.setPattern(p, resolution); }