From df2a66484bbd615533007a54df1963ab2edf1190 Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sat, 26 Sep 2020 12:22:15 +0200 Subject: [PATCH] First minimal implementation of Screen device for screen capture under Linux (ximagesrc). Cleanup code. --- DeviceSource.cpp | 128 +++++++++++++++++++++++++++++++++++------------ DeviceSource.h | 2 +- GstToolkit.cpp | 119 ------------------------------------------- GstToolkit.h | 3 -- Stream.cpp | 1 + 5 files changed, 98 insertions(+), 155 deletions(-) diff --git a/DeviceSource.cpp b/DeviceSource.cpp index d8241d0..701deb2 100644 --- a/DeviceSource.cpp +++ b/DeviceSource.cpp @@ -17,6 +17,53 @@ #include "Visitor.h" #include "Log.h" +#ifndef NDEBUG +#define DEVICE_DEBUG +#endif + +////EXAMPLE : +/// +//v4l2deviceprovider, udev-probed=(boolean)true, +//device.bus_path=(string)pci-0000:00:14.0-usb-0:2:1.0, +//sysfs.path=(string)/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/video4linux/video0, +//device.bus=(string)usb, +//device.subsystem=(string)video4linux, +//device.vendor.id=(string)1bcf, +//device.vendor.name=(string)"Sunplus\\x20IT\\x20Co\\x20", +//device.product.id=(string)2286, +//device.product.name=(string)"AUSDOM\ FHD\ Camera:\ AUSDOM\ FHD\ C", +//device.serial=(string)Sunplus_IT_Co_AUSDOM_FHD_Camera, +//device.capabilities=(string):capture:, +//device.api=(string)v4l2, +//device.path=(string)/dev/video0, +//v4l2.device.driver=(string)uvcvideo, +//v4l2.device.card=(string)"AUSDOM\ FHD\ Camera:\ AUSDOM\ FHD\ C", +//v4l2.device.bus_info=(string)usb-0000:00:14.0-2, +//v4l2.device.version=(uint)328748, +//v4l2.device.capabilities=(uint)2225078273, +//v4l2.device.device_caps=(uint)69206017; +//Device added: AUSDOM FHD Camera: AUSDOM FHD C - v4l2src device=/dev/video0 + +//v4l2deviceprovider, udev-probed=(boolean)true, +//device.bus_path=(string)pci-0000:00:14.0-usb-0:4:1.0, +//sysfs.path=(string)/sys/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/video4linux/video2, +//device.bus=(string)usb, +//device.subsystem=(string)video4linux, +//device.vendor.id=(string)046d, +//device.vendor.name=(string)046d, +//device.product.id=(string)080f, +//device.product.name=(string)"UVC\ Camera\ \(046d:080f\)", +//device.serial=(string)046d_080f_3EA77580, +//device.capabilities=(string):capture:, +//device.api=(string)v4l2, +//device.path=(string)/dev/video2, +//v4l2.device.driver=(string)uvcvideo, +//v4l2.device.card=(string)"UVC\ Camera\ \(046d:080f\)", +//v4l2.device.bus_info=(string)usb-0000:00:14.0-4, +//v4l2.device.version=(uint)328748, +//v4l2.device.capabilities=(uint)2225078273, +//v4l2.device.device_caps=(uint)69206017; // decimal of hexadecimal v4l code Device Caps : 0x04200001 +//Device added: UVC Camera (046d:080f) - v4l2src device=/dev/video2 gboolean Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer user_data) @@ -29,6 +76,11 @@ Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer us gst_message_parse_device_added (message, &device); name = gst_device_get_display_name (device); manager().src_name_.push_back(name); +#ifdef DEVICE_DEBUG + gchar *stru = gst_structure_to_string( gst_device_get_properties(device) ); + g_print("Device %s plugged : %s", name, stru); + g_free (stru); +#endif g_free (name); std::ostringstream pipe; @@ -42,10 +94,6 @@ Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer us manager().list_uptodate_ = false; -// gchar *stru; -// stru = gst_structure_to_string( gst_device_get_properties(device) ); -// g_print("New device %s \n", stru); - gst_object_unref (device); } break; @@ -53,7 +101,9 @@ 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); +#ifdef DEVICE_DEBUG + g_print("Device %s unplugged", name); +#endif g_free (name); manager().list_uptodate_ = false; @@ -130,6 +180,22 @@ Device::Device() src_config_.push_back(confs); } g_list_free(devices); + + // Add config for plugged screen + src_name_.push_back("Screen"); + src_description_.push_back("ximagesrc "); + // Try to auto find resolution + DeviceConfigSet confs = getDeviceConfigs("ximagesrc name=devsrc"); + // fix the framerate (otherwise at 1 FPS + DeviceConfig best = *confs.rbegin(); + DeviceConfigSet confscreen; + best.fps_numerator = 15; + confscreen.insert(best); + src_config_.push_back(confscreen); + + // TODO Use lib glfw to get monitors + // TODO Detect auto removal of monitors + list_uptodate_ = true; } @@ -186,21 +252,10 @@ int Device::index(const std::string &device) const return i; } - -//// std::string desc = "v4l2src ! video/x-raw,width=320,height=240,framerate=30/1 ! videoconvert"; -//// std::string desc = "v4l2src ! jpegdec ! videoconvert"; -// std::string desc = "v4l2src ! image/jpeg,width=640,height=480,framerate=30/1 ! jpegdec ! videoscale ! videoconvert"; - -//// std::string desc = "v4l2src ! jpegdec ! videoscale ! videoconvert"; - -//// std::string desc = "videotestsrc pattern=snow is-live=true "; -//// std::string desc = "ximagesrc endx=800 endy=600 ! video/x-raw,framerate=15/1 ! videoscale ! videoconvert"; - - DeviceSource::DeviceSource() : StreamSource() { // create stream - stream_ = (Stream *) new Stream(); + stream_ = new Stream; // set icons TODO overlays_[View::MIXING]->attach( new Symbol(Symbol::EMPTY, glm::vec3(0.8f, 0.8f, 0.01f)) ); @@ -220,24 +275,30 @@ void DeviceSource::setDevice(const std::string &devicename) pipeline << Device::manager().description(index); // test the device and get config - DeviceConfigSet confs = Device::manager().config(index); -// for( DeviceConfigSet::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(); - Log::Info("Auto select optimal config for '%s': %s %dx%d @ %d fps", device_.c_str(), (*best).format.c_str(), (*best).width, (*best).height, (*best).fps_numerator); + DeviceConfigSet confs = Device::manager().config(index); +#ifdef DEVICE_DEBUG + Log::Info("Device %s supported configs:", devicename.c_str()); + for( DeviceConfigSet::iterator it = confs.begin(); it != confs.end(); it++ ){ + Log::Info(" - %s,\t%d x %d\t%d fps", (*it).format.c_str(), (*it).width, (*it).height, (*it).fps_numerator); + } +#endif + DeviceConfig best = *confs.rbegin(); + Log::Info("Device %s selected its optimal config: %s %dx%d@%dfps", device_.c_str(), best.format.c_str(), best.width, best.height, best.fps_numerator); - pipeline << " ! " << (*best).format; - pipeline << ",framerate=" << (*best).fps_numerator << "/" << (*best).fps_denominator; - pipeline << ",width=" << (*best).width; - pipeline << ",height=" << (*best).height; + pipeline << " ! " << best.format; + pipeline << ",framerate=" << best.fps_numerator << "/" << best.fps_denominator; + pipeline << ",width=" << best.width; + pipeline << ",height=" << best.height; - if ( (*best).format.find("jpeg") != std::string::npos ) + if ( best.format.find("jpeg") != std::string::npos ) pipeline << " ! jpegdec"; + if ( device_.find("Screen") != std::string::npos ) + pipeline << " ! videoconvert ! video/x-raw,format=RGB ! queue"; + pipeline << " ! videoconvert"; - stream_->open( pipeline.str(), (*best).width, (*best).height); + stream_->open( pipeline.str(), best.width, best.height); stream_->play(true); } else @@ -293,7 +354,13 @@ DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description) // loop over all caps offered by the pad int C = gst_caps_get_size(device_caps); for (int c = 0; c < C; ++c) { + // get GST cap GstStructure *decice_cap_struct = gst_caps_get_structure (device_caps, c); +// gchar *capstext = gst_structure_to_string (decice_cap_struct); +// Log::Info("DeviceSource found cap struct %s", capstext); +// g_free(capstext); + + // fill our config DeviceConfig config; // NAME : typically video/x-raw or image/jpeg @@ -339,9 +406,6 @@ DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description) if ( gst_structure_has_field (decice_cap_struct, "height")) gst_structure_get_int (decice_cap_struct, "height", &config.height); -// 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 d2ccc6e..52b1e03 100644 --- a/DeviceSource.h +++ b/DeviceSource.h @@ -76,6 +76,7 @@ public: int index (const std::string &device) const; static gboolean callback_device_monitor (GstBus *, GstMessage *, gpointer); + static DeviceConfigSet getDeviceConfigs(const std::string &src_description); private: @@ -84,7 +85,6 @@ private: std::vector< std::string > src_description_; std::vector< DeviceConfigSet > src_config_; - static DeviceConfigSet getDeviceConfigs(const std::string &src_description); bool list_uptodate_; GstDeviceMonitor *monitor_; diff --git a/GstToolkit.cpp b/GstToolkit.cpp index ba7cc40..d35656c 100644 --- a/GstToolkit.cpp +++ b/GstToolkit.cpp @@ -121,122 +121,3 @@ string GstToolkit::gst_version() return oss.str(); } - -////EXAMPLE : -/// -//v4l2deviceprovider, udev-probed=(boolean)true, -//device.bus_path=(string)pci-0000:00:14.0-usb-0:2:1.0, -//sysfs.path=(string)/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/video4linux/video0, -//device.bus=(string)usb, -//device.subsystem=(string)video4linux, -//device.vendor.id=(string)1bcf, -//device.vendor.name=(string)"Sunplus\\x20IT\\x20Co\\x20", -//device.product.id=(string)2286, -//device.product.name=(string)"AUSDOM\ FHD\ Camera:\ AUSDOM\ FHD\ C", -//device.serial=(string)Sunplus_IT_Co_AUSDOM_FHD_Camera, -//device.capabilities=(string):capture:, -//device.api=(string)v4l2, -//device.path=(string)/dev/video0, -//v4l2.device.driver=(string)uvcvideo, -//v4l2.device.card=(string)"AUSDOM\ FHD\ Camera:\ AUSDOM\ FHD\ C", -//v4l2.device.bus_info=(string)usb-0000:00:14.0-2, -//v4l2.device.version=(uint)328748, -//v4l2.device.capabilities=(uint)2225078273, -//v4l2.device.device_caps=(uint)69206017; -//Device added: AUSDOM FHD Camera: AUSDOM FHD C - v4l2src device=/dev/video0 - -//v4l2deviceprovider, udev-probed=(boolean)true, -//device.bus_path=(string)pci-0000:00:14.0-usb-0:4:1.0, -//sysfs.path=(string)/sys/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4:1.0/video4linux/video2, -//device.bus=(string)usb, -//device.subsystem=(string)video4linux, -//device.vendor.id=(string)046d, -//device.vendor.name=(string)046d, -//device.product.id=(string)080f, -//device.product.name=(string)"UVC\ Camera\ \(046d:080f\)", -//device.serial=(string)046d_080f_3EA77580, -//device.capabilities=(string):capture:, -//device.api=(string)v4l2, -//device.path=(string)/dev/video2, -//v4l2.device.driver=(string)uvcvideo, -//v4l2.device.card=(string)"UVC\ Camera\ \(046d:080f\)", -//v4l2.device.bus_info=(string)usb-0000:00:14.0-4, -//v4l2.device.version=(uint)328748, -//v4l2.device.capabilities=(uint)2225078273, -//v4l2.device.device_caps=(uint)69206017; // decimal of hexadecimal v4l code Device Caps : 0x04200001 -//Device added: UVC Camera (046d:080f) - v4l2src device=/dev/video2 - -static gboolean -my_bus_func (GstBus * bus, GstMessage * message, gpointer user_data) -{ - GstDevice *device; - gchar *name; - gchar *stru; - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_DEVICE_ADDED: - gst_message_parse_device_added (message, &device); - name = gst_device_get_display_name (device); - - stru = gst_structure_to_string( gst_device_get_properties(device) ); - g_print("%s \n", stru); - g_print("Device added: %s - %ssrc device=%s\n", name, - gst_structure_get_string(gst_device_get_properties(device), "device.api"), - gst_structure_get_string(gst_device_get_properties(device), "device.path")); - - g_free (name); - gst_object_unref (device); - break; - case GST_MESSAGE_DEVICE_REMOVED: - gst_message_parse_device_removed (message, &device); - name = gst_device_get_display_name (device); - g_print("Device removed: %s\n", name); - g_free (name); - gst_object_unref (device); - break; - default: - break; - } - - return G_SOURCE_CONTINUE; -} - -GstDeviceMonitor *GstToolkit::setup_raw_video_source_device_monitor() -{ - GstDeviceMonitor *monitor; - GstBus *bus; - GstCaps *caps; - - monitor = gst_device_monitor_new (); - - bus = gst_device_monitor_get_bus (monitor); - gst_bus_add_watch (bus, my_bus_func, NULL); - gst_object_unref (bus); - - caps = gst_caps_new_empty_simple ("video/x-raw"); - gst_device_monitor_add_filter (monitor, "Video/Source", caps); - gst_caps_unref (caps); - - gst_device_monitor_set_show_all_devices(monitor, true); - - gst_device_monitor_start (monitor); - - GList *devices = gst_device_monitor_get_devices(monitor); - - GList *tmp; - for (tmp = devices; tmp ; tmp = tmp->next ) { - - GstDevice *device = (GstDevice *) tmp->data; - - gchar *name = gst_device_get_display_name (device); - g_print("Device already plugged: %s - %ssrc device=%s\n", name, - gst_structure_get_string(gst_device_get_properties(device), "device.api"), - gst_structure_get_string(gst_device_get_properties(device), "device.path")); - - g_free (name); - } - g_list_free(devices); - - return monitor; -} - diff --git a/GstToolkit.h b/GstToolkit.h index a3dfc30..d60cc6e 100644 --- a/GstToolkit.h +++ b/GstToolkit.h @@ -23,9 +23,6 @@ std::list all_plugin_features(std::string pluginname); bool enable_feature (std::string name, bool enable); - -GstDeviceMonitor *setup_raw_video_source_device_monitor(); - } #endif // __GSTGUI_TOOLKIT_H_ diff --git a/Stream.cpp b/Stream.cpp index b102283..7ba188b 100644 --- a/Stream.cpp +++ b/Stream.cpp @@ -149,6 +149,7 @@ void Stream::execute_open() callbacks.new_preroll = callback_new_preroll; callbacks.eos = NULL; callbacks.new_sample = NULL; + Log::Info("Stream %d contains a single frame", id_); } else { callbacks.new_preroll = callback_new_preroll;