3#include <QtCore/QSettings>
4#include <QtCore/QString>
20std::atomic_bool g_externalPluginLoaderFailed =
false;
22void glib_print_handler(
const gchar*
string)
24 qCInfo(GStreamerLoggingLog) << string;
27void glib_printerr_handler(
const gchar*
string)
29 qCWarning(GStreamerLoggingLog) << string;
32void glib_log_handler(
const gchar* log_domain, GLogLevelFlags log_level,
const gchar* message, gpointer user_data)
35 const QString domain = log_domain ? QString::fromUtf8(log_domain) : QStringLiteral(
"GLib");
36 const QString msg = QString::fromUtf8(message);
38 if (msg.contains(QStringLiteral(
"External plugin loader failed"), Qt::CaseInsensitive)) {
39 g_externalPluginLoaderFailed.store(
true);
42 if (msg.contains(QStringLiteral(
"pygobject initialization failed"), Qt::CaseInsensitive)) {
43 qCDebug(GStreamerLoggingLog) << domain << msg;
47 switch (log_level & G_LOG_LEVEL_MASK) {
48 case G_LOG_LEVEL_ERROR:
49 case G_LOG_LEVEL_CRITICAL:
50 qCCritical(GStreamerLoggingLog) << domain << msg;
52 case G_LOG_LEVEL_WARNING:
53 qCWarning(GStreamerLoggingLog) << domain << msg;
55 case G_LOG_LEVEL_MESSAGE:
56 case G_LOG_LEVEL_INFO:
57 qCInfo(GStreamerLoggingLog) << domain << msg;
59 case G_LOG_LEVEL_DEBUG:
61 qCDebug(GStreamerLoggingLog) << domain << msg;
72 g_externalPluginLoaderFailed.store(
false);
77 return g_externalPluginLoaderFailed.load();
82 g_set_print_handler(glib_print_handler);
83 g_set_printerr_handler(glib_printerr_handler);
84 g_log_set_default_handler(glib_log_handler,
nullptr);
87void qtGstLog(GstDebugCategory* category, GstDebugLevel level,
const gchar* file,
const gchar* function, gint line,
88 GObject*
object, GstDebugMessage* message, gpointer data)
92 if (level > gst_debug_category_get_threshold(category)) {
96 QMessageLogger log(file, line, function);
100 void operator()(gchar* p)
const { g_free(p); }
103 const std::unique_ptr<gchar, GFree> object_info(gst_info_strdup_printf(
"%" GST_PTR_FORMAT,
object));
106 case GST_LEVEL_ERROR:
107 log.critical(GStreamerAPILog,
"%s %s", object_info.get(), gst_debug_message_get(message));
109 case GST_LEVEL_WARNING:
110 log.warning(GStreamerAPILog,
"%s %s", object_info.get(), gst_debug_message_get(message));
112 case GST_LEVEL_FIXME:
114 log.info(GStreamerAPILog,
"%s %s", object_info.get(), gst_debug_message_get(message));
116 case GST_LEVEL_DEBUG:
121 case GST_LEVEL_TRACE:
122 case GST_LEVEL_MEMDUMP:
124 log.debug(GStreamerAPILog,
"%s %s", object_info.get(), gst_debug_message_get(message));
133 gst_debug_remove_log_function(gst_debug_log_default);
137 if (!qEnvironmentVariableIsEmpty(
"GST_DEBUG")) {
142 if (settings.contains(AppSettings::gstDebugLevelName)) {
144 std::clamp(settings.value(AppSettings::gstDebugLevelName).toInt(), 0,
static_cast<int>(GST_LEVEL_MEMDUMP));
145 gst_debug_set_default_threshold(
static_cast<GstDebugLevel
>(level));
151 if (!gst_is_initialized()) {
154 const int clamped = std::clamp(level, 0,
static_cast<int>(GST_LEVEL_MEMDUMP));
155 gst_debug_set_default_threshold(
static_cast<GstDebugLevel
>(clamped));
156 qCDebug(GStreamerLoggingLog) <<
"GStreamer debug threshold set to" << clamped;
161 GList* factories = gst_element_factory_list_get_elements(
162 static_cast<GstElementFactoryListType
>(GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO),
166 qCDebug(GStreamerDecoderRanksLog) <<
"No video decoder factories found";
170 factories = g_list_sort(factories, [](gconstpointer lhs, gconstpointer rhs) -> gint {
171 const guint lhsRank = gst_plugin_feature_get_rank(GST_PLUGIN_FEATURE(lhs));
172 const guint rhsRank = gst_plugin_feature_get_rank(GST_PLUGIN_FEATURE(rhs));
173 if (lhsRank != rhsRank) {
174 return (lhsRank > rhsRank) ? -1 : 1;
176 return g_strcmp0(gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(lhs)),
177 gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(rhs)));
180 qCDebug(GStreamerDecoderRanksLog) <<
"Video decoder ranks:";
181 for (GList* node = factories; node !=
nullptr; node = node->next) {
182 GstElementFactory* factory = GST_ELEMENT_FACTORY(node->data);
183 GstPluginFeature* feature = GST_PLUGIN_FEATURE(factory);
184 const gchar* featureName = gst_plugin_feature_get_name(feature);
185 const guint rank = gst_plugin_feature_get_rank(feature);
186 const gchar* klass = gst_element_factory_get_klass(factory);
189 GstPlugin* plugin = gst_plugin_feature_get_plugin(feature);
190 const gchar* pluginName = plugin ? gst_plugin_get_name(plugin) :
"?";
192 qCDebug(GStreamerDecoderRanksLog).noquote()
193 << QStringLiteral(
" [%1] %2/%3 rank=%4 (%5)")
194 .arg(isHw ? QStringLiteral(
"HW") : QStringLiteral(
"SW"), QString::fromUtf8(pluginName),
195 QString::fromUtf8(featureName))
197 .arg(QString::fromUtf8(klass));
200 gst_object_unref(plugin);
204 gst_plugin_feature_list_free(factories);
#define QGC_LOGGING_CATEGORY_ON(name, categoryStr)
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void configureDebugLogging()
void qtGstLog(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer data)
void setDebugLevel(int level)
bool didExternalPluginLoaderFail()
void redirectGLibLogging()
bool isHardwareDecoderFactory(GstElementFactory *factory)
void resetExternalPluginLoaderFailure()