First minimal implementation of Screen device for screen capture under

Linux (ximagesrc). Cleanup code.
This commit is contained in:
brunoherbelin
2020-09-26 12:22:15 +02:00
parent 69c74aa103
commit df2a66484b
5 changed files with 98 additions and 155 deletions

View File

@@ -17,6 +17,53 @@
#include "Visitor.h" #include "Visitor.h"
#include "Log.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 gboolean
Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer user_data) 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); gst_message_parse_device_added (message, &device);
name = gst_device_get_display_name (device); name = gst_device_get_display_name (device);
manager().src_name_.push_back(name); 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); g_free (name);
std::ostringstream pipe; std::ostringstream pipe;
@@ -42,10 +94,6 @@ Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer us
manager().list_uptodate_ = false; 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); gst_object_unref (device);
} }
break; break;
@@ -53,7 +101,9 @@ Device::callback_device_monitor (GstBus * bus, GstMessage * message, gpointer us
gst_message_parse_device_removed (message, &device); gst_message_parse_device_removed (message, &device);
name = gst_device_get_display_name (device); name = gst_device_get_display_name (device);
manager().remove(name); manager().remove(name);
// g_print("Device removed: %s\n", name); #ifdef DEVICE_DEBUG
g_print("Device %s unplugged", name);
#endif
g_free (name); g_free (name);
manager().list_uptodate_ = false; manager().list_uptodate_ = false;
@@ -130,6 +180,22 @@ Device::Device()
src_config_.push_back(confs); src_config_.push_back(confs);
} }
g_list_free(devices); 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; list_uptodate_ = true;
} }
@@ -186,21 +252,10 @@ int Device::index(const std::string &device) const
return i; 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() DeviceSource::DeviceSource() : StreamSource()
{ {
// create stream // create stream
stream_ = (Stream *) new Stream(); stream_ = new Stream;
// set icons TODO // set icons TODO
overlays_[View::MIXING]->attach( new Symbol(Symbol::EMPTY, glm::vec3(0.8f, 0.8f, 0.01f)) ); overlays_[View::MIXING]->attach( new Symbol(Symbol::EMPTY, glm::vec3(0.8f, 0.8f, 0.01f)) );
@@ -221,23 +276,29 @@ void DeviceSource::setDevice(const std::string &devicename)
// test the device and get config // test the device and get config
DeviceConfigSet confs = Device::manager().config(index); DeviceConfigSet confs = Device::manager().config(index);
// for( DeviceConfigSet::iterator it = confs.begin(); it != confs.end(); it++ ){ #ifdef DEVICE_DEBUG
// Log::Info("config possible : %s %dx%d @ %d fps", (*it).format.c_str(), (*it).width, (*it).height, (*it).fps_numerator); Log::Info("Device %s supported configs:", devicename.c_str());
// } for( DeviceConfigSet::iterator it = confs.begin(); it != confs.end(); it++ ){
DeviceConfigSet::reverse_iterator best = confs.rbegin(); Log::Info(" - %s,\t%d x %d\t%d fps", (*it).format.c_str(), (*it).width, (*it).height, (*it).fps_numerator);
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); }
#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 << " ! " << 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).format.find("jpeg") != std::string::npos ) if ( best.format.find("jpeg") != std::string::npos )
pipeline << " ! jpegdec"; pipeline << " ! jpegdec";
if ( device_.find("Screen") != std::string::npos )
pipeline << " ! videoconvert ! video/x-raw,format=RGB ! queue";
pipeline << " ! videoconvert"; pipeline << " ! videoconvert";
stream_->open( pipeline.str(), (*best).width, (*best).height); stream_->open( pipeline.str(), best.width, best.height);
stream_->play(true); stream_->play(true);
} }
else else
@@ -293,7 +354,13 @@ DeviceConfigSet Device::getDeviceConfigs(const std::string &src_description)
// loop over all caps offered by the pad // loop over all caps offered by the pad
int C = gst_caps_get_size(device_caps); int C = gst_caps_get_size(device_caps);
for (int c = 0; c < C; ++c) { for (int c = 0; c < C; ++c) {
// get GST cap
GstStructure *decice_cap_struct = gst_caps_get_structure (device_caps, c); 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; DeviceConfig config;
// NAME : typically video/x-raw or image/jpeg // 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")) if ( gst_structure_has_field (decice_cap_struct, "height"))
gst_structure_get_int (decice_cap_struct, "height", &config.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 // add this config
configs.insert(config); configs.insert(config);

View File

@@ -76,6 +76,7 @@ public:
int index (const std::string &device) const; int index (const std::string &device) const;
static gboolean callback_device_monitor (GstBus *, GstMessage *, gpointer); static gboolean callback_device_monitor (GstBus *, GstMessage *, gpointer);
static DeviceConfigSet getDeviceConfigs(const std::string &src_description);
private: private:
@@ -84,7 +85,6 @@ private:
std::vector< std::string > src_description_; std::vector< std::string > src_description_;
std::vector< DeviceConfigSet > src_config_; std::vector< DeviceConfigSet > src_config_;
static DeviceConfigSet getDeviceConfigs(const std::string &src_description);
bool list_uptodate_; bool list_uptodate_;
GstDeviceMonitor *monitor_; GstDeviceMonitor *monitor_;

View File

@@ -121,122 +121,3 @@ string GstToolkit::gst_version()
return oss.str(); 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;
}

View File

@@ -23,9 +23,6 @@ std::list<std::string> all_plugin_features(std::string pluginname);
bool enable_feature (std::string name, bool enable); bool enable_feature (std::string name, bool enable);
GstDeviceMonitor *setup_raw_video_source_device_monitor();
} }
#endif // __GSTGUI_TOOLKIT_H_ #endif // __GSTGUI_TOOLKIT_H_

View File

@@ -149,6 +149,7 @@ void Stream::execute_open()
callbacks.new_preroll = callback_new_preroll; callbacks.new_preroll = callback_new_preroll;
callbacks.eos = NULL; callbacks.eos = NULL;
callbacks.new_sample = NULL; callbacks.new_sample = NULL;
Log::Info("Stream %d contains a single frame", id_);
} }
else { else {
callbacks.new_preroll = callback_new_preroll; callbacks.new_preroll = callback_new_preroll;