BugFix Device manager initialization

Ensure initialization is complete before other calls to Device::manager can operate (e.g. setDevice in session Creator)
This commit is contained in:
Bruno
2022-01-17 23:47:07 +01:00
parent 7acffabdd8
commit 6b4781b7d5
2 changed files with 57 additions and 28 deletions

View File

@@ -141,7 +141,7 @@ void Device::add(GstDevice *device)
g_free (stru); g_free (stru);
#endif #endif
} }
list_uptodate_ = false;
} }
g_free (device_name); g_free (device_name);
@@ -169,9 +169,7 @@ void Device::remove(GstDevice *device)
src_name_.erase(nameit); src_name_.erase(nameit);
src_description_.erase(descit); src_description_.erase(descit);
src_config_.erase(coit); src_config_.erase(coit);
monitor_unplug_event_ = true;
list_uptodate_ = false;
#ifdef GST_DEVICE_DEBUG #ifdef GST_DEVICE_DEBUG
g_print("\nDevice %s unplugged\n", device_name); g_print("\nDevice %s unplugged\n", device_name);
#endif #endif
@@ -189,23 +187,25 @@ void Device::remove(GstDevice *device)
} }
Device::Device(): list_uptodate_(false)
Device::Device(): monitor_initialized_(false), monitor_unplug_event_(false)
{ {
std::thread(launchMonitoring, this).detach(); std::thread(launchMonitoring, this).detach();
} }
void Device::launchMonitoring(Device *d) void Device::launchMonitoring(Device *d)
{ {
// gstreamer monitoring of devices
d->monitor_ = gst_device_monitor_new (); d->monitor_ = gst_device_monitor_new ();
// watching all video stream sources
GstCaps *caps = gst_caps_new_empty_simple ("video/x-raw"); GstCaps *caps = gst_caps_new_empty_simple ("video/x-raw");
gst_device_monitor_add_filter (d->monitor_, "Video/Source", caps); gst_device_monitor_add_filter (d->monitor_, "Video/Source", caps);
gst_caps_unref (caps); gst_caps_unref (caps);
gst_device_monitor_set_show_all_devices(d->monitor_, true); gst_device_monitor_set_show_all_devices(d->monitor_, true);
gst_device_monitor_start (d->monitor_); gst_device_monitor_start (d->monitor_);
// Add configs for plugged devices // Add configs for already plugged devices
GList *devices = gst_device_monitor_get_devices(d->monitor_); GList *devices = gst_device_monitor_get_devices(d->monitor_);
GList *tmp; GList *tmp;
for (tmp = devices; tmp ; tmp = tmp->next ) { for (tmp = devices; tmp ; tmp = tmp->next ) {
@@ -215,12 +215,7 @@ void Device::launchMonitoring(Device *d)
} }
g_list_free(devices); g_list_free(devices);
// Add config for plugged screen // Try to get captrure screen
d->access_.lock();
d->src_name_.push_back("Screen capture");
d->src_description_.push_back(gst_plugin_vidcap);
// Try to auto find resolution
DeviceConfigSet confs = getDeviceConfigs(gst_plugin_vidcap); DeviceConfigSet confs = getDeviceConfigs(gst_plugin_vidcap);
if (!confs.empty()) { if (!confs.empty()) {
DeviceConfig best = *confs.rbegin(); DeviceConfig best = *confs.rbegin();
@@ -229,29 +224,40 @@ void Device::launchMonitoring(Device *d)
best.fps_numerator = MIN( best.fps_numerator, 30); best.fps_numerator = MIN( best.fps_numerator, 30);
best.fps_denominator = 1; best.fps_denominator = 1;
confscreen.insert(best); confscreen.insert(best);
// add to config list
d->access_.lock();
d->src_name_.push_back("Screen capture");
d->src_description_.push_back(gst_plugin_vidcap);
d->src_config_.push_back(confscreen); d->src_config_.push_back(confscreen);
d->access_.unlock();
} }
d->access_.unlock();
d->list_uptodate_ = true; // monitor is initialized
d->monitor_initialized_ = true;
d->monitor_initialization_.notify_all();
// create a local g_main_context for this threaded monitor // create a local g_main_context to launch monitoring in this thread
GMainContext *_gcontext_device = g_main_context_new(); GMainContext *_gcontext_device = g_main_context_new();
if (g_main_context_acquire(_gcontext_device)) g_main_context_acquire(_gcontext_device);
g_printerr("Starting Device monitoring... \n");
// temporarily push as default the default g_main_context for add_watch // temporarily push as default the default g_main_context for add_watch
g_main_context_push_thread_default(_gcontext_device); g_main_context_push_thread_default(_gcontext_device);
// add a bus watch on the device monitoring using the main loop we created
GstBus *bus = gst_device_monitor_get_bus (d->monitor_); GstBus *bus = gst_device_monitor_get_bus (d->monitor_);
gst_bus_add_watch (bus, callback_device_monitor, NULL); gst_bus_add_watch (bus, callback_device_monitor, NULL);
gst_object_unref (bus); gst_object_unref (bus);
// restore g_main_context
g_main_context_pop_thread_default(_gcontext_device); g_main_context_pop_thread_default(_gcontext_device);
// start main loop for this context (blocking infinitely) // start main loop for this context (blocking infinitely)
g_main_loop_run( g_main_loop_new (_gcontext_device, true) ); g_main_loop_run( g_main_loop_new (_gcontext_device, true) );
}
bool Device::initialized()
{
return Device::manager().monitor_initialized_;
} }
int Device::numDevices() int Device::numDevices()
@@ -305,13 +311,6 @@ Source *Device::createSource(const std::string &device) const
return s; return s;
} }
bool Device::unplugged(const std::string &device)
{
if (list_uptodate_)
return false;
return !exists(device);
}
std::string Device::name(int index) std::string Device::name(int index)
{ {
std::string ret = ""; std::string ret = "";
@@ -378,8 +377,15 @@ DeviceSource::~DeviceSource()
void DeviceSource::setDevice(const std::string &devicename) void DeviceSource::setDevice(const std::string &devicename)
{ {
// instanciate and wait for monitor initialization if not already initialized
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
Device::manager().monitor_initialization_.wait(lck, Device::initialized);
// remember device name
device_ = devicename; device_ = devicename;
// check existence of a device with that name
int index = Device::manager().index(device_); int index = Device::manager().index(device_);
if (index > -1) { if (index > -1) {
@@ -444,7 +450,23 @@ void DeviceSource::accept(Visitor& v)
bool DeviceSource::failed() const bool DeviceSource::failed() const
{ {
return stream_->failed() || Device::manager().unplugged(device_); // fail if stream openned and failed
if (stream_ && stream_->failed())
return true;
// if there was a unplug event
if (Device::manager().monitor_unplug_event_) {
// check if it was this device that was unplugged
if (!Device::manager().exists(device_)){
// the unplug event is resolved
Device::manager().monitor_unplug_event_ = false;
// this device source fail
return true;
}
}
// no other reason to fail
return false;
} }
DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description) DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description)
@@ -570,6 +592,11 @@ DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description)
} }
} }
} }
else {
// default
config.fps_numerator = 30;
config.fps_denominator = 1;
}
// WIDTH and HEIGHT // WIDTH and HEIGHT
if ( gst_structure_has_field (decice_cap_struct, "width")) if ( gst_structure_has_field (decice_cap_struct, "width"))

View File

@@ -107,7 +107,6 @@ public:
int index (const std::string &device); int index (const std::string &device);
bool exists (const std::string &device) ; bool exists (const std::string &device) ;
bool unplugged (const std::string &device) ;
Source *createSource(const std::string &device) const; Source *createSource(const std::string &device) const;
@@ -117,6 +116,7 @@ public:
private: private:
static void launchMonitoring(Device *d); static void launchMonitoring(Device *d);
static bool initialized();
void remove(GstDevice *device); void remove(GstDevice *device);
void add(GstDevice *device); void add(GstDevice *device);
@@ -124,8 +124,10 @@ private:
std::vector< std::string > src_name_; std::vector< std::string > src_name_;
std::vector< std::string > src_description_; std::vector< std::string > src_description_;
std::vector< DeviceConfigSet > src_config_; std::vector< DeviceConfigSet > src_config_;
bool list_uptodate_;
GstDeviceMonitor *monitor_; GstDeviceMonitor *monitor_;
std::condition_variable monitor_initialization_;
bool monitor_initialized_;
bool monitor_unplug_event_;
std::list< DeviceSource * > device_sources_; std::list< DeviceSource * > device_sources_;
}; };