Fixed Device manager: restore gmainloop

The gmainloop is used by gst to detect devices. Fixed bugs on detection of invalid devices.
This commit is contained in:
Bruno Herbelin
2022-01-02 14:17:10 +01:00
parent 53ae715816
commit 61e89286bc
4 changed files with 91 additions and 79 deletions

View File

@@ -38,7 +38,7 @@
#ifndef NDEBUG #ifndef NDEBUG
#define DEVICE_DEBUG #define DEVICE_DEBUG
//#define GST_DEVICE_DEBUG #define GST_DEVICE_DEBUG
#endif #endif
@@ -120,69 +120,82 @@ gboolean
Device::callback_device_monitor (GstBus *, GstMessage * message, gpointer ) Device::callback_device_monitor (GstBus *, GstMessage * message, gpointer )
{ {
GstDevice *device; GstDevice *device;
gchar *name;
switch (GST_MESSAGE_TYPE (message)) { switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_DEVICE_ADDED: { case GST_MESSAGE_DEVICE_ADDED:
{
gst_message_parse_device_added (message, &device); gst_message_parse_device_added (message, &device);
name = gst_device_get_display_name (device); manager().add(device);
// ignore if already in the list
if ( std::find(manager().src_name_.begin(), manager().src_name_.end(), name) != manager().src_name_.end())
break;
manager().src_name_.push_back(name);
#ifdef GST_DEVICE_DEBUG
gchar *stru = gst_structure_to_string( gst_device_get_properties(device) );
g_print("\nDevice %s plugged : %s\n", name, stru);
g_free (stru);
#endif
g_free (name);
std::string p = pipelineForDevice(device, manager().src_description_.size());
manager().src_description_.push_back(p);
DeviceConfigSet confs = getDeviceConfigs(p);
manager().src_config_.push_back(confs);
manager().list_uptodate_ = false;
gst_object_unref (device); gst_object_unref (device);
} }
break; break;
case GST_MESSAGE_DEVICE_REMOVED: { case GST_MESSAGE_DEVICE_REMOVED:
{
gst_message_parse_device_removed (message, &device); gst_message_parse_device_removed (message, &device);
name = gst_device_get_display_name (device); manager().remove(device);
manager().remove(name);
#ifdef GST_DEVICE_DEBUG
g_print("\nDevice %s unplugged\n", name);
#endif
g_free (name);
manager().list_uptodate_ = false;
gst_object_unref (device); gst_object_unref (device);
} }
break; break;
default: default:
break; break;
} }
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
} }
void Device::remove(const char *device)
void Device::add(GstDevice *device)
{ {
if (device==nullptr)
return;
gchar *device_name = gst_device_get_display_name (device);
if ( std::find(manager().src_name_.begin(), manager().src_name_.end(), device_name) == manager().src_name_.end()) {
std::string p = pipelineForDevice(device, manager().src_description_.size());
DeviceConfigSet confs = getDeviceConfigs(p);
// add if not in the list and valid
if (!p.empty() && !confs.empty()) {
src_name_.push_back(device_name);
src_description_.push_back(p);
src_config_.push_back(confs);
#ifdef GST_DEVICE_DEBUG
gchar *stru = gst_structure_to_string( gst_device_get_properties(device) );
g_print("\nDevice %s plugged : %s\n", device_name, stru);
g_free (stru);
#endif
}
list_uptodate_ = false;
}
g_free (device_name);
}
void Device::remove(GstDevice *device)
{
if (device==nullptr)
return;
gchar *device_name = gst_device_get_display_name (device);
std::vector< std::string >::iterator nameit = src_name_.begin(); std::vector< std::string >::iterator nameit = src_name_.begin();
std::vector< std::string >::iterator descit = src_description_.begin(); std::vector< std::string >::iterator descit = src_description_.begin();
std::vector< DeviceConfigSet >::iterator coit = src_config_.begin(); std::vector< DeviceConfigSet >::iterator coit = src_config_.begin();
while (nameit != src_name_.end()){ while (nameit != src_name_.end()){
if ( (*nameit).compare(device) == 0 ) if ( (*nameit).compare(device_name) == 0 )
{ {
src_name_.erase(nameit); src_name_.erase(nameit);
src_description_.erase(descit); src_description_.erase(descit);
src_config_.erase(coit); src_config_.erase(coit);
list_uptodate_ = false;
#ifdef GST_DEVICE_DEBUG
g_print("\nDevice %s unplugged\n", device_name);
#endif
break; break;
} }
@@ -190,10 +203,16 @@ void Device::remove(const char *device)
++descit; ++descit;
++coit; ++coit;
} }
g_free (device_name);
} }
Device::Device() Device::Device(): list_uptodate_(false)
{
}
void Device::init()
{ {
GstBus *bus; GstBus *bus;
GstCaps *caps; GstCaps *caps;
@@ -217,24 +236,9 @@ Device::Device()
GList *devices = gst_device_monitor_get_devices(monitor_); GList *devices = gst_device_monitor_get_devices(monitor_);
GList *tmp; GList *tmp;
for (tmp = devices; tmp ; tmp = tmp->next ) { for (tmp = devices; tmp ; tmp = tmp->next ) {
GstDevice *device = (GstDevice *) tmp->data; GstDevice *device = (GstDevice *) tmp->data;
add(device);
gchar *name = gst_device_get_display_name (device); gst_object_unref (device);
src_name_.push_back(name);
g_free (name);
#ifdef GST_DEVICE_DEBUG
gchar *stru = gst_structure_to_string( gst_device_get_properties(device) );
g_print("\nDevice %s already plugged : %s", name, stru);
g_free (stru);
#endif
std::string p = pipelineForDevice(device, src_description_.size());
src_description_.push_back(p);
DeviceConfigSet confs = getDeviceConfigs(p);
src_config_.push_back(confs);
} }
g_list_free(devices); g_list_free(devices);
@@ -383,32 +387,34 @@ void DeviceSource::setDevice(const std::string &devicename)
Log::Info(" - %s %s %d x %d %.1f fps", (*it).stream.c_str(), (*it).format.c_str(), (*it).width, (*it).height, fps); Log::Info(" - %s %s %d x %d %.1f fps", (*it).stream.c_str(), (*it).format.c_str(), (*it).width, (*it).height, fps);
} }
#endif #endif
DeviceConfig best = *confs.rbegin(); if (!confs.empty()) {
float fps = static_cast<float>(best.fps_numerator) / static_cast<float>(best.fps_denominator); DeviceConfig best = *confs.rbegin();
Log::Info("Device %s selected its optimal config: %s %s %dx%d@%.1ffps", device_.c_str(), best.stream.c_str(), best.format.c_str(), best.width, best.height, fps); float fps = static_cast<float>(best.fps_numerator) / static_cast<float>(best.fps_denominator);
Log::Info("Device %s selected its optimal config: %s %s %dx%d@%.1ffps", device_.c_str(), best.stream.c_str(), best.format.c_str(), best.width, best.height, fps);
pipeline << " ! " << best.stream; pipeline << " ! " << best.stream;
if (!best.format.empty()) if (!best.format.empty())
pipeline << ",format=" << best.format; pipeline << ",format=" << best.format;
pipeline << ",framerate=" << best.fps_numerator << "/" << best.fps_denominator; pipeline << ",framerate=" << best.fps_numerator << "/" << best.fps_denominator;
pipeline << ",width=" << best.width; pipeline << ",width=" << best.width;
pipeline << ",height=" << best.height; pipeline << ",height=" << best.height;
if ( best.stream.find("jpeg") != std::string::npos ) if ( best.stream.find("jpeg") != std::string::npos )
pipeline << " ! jpegdec"; pipeline << " ! jpegdec";
if ( device_.find("Screen") != std::string::npos ) if ( device_.find("Screen") != std::string::npos )
pipeline << " ! videoconvert ! video/x-raw,format=RGB ! queue max-size-buffers=3"; pipeline << " ! videoconvert ! video/x-raw,format=RGB ! queue max-size-buffers=3";
pipeline << " ! videoconvert"; pipeline << " ! videoconvert";
// resize render buffer // resize render buffer
if (renderbuffer_) if (renderbuffer_)
renderbuffer_->resize(best.width, best.height); renderbuffer_->resize(best.width, best.height);
// open gstreamer // open gstreamer
stream_->open( pipeline.str(), best.width, best.height); stream_->open( pipeline.str(), best.width, best.height);
stream_->play(true); stream_->play(true);
}
// will be ready after init and one frame rendered // will be ready after init and one frame rendered
ready_ = false; ready_ = false;

View File

@@ -100,6 +100,7 @@ public:
return _instance; return _instance;
} }
void init();
int numDevices () const; int numDevices () const;
std::string name (int index) const; std::string name (int index) const;
std::string description (int index) const; std::string description (int index) const;
@@ -116,7 +117,8 @@ public:
private: private:
void remove(const char *device); void remove(GstDevice *device);
void add(GstDevice *device);
std::vector< std::string > src_name_; std::vector< std::string > src_name_;
std::vector< std::string > src_description_; std::vector< std::string > src_description_;

View File

@@ -352,10 +352,8 @@ void Rendering::draw()
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents(); glfwPollEvents();
#ifndef USE_GST_APPSINK_CALLBACKS
// no g_main_loop_run(loop) : update global GMainContext // no g_main_loop_run(loop) : update global GMainContext
g_main_context_iteration(NULL, FALSE); g_main_context_iteration(NULL, FALSE);
#endif
} }

View File

@@ -30,6 +30,7 @@
#include "ControlManager.h" #include "ControlManager.h"
#include "Connection.h" #include "Connection.h"
#include "Metronome.h" #include "Metronome.h"
#include "DeviceSource.h"
#if defined(APPLE) #if defined(APPLE)
extern "C"{ extern "C"{
@@ -120,6 +121,11 @@ int main(int argc, char *argv[])
if ( !Rendering::manager().init() ) if ( !Rendering::manager().init() )
return 1; return 1;
///
/// DEVICES INIT
///
Device::manager().init();
/// ///
/// UI INIT /// UI INIT
/// ///