VideoStreaming.cc 6.86 KB
Newer Older
1
/****************************************************************************
2
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
9 10 11 12 13


/**
 * @file
 *   @brief QGC Video Streaming Initialization
Gus Grubba's avatar
Gus Grubba committed
14
 *   @author Gus Grubba <gus@auterion.com>
15 16 17 18 19 20 21
 */

#include <QtQml>
#include <QDebug>

#if defined(QGC_GST_STREAMING)
#include <gst/gst.h>
22 23 24 25 26 27 28 29 30 31 32 33 34

#include "QGCLoggingCategory.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)
35
{
36 37
    if (level > gst_debug_category_get_threshold(category)) {
        return;
38
    }
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

    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;
66
}
67 68

#if defined(__ios__)
69 70
#include "gst_ios_init.h"
#endif
71 72
#else
#include "GLVideoItemStub.h"
73 74 75 76 77 78 79
#endif

#include "VideoStreaming.h"

#if defined(QGC_GST_STREAMING)
    G_BEGIN_DECLS
    // The static plugins we use
80
#if defined(__android__) || defined(__ios__)
81
    GST_PLUGIN_STATIC_DECLARE(coreelements);
82
    GST_PLUGIN_STATIC_DECLARE(playback);
83 84
    GST_PLUGIN_STATIC_DECLARE(libav);
    GST_PLUGIN_STATIC_DECLARE(rtp);
85
    GST_PLUGIN_STATIC_DECLARE(rtsp);
86 87 88
    GST_PLUGIN_STATIC_DECLARE(udp);
    GST_PLUGIN_STATIC_DECLARE(videoparsersbad);
    GST_PLUGIN_STATIC_DECLARE(x264);
89
    GST_PLUGIN_STATIC_DECLARE(rtpmanager);
90 91
    GST_PLUGIN_STATIC_DECLARE(isomp4);
    GST_PLUGIN_STATIC_DECLARE(matroska);
92
    GST_PLUGIN_STATIC_DECLARE(opengl);
93 94
#if defined(__android__)
    GST_PLUGIN_STATIC_DECLARE(androidmedia);
95 96 97
#elif defined(__ios__)
    GST_PLUGIN_STATIC_DECLARE(applemedia);
#endif
98
#endif
99
    GST_PLUGIN_STATIC_DECLARE(qmlgl);
100
    GST_PLUGIN_STATIC_DECLARE(qgc);
101 102 103
    G_END_DECLS
#endif

dogmaphobic's avatar
dogmaphobic committed
104
#if defined(QGC_GST_STREAMING)
105
#if (defined(Q_OS_MAC) && defined(QGC_INSTALL_RELEASE)) || defined(Q_OS_WIN)
dogmaphobic's avatar
dogmaphobic committed
106 107 108 109 110 111
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
Don Gagne's avatar
Don Gagne committed
112
#endif
dogmaphobic's avatar
dogmaphobic committed
113

114
void initializeVideoStreaming(int &argc, char* argv[], int gstDebuglevel)
115 116
{
#if defined(QGC_GST_STREAMING)
117
    #ifdef Q_OS_MAC
118 119 120 121 122 123 124 125 126 127
        #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");
        #endif
Don Gagne's avatar
Don Gagne committed
128 129 130
    #elif defined(Q_OS_WIN)
        QString currentDir = QCoreApplication::applicationDirPath();
        qgcputenv("GST_PLUGIN_PATH", currentDir, "/gstreamer-plugins");
131
    #endif
132

133 134 135 136 137
    //-- 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>(gstDebuglevel));
        gst_debug_remove_log_function(gst_debug_log_default);
        gst_debug_add_log_function(qt_gst_log, nullptr, nullptr);
138 139 140
    }

    // Initialize GStreamer
141
#if defined(__ios__)
142 143 144
    //-- iOS specific initialization
    gst_ios_pre_init();
#endif
145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
    GError* error = nullptr;
    if (!gst_init_check(&argc, &argv, &error)) {
        qCritical() << "gst_init_check() failed: " << error->message;
        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(opengl);

#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();
176
#endif
177

178 179 180 181
    /* 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 */
182 183 184 185 186 187 188 189
    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) {
190
        gst_object_unref(sink);
191
        sink = nullptr;
192 193 194
    } else {
        qCritical() << "unable to find qmlglsink - you need to build it yourself and add to GST_PLUGIN_PATH";
    }
195 196

    GST_PLUGIN_STATIC_REGISTER(qgc);
197
#else
198
    qmlRegisterType<GLVideoItemStub>("org.freedesktop.gstreamer.GLVideoItem", 1, 0, "GstGLVideoItem");
199 200
    Q_UNUSED(argc)
    Q_UNUSED(argv)
201
    Q_UNUSED(gstDebuglevel)
202
#endif
203
}