Newer
Older
/****************************************************************************
* (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/**
* @file
* @brief QGC Video Streaming Initialization
#include "GStreamer.h"
#include "GstVideoReceiver.h"
QGC_LOGGING_CATEGORY(GStreamerLog, "GStreamerLog")
static void qt_gst_log(GstDebugCategory * category,
GstDebugLevel level,
const gchar * file,
const gchar * function,
gint line,
GObject * object,
GstDebugMessage * message,
gpointer data)
Andrew Voznytsa
committed
{
if (level > gst_debug_category_get_threshold(category)) {
return;
Andrew Voznytsa
committed
}
QMessageLogger log(file, line, function);
char* object_info = gst_info_strdup_printf("%" GST_PTR_FORMAT, static_cast<void*>(object));
switch (level) {
default:
case GST_LEVEL_ERROR:
log.critical(GStreamerLog, "%s %s", object_info, gst_debug_message_get(message));
break;
case GST_LEVEL_WARNING:
log.warning(GStreamerLog, "%s %s", object_info, gst_debug_message_get(message));
break;
case GST_LEVEL_FIXME:
case GST_LEVEL_INFO:
log.info(GStreamerLog, "%s %s", object_info, gst_debug_message_get(message));
break;
case GST_LEVEL_DEBUG:
case GST_LEVEL_LOG:
case GST_LEVEL_TRACE:
case GST_LEVEL_MEMDUMP:
log.debug(GStreamerLog, "%s %s", object_info, gst_debug_message_get(message));
break;
}
g_free(object_info);
object_info = nullptr;
Andrew Voznytsa
committed
}
G_BEGIN_DECLS
// The static plugins we use
Andrew Voznytsa
committed
#if defined(__android__) || defined(__ios__)
GST_PLUGIN_STATIC_DECLARE(coreelements);
Andrew Voznytsa
committed
GST_PLUGIN_STATIC_DECLARE(playback);
GST_PLUGIN_STATIC_DECLARE(libav);
GST_PLUGIN_STATIC_DECLARE(rtp);
GST_PLUGIN_STATIC_DECLARE(rtsp);
GST_PLUGIN_STATIC_DECLARE(udp);
GST_PLUGIN_STATIC_DECLARE(videoparsersbad);
GST_PLUGIN_STATIC_DECLARE(x264);
GST_PLUGIN_STATIC_DECLARE(rtpmanager);
GST_PLUGIN_STATIC_DECLARE(isomp4);
GST_PLUGIN_STATIC_DECLARE(matroska);
GST_PLUGIN_STATIC_DECLARE(mpegtsdemux);
Andrew Voznytsa
committed
GST_PLUGIN_STATIC_DECLARE(opengl);
#if defined(__android__)
GST_PLUGIN_STATIC_DECLARE(androidmedia);
Andrew Voznytsa
committed
#elif defined(__ios__)
GST_PLUGIN_STATIC_DECLARE(applemedia);
#endif
Andrew Voznytsa
committed
GST_PLUGIN_STATIC_DECLARE(qmlgl);
GST_PLUGIN_STATIC_DECLARE(qgc);
#if (defined(Q_OS_MAC) && defined(QGC_INSTALL_RELEASE)) || defined(Q_OS_WIN)
static void qgcputenv(const QString& key, const QString& root, const QString& path)
{
QString value = root + path;
qputenv(key.toStdString().c_str(), QByteArray(value.toStdString().c_str()));
}
#endif
void
GStreamer::initialize(int argc, char* argv[], int debuglevel)
#ifdef Q_OS_MAC
#ifdef QGC_INSTALL_RELEASE
QString currentDir = QCoreApplication::applicationDirPath();
qgcputenv("GST_PLUGIN_SCANNER", currentDir, "/../Frameworks/GStreamer.framework/Versions/1.0/libexec/gstreamer-1.0/gst-plugin-scanner");
qgcputenv("GTK_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current");
qgcputenv("GIO_EXTRA_MODULES", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gio/modules");
qgcputenv("GST_PLUGIN_SYSTEM_PATH_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
qgcputenv("GST_PLUGIN_SYSTEM_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
qgcputenv("GST_PLUGIN_PATH_1_0", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
qgcputenv("GST_PLUGIN_PATH", currentDir, "/../Frameworks/GStreamer.framework/Versions/Current/lib/gstreamer-1.0");
#elif defined(Q_OS_WIN)
QString currentDir = QCoreApplication::applicationDirPath();
qgcputenv("GST_PLUGIN_PATH", currentDir, "/gstreamer-plugins");
#endif
//-- If gstreamer debugging is not configured via environment then use internal QT logging
if (qgetenv("GST_DEBUG").isEmpty()) {
gst_debug_set_default_threshold(static_cast<GstDebugLevel>(debuglevel));
gst_debug_remove_log_function(gst_debug_log_default);
gst_debug_add_log_function(qt_gst_log, nullptr, nullptr);
Andrew Voznytsa
committed
}
// Initialize GStreamer
Andrew Voznytsa
committed
//-- iOS specific initialization
gst_ios_pre_init();
#endif
Andrew Voznytsa
committed
Andrew Voznytsa
committed
GError* error = nullptr;
if (!gst_init_check(&argc, &argv, &error)) {
qCCritical(GStreamerLog) << "gst_init_check() failed: " << error->message;
Andrew Voznytsa
committed
g_error_free(error);
}
// The static plugins we use
#if defined(__android__) || defined(__ios__)
GST_PLUGIN_STATIC_REGISTER(coreelements);
GST_PLUGIN_STATIC_REGISTER(playback);
GST_PLUGIN_STATIC_REGISTER(libav);
GST_PLUGIN_STATIC_REGISTER(rtp);
GST_PLUGIN_STATIC_REGISTER(rtsp);
GST_PLUGIN_STATIC_REGISTER(udp);
GST_PLUGIN_STATIC_REGISTER(videoparsersbad);
GST_PLUGIN_STATIC_REGISTER(x264);
GST_PLUGIN_STATIC_REGISTER(rtpmanager);
GST_PLUGIN_STATIC_REGISTER(isomp4);
GST_PLUGIN_STATIC_REGISTER(matroska);
GST_PLUGIN_STATIC_REGISTER(mpegtsdemux);
Andrew Voznytsa
committed
GST_PLUGIN_STATIC_REGISTER(opengl);
Andrew Voznytsa
committed
#if defined(__android__)
GST_PLUGIN_STATIC_REGISTER(androidmedia);
#elif defined(__ios__)
GST_PLUGIN_STATIC_REGISTER(applemedia);
#endif
#endif
#if defined(__ios__)
gst_ios_post_init();
Andrew Voznytsa
committed
/* the plugin must be loaded before loading the qml file to register the
* GstGLVideoItem qml item
* FIXME Add a QQmlExtensionPlugin into qmlglsink to register GstGLVideoItem
* with the QML engine, then remove this */
Andrew Voznytsa
committed
GstElement *sink = gst_element_factory_make("qmlglsink", nullptr);
if (sink == nullptr) {
GST_PLUGIN_STATIC_REGISTER(qmlgl);
sink = gst_element_factory_make("qmlglsink", nullptr);
}
if (sink != nullptr) {
Andrew Voznytsa
committed
sink = nullptr;
qCCritical(GStreamerLog) << "unable to find qmlglsink - you need to build it yourself and add to GST_PLUGIN_PATH";
GST_PLUGIN_STATIC_REGISTER(qgc);
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
}
void*
GStreamer::createVideoSink(QObject* parent, QQuickItem* widget)
{
Q_UNUSED(parent)
GstElement* sink;
if ((sink = gst_element_factory_make("qgcvideosinkbin", nullptr)) != nullptr) {
g_object_set(sink, "widget", widget, NULL);
} else {
qCritical() << "gst_element_factory_make('qgcvideosinkbin') failed";
}
return sink;
}
void
GStreamer::releaseVideoSink(void* sink)
{
if (sink != nullptr) {
gst_object_unref(GST_ELEMENT(sink));
}
}
VideoReceiver*
GStreamer::createVideoReceiver(QObject* parent)
{
Q_UNUSED(parent)
return new GstVideoReceiver(nullptr);