diff options
49 files changed, 816 insertions, 265 deletions
diff --git a/.qmake.conf b/.qmake.conf index 09a75f0b9..b3c7403c2 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -2,4 +2,4 @@ load(qt_build_config) DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST -MODULE_VERSION = 5.14.1 +MODULE_VERSION = 5.15.0 diff --git a/examples/multimedia/spectrum/app/engine.cpp b/examples/multimedia/spectrum/app/engine.cpp index fd977785b..d188259dc 100644 --- a/examples/multimedia/spectrum/app/engine.cpp +++ b/examples/multimedia/spectrum/app/engine.cpp @@ -569,15 +569,17 @@ bool Engine::selectFormat() sampleRatesList += m_audioInputDevice.supportedSampleRates(); sampleRatesList += m_audioOutputDevice.supportedSampleRates(); - sampleRatesList = sampleRatesList.toSet().toList(); // remove duplicates std::sort(sampleRatesList.begin(), sampleRatesList.end()); + const auto uniqueRatesEnd = std::unique(sampleRatesList.begin(), sampleRatesList.end()); + sampleRatesList.erase(uniqueRatesEnd, sampleRatesList.end()); ENGINE_DEBUG << "Engine::initialize frequenciesList" << sampleRatesList; QList<int> channelsList; channelsList += m_audioInputDevice.supportedChannelCounts(); channelsList += m_audioOutputDevice.supportedChannelCounts(); - channelsList = channelsList.toSet().toList(); std::sort(channelsList.begin(), channelsList.end()); + const auto uniqueChannelsEnd = std::unique(channelsList.begin(), channelsList.end()); + channelsList.erase(uniqueChannelsEnd, channelsList.end()); ENGINE_DEBUG << "Engine::initialize channelsList" << channelsList; QAudioFormat format; diff --git a/src/gsttools/gstvideoconnector.c b/src/gsttools/gstvideoconnector.c index b85f5bdbe..7f88a89af 100644 --- a/src/gsttools/gstvideoconnector.c +++ b/src/gsttools/gstvideoconnector.c @@ -116,13 +116,13 @@ gst_video_connector_class_init (GstVideoConnectorClass * klass) gst_video_connector_signals[SIGNAL_RESEND_NEW_SEGMENT] = g_signal_new ("resend-new-segment", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstVideoConnectorClass, resend_new_segment), NULL, NULL, + G_STRUCT_OFFSET (GstVideoConnectorClass, resend_new_segment), nullptr, nullptr, g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); gst_video_connector_signals[SIGNAL_CONNECTION_FAILED] = g_signal_new ("connection-failed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - 0, NULL, NULL, + 0, nullptr, nullptr, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } @@ -159,7 +159,7 @@ gst_video_connector_init (GstVideoConnector *element, element->relinked = FALSE; element->failedSignalEmited = FALSE; gst_segment_init (&element->segment, GST_FORMAT_TIME); - element->latest_buffer = NULL; + element->latest_buffer = nullptr; } static void @@ -167,9 +167,9 @@ gst_video_connector_reset (GstVideoConnector * element) { element->relinked = FALSE; element->failedSignalEmited = FALSE; - if (element->latest_buffer != NULL) { + if (element->latest_buffer != nullptr) { gst_buffer_unref (element->latest_buffer); - element->latest_buffer = NULL; + element->latest_buffer = nullptr; } gst_segment_init (&element->segment, GST_FORMAT_UNDEFINED); } @@ -196,7 +196,7 @@ gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size, if (!buf) return GST_FLOW_ERROR; - *buf = NULL; + *buf = nullptr; gboolean isFailed = FALSE; while (1) { @@ -265,7 +265,7 @@ gst_video_connector_setcaps (GstPad *pad, GstCaps *caps) /* forward-negotiate */ gboolean res = gst_pad_set_caps(element->srcpad, caps); - gchar * debugmsg = NULL; + gchar * debugmsg = nullptr; GST_DEBUG_OBJECT(element, "gst_video_connector_setcaps %s %i", debugmsg = gst_caps_to_string(caps), res); if (debugmsg) g_free(debugmsg); @@ -407,7 +407,7 @@ gst_video_connector_chain (GstPad * pad, GstBuffer * buf) if (element->latest_buffer) { gst_buffer_unref (element->latest_buffer); - element->latest_buffer = NULL; + element->latest_buffer = nullptr; } element->latest_buffer = gst_buffer_ref(buf); diff --git a/src/gsttools/qgstappsrc.cpp b/src/gsttools/qgstappsrc.cpp index d5c44ec08..f6ecd48be 100644 --- a/src/gsttools/qgstappsrc.cpp +++ b/src/gsttools/qgstappsrc.cpp @@ -69,7 +69,7 @@ bool QGstAppSrc::setup(GstElement* appsrc) gst_object_ref(G_OBJECT(m_appSrc)); gst_app_src_set_callbacks(m_appSrc, (GstAppSrcCallbacks*)&m_callbacks, this, (GDestroyNotify)&QGstAppSrc::destroy_notify); - g_object_get(G_OBJECT(m_appSrc), "max-bytes", &m_maxBytes, NULL); + g_object_get(G_OBJECT(m_appSrc), "max-bytes", &m_maxBytes, nullptr); if (m_sequential) m_streamType = GST_APP_STREAM_TYPE_STREAM; diff --git a/src/gsttools/qgstbufferpoolinterface_p.h b/src/gsttools/qgstbufferpoolinterface_p.h index 45e573262..f5cbc35aa 100644 --- a/src/gsttools/qgstbufferpoolinterface_p.h +++ b/src/gsttools/qgstbufferpoolinterface_p.h @@ -79,7 +79,7 @@ public: /*! Build an QAbstractVideoBuffer instance from GstBuffer. - Returns NULL if GstBuffer is not compatible with this buffer pool. + Returns nullptr if GstBuffer is not compatible with this buffer pool. This method is called from gstreamer video sink thread. */ @@ -105,7 +105,7 @@ public: /*! Build an QAbstractVideoBuffer instance from compatible GstBuffer. - Returns NULL if GstBuffer is not compatible with this buffer pool. + Returns nullptr if GstBuffer is not compatible with this buffer pool. This method is called from gstreamer video sink thread. */ diff --git a/src/gsttools/qgstcodecsinfo.cpp b/src/gsttools/qgstcodecsinfo.cpp index c6e61f824..2522ee19c 100644 --- a/src/gsttools/qgstcodecsinfo.cpp +++ b/src/gsttools/qgstcodecsinfo.cpp @@ -99,7 +99,7 @@ QStringList QGstCodecsInfo::codecOptions(const QString &codec) const if (elementName.isEmpty()) return options; - GstElement *element = gst_element_factory_make(elementName, NULL); + GstElement *element = gst_element_factory_make(elementName, nullptr); if (element) { guint numProperties; GParamSpec **properties = g_object_class_list_properties(G_OBJECT_GET_CLASS(element), @@ -174,7 +174,7 @@ void QGstCodecsInfo::updateCodecs(ElementType elementType) } } - GstCaps *newCaps = gst_caps_new_full(newStructure, NULL); + GstCaps *newCaps = gst_caps_new_full(newStructure, nullptr); gchar *capsString = gst_caps_to_string(newCaps); QString codec = QLatin1String(capsString); diff --git a/src/gsttools/qgstreameraudioinputselector.cpp b/src/gsttools/qgstreameraudioinputselector.cpp index 72d079cbc..36b36dda4 100644 --- a/src/gsttools/qgstreameraudioinputselector.cpp +++ b/src/gsttools/qgstreameraudioinputselector.cpp @@ -124,23 +124,23 @@ void QGstreamerAudioInputSelector::updateAlsaDevices() } n = hints; - while (*n != NULL) { + while (*n != nullptr) { char *name = snd_device_name_get_hint(*n, "NAME"); char *descr = snd_device_name_get_hint(*n, "DESC"); char *io = snd_device_name_get_hint(*n, "IOID"); - if ((name != NULL) && (descr != NULL)) { - if ( io == NULL || qstrcmp(io,"Input") == 0 ) { + if ((name != nullptr) && (descr != nullptr)) { + if (io == nullptr || qstrcmp(io, "Input") == 0) { m_names.append(QLatin1String("alsa:")+QString::fromUtf8(name)); m_descriptions.append(QString::fromUtf8(descr)); } } - if (name != NULL) + if (name != nullptr) free(name); - if (descr != NULL) + if (descr != nullptr) free(descr); - if (io != NULL) + if (io != nullptr) free(io); n++; } diff --git a/src/gsttools/qgstreamerbufferprobe.cpp b/src/gsttools/qgstreamerbufferprobe.cpp index d95de4c63..e2956eadd 100644 --- a/src/gsttools/qgstreamerbufferprobe.cpp +++ b/src/gsttools/qgstreamerbufferprobe.cpp @@ -70,11 +70,11 @@ void QGstreamerBufferProbe::addProbeToPad(GstPad *pad, bool downstream) : GST_PAD_PROBE_TYPE_EVENT_UPSTREAM, capsProbe, this, - NULL); + nullptr); } if (m_flags & ProbeBuffers) { m_bufferProbeId = gst_pad_add_probe( - pad, GST_PAD_PROBE_TYPE_BUFFER, bufferProbe, this, NULL); + pad, GST_PAD_PROBE_TYPE_BUFFER, bufferProbe, this, nullptr); } #else Q_UNUSED(downstream); diff --git a/src/gsttools/qgstreamerbushelper.cpp b/src/gsttools/qgstreamerbushelper.cpp index 5df046fde..1a4034eee 100644 --- a/src/gsttools/qgstreamerbushelper.cpp +++ b/src/gsttools/qgstreamerbushelper.cpp @@ -69,7 +69,7 @@ public: connect(m_intervalTimer, SIGNAL(timeout()), SLOT(interval())); m_intervalTimer->start(); } else { - m_tag = gst_bus_add_watch_full(bus, G_PRIORITY_DEFAULT, busCallback, this, NULL); + m_tag = gst_bus_add_watch_full(bus, G_PRIORITY_DEFAULT, busCallback, this, nullptr); } } @@ -186,27 +186,27 @@ QGstreamerBusHelper::~QGstreamerBusHelper() void QGstreamerBusHelper::installMessageFilter(QObject *filter) { - QGstreamerSyncMessageFilter *syncFilter = qobject_cast<QGstreamerSyncMessageFilter*>(filter); + auto syncFilter = qobject_cast<QGstreamerSyncMessageFilter*>(filter); if (syncFilter) { QMutexLocker lock(&d->filterMutex); if (!d->syncFilters.contains(syncFilter)) d->syncFilters.append(syncFilter); } - QGstreamerBusMessageFilter *busFilter = qobject_cast<QGstreamerBusMessageFilter*>(filter); + auto busFilter = qobject_cast<QGstreamerBusMessageFilter*>(filter); if (busFilter && !d->busFilters.contains(busFilter)) d->busFilters.append(busFilter); } void QGstreamerBusHelper::removeMessageFilter(QObject *filter) { - QGstreamerSyncMessageFilter *syncFilter = qobject_cast<QGstreamerSyncMessageFilter*>(filter); + auto syncFilter = qobject_cast<QGstreamerSyncMessageFilter*>(filter); if (syncFilter) { QMutexLocker lock(&d->filterMutex); d->syncFilters.removeAll(syncFilter); } - QGstreamerBusMessageFilter *busFilter = qobject_cast<QGstreamerBusMessageFilter*>(filter); + auto busFilter = qobject_cast<QGstreamerBusMessageFilter*>(filter); if (busFilter) d->busFilters.removeAll(busFilter); } diff --git a/src/gsttools/qgstreamerplayersession.cpp b/src/gsttools/qgstreamerplayersession.cpp index ed3f16c5f..1d16df5b7 100644 --- a/src/gsttools/qgstreamerplayersession.cpp +++ b/src/gsttools/qgstreamerplayersession.cpp @@ -118,7 +118,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) void QGstreamerPlayerSession::initPlaybin() { - m_playbin = gst_element_factory_make(QT_GSTREAMER_PLAYBIN_ELEMENT_NAME, NULL); + m_playbin = gst_element_factory_make(QT_GSTREAMER_PLAYBIN_ELEMENT_NAME, nullptr); if (m_playbin) { //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale, //since those elements are included in the video output bin when necessary. @@ -131,7 +131,7 @@ void QGstreamerPlayerSession::initPlaybin() flags |= GST_PLAY_FLAG_NATIVE_VIDEO; #endif } - g_object_set(G_OBJECT(m_playbin), "flags", flags, NULL); + g_object_set(G_OBJECT(m_playbin), "flags", flags, nullptr); const QByteArray envAudioSink = qgetenv("QT_GSTREAMER_PLAYBIN_AUDIOSINK"); GstElement *audioSink = gst_element_factory_make(envAudioSink.isEmpty() ? "autoaudiosink" : envAudioSink, "audiosink"); @@ -144,7 +144,7 @@ void QGstreamerPlayerSession::initPlaybin() if (m_volumeElement) { m_audioSink = gst_bin_new("audio-output-bin"); - gst_bin_add_many(GST_BIN(m_audioSink), m_volumeElement, audioSink, NULL); + gst_bin_add_many(GST_BIN(m_audioSink), m_volumeElement, audioSink, nullptr); gst_element_link(m_volumeElement, audioSink); GstPad *pad = gst_element_get_static_pad(m_volumeElement, "sink"); @@ -156,13 +156,13 @@ void QGstreamerPlayerSession::initPlaybin() } } - g_object_set(G_OBJECT(m_playbin), "audio-sink", m_audioSink, NULL); + g_object_set(G_OBJECT(m_playbin), "audio-sink", m_audioSink, nullptr); addAudioBufferProbe(); } } #if GST_CHECK_VERSION(1,0,0) - m_videoIdentity = gst_element_factory_make("identity", NULL); // floating ref + m_videoIdentity = gst_element_factory_make("identity", nullptr); // floating ref #else m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0)); // floating ref g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this); @@ -172,8 +172,8 @@ void QGstreamerPlayerSession::initPlaybin() qt_gst_object_ref_sink(GST_OBJECT(m_colorSpace)); #endif - m_nullVideoSink = gst_element_factory_make("fakesink", NULL); - g_object_set(G_OBJECT(m_nullVideoSink), "sync", true, NULL); + m_nullVideoSink = gst_element_factory_make("fakesink", nullptr); + g_object_set(G_OBJECT(m_nullVideoSink), "sync", true, nullptr); gst_object_ref(GST_OBJECT(m_nullVideoSink)); m_videoOutputBin = gst_bin_new("video-output-bin"); @@ -183,15 +183,15 @@ void QGstreamerPlayerSession::initPlaybin() GstElement *videoOutputSink = m_videoIdentity; #if QT_CONFIG(gstreamer_gl) if (QGstUtils::useOpenGL()) { - videoOutputSink = gst_element_factory_make("glupload", NULL); - GstElement *colorConvert = gst_element_factory_make("glcolorconvert", NULL); - gst_bin_add_many(GST_BIN(m_videoOutputBin), videoOutputSink, colorConvert, m_videoIdentity, m_nullVideoSink, NULL); - gst_element_link_many(videoOutputSink, colorConvert, m_videoIdentity, NULL); + videoOutputSink = gst_element_factory_make("glupload", nullptr); + GstElement *colorConvert = gst_element_factory_make("glcolorconvert", nullptr); + gst_bin_add_many(GST_BIN(m_videoOutputBin), videoOutputSink, colorConvert, m_videoIdentity, m_nullVideoSink, nullptr); + gst_element_link_many(videoOutputSink, colorConvert, m_videoIdentity, nullptr); } else { - gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, NULL); + gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, nullptr); } #else - gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, NULL); + gst_bin_add_many(GST_BIN(m_videoOutputBin), m_videoIdentity, m_nullVideoSink, nullptr); #endif gst_element_link(m_videoIdentity, m_nullVideoSink); @@ -206,7 +206,7 @@ void QGstreamerPlayerSession::initPlaybin() // Sort out messages setBus(gst_element_get_bus(m_playbin)); - g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL); + g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, nullptr); g_signal_connect(G_OBJECT(m_playbin), "notify::source", G_CALLBACK(playbinNotifySource), this); g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this); @@ -287,7 +287,7 @@ void QGstreamerPlayerSession::configureAppSrcElement(GObject* object, GObject *o return; GstElement *appsrc; - g_object_get(orig, "source", &appsrc, NULL); + g_object_get(orig, "source", &appsrc, nullptr); if (!self->appsrc()->setup(appsrc)) qWarning()<<"Could not setup appsrc element"; @@ -314,7 +314,7 @@ void QGstreamerPlayerSession::loadFromStream(const QNetworkRequest &request, QIO m_tags.clear(); emit tagsChanged(); - g_object_set(G_OBJECT(m_playbin), "uri", "appsrc://", NULL); + g_object_set(G_OBJECT(m_playbin), "uri", "appsrc://", nullptr); if (!m_streamTypes.isEmpty()) { m_streamProperties.clear(); @@ -346,7 +346,7 @@ void QGstreamerPlayerSession::loadFromUri(const QNetworkRequest &request) m_tags.clear(); emit tagsChanged(); - g_object_set(G_OBJECT(m_playbin), "uri", m_request.url().toEncoded().constData(), NULL); + g_object_set(G_OBJECT(m_playbin), "uri", m_request.url().toEncoded().constData(), nullptr); if (!m_streamTypes.isEmpty()) { m_streamProperties.clear(); @@ -547,13 +547,13 @@ int QGstreamerPlayerSession::activeStream(QMediaStreamsControl::StreamType strea if (m_playbin) { switch (streamType) { case QMediaStreamsControl::AudioStream: - g_object_get(G_OBJECT(m_playbin), "current-audio", &streamNumber, NULL); + g_object_get(G_OBJECT(m_playbin), "current-audio", &streamNumber, nullptr); break; case QMediaStreamsControl::VideoStream: - g_object_get(G_OBJECT(m_playbin), "current-video", &streamNumber, NULL); + g_object_get(G_OBJECT(m_playbin), "current-video", &streamNumber, nullptr); break; case QMediaStreamsControl::SubPictureStream: - g_object_get(G_OBJECT(m_playbin), "current-text", &streamNumber, NULL); + g_object_get(G_OBJECT(m_playbin), "current-text", &streamNumber, nullptr); break; default: break; @@ -578,13 +578,13 @@ void QGstreamerPlayerSession::setActiveStream(QMediaStreamsControl::StreamType s if (m_playbin) { switch (streamType) { case QMediaStreamsControl::AudioStream: - g_object_set(G_OBJECT(m_playbin), "current-audio", streamNumber, NULL); + g_object_set(G_OBJECT(m_playbin), "current-audio", streamNumber, nullptr); break; case QMediaStreamsControl::VideoStream: - g_object_set(G_OBJECT(m_playbin), "current-video", streamNumber, NULL); + g_object_set(G_OBJECT(m_playbin), "current-video", streamNumber, nullptr); break; case QMediaStreamsControl::SubPictureStream: - g_object_set(G_OBJECT(m_playbin), "current-text", streamNumber, NULL); + g_object_set(G_OBJECT(m_playbin), "current-text", streamNumber, nullptr); break; default: break; @@ -666,9 +666,7 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) } } - QGstreamerVideoRendererInterface* renderer = qobject_cast<QGstreamerVideoRendererInterface*>(videoOutput); - - m_renderer = renderer; + m_renderer = qobject_cast<QGstreamerVideoRendererInterface*>(videoOutput); emit rendererChanged(); // No sense to continue if custom pipeline requested. @@ -737,7 +735,7 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) qDebug() << "Failed to connect video output, inserting the colorspace element."; #endif gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace); - linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL); + linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, nullptr); } #endif @@ -746,7 +744,7 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "show-preroll-frame") != 0) { gboolean value = m_displayPrerolledFrame; - g_object_set(G_OBJECT(m_videoSink), "show-preroll-frame", value, NULL); + g_object_set(G_OBJECT(m_videoSink), "show-preroll-frame", value, nullptr); } addVideoBufferProbe(); @@ -782,7 +780,7 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) //block pads, async to avoid locking in paused state GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src"); #if GST_CHECK_VERSION(1,0,0) - this->pad_probe_id = gst_pad_add_probe(srcPad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCKING), block_pad_cb, this, NULL); + this->pad_probe_id = gst_pad_add_probe(srcPad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCKING), block_pad_cb, this, nullptr); #else gst_pad_set_blocked_async(srcPad, true, &block_pad_cb, this); #endif @@ -815,7 +813,7 @@ void QGstreamerPlayerSession::finishVideoOutputChange() //pad is not blocked, it's possible to swap outputs only in the null state qWarning() << "Pad is not blocked yet, could not switch video sink"; GstState identityElementState = GST_STATE_NULL; - gst_element_get_state(m_videoIdentity, &identityElementState, NULL, GST_CLOCK_TIME_NONE); + gst_element_get_state(m_videoIdentity, &identityElementState, nullptr, GST_CLOCK_TIME_NONE); if (identityElementState != GST_STATE_NULL) { gst_object_unref(GST_OBJECT(srcPad)); return; //can't change vo yet, received async call from the previous change @@ -873,7 +871,7 @@ void QGstreamerPlayerSession::finishVideoOutputChange() qDebug() << "Failed to connect video output, inserting the colorspace element."; #endif gst_bin_add(GST_BIN(m_videoOutputBin), m_colorSpace); - linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, NULL); + linked = gst_element_link_many(m_videoIdentity, m_colorSpace, m_videoSink, nullptr); } #endif @@ -964,7 +962,7 @@ void QGstreamerPlayerSession::insertColorSpaceElement(GstElement *element, gpoin gst_element_unlink(session->m_videoIdentity, session->m_videoSink); gst_bin_add(GST_BIN(session->m_videoOutputBin), session->m_colorSpace); - gst_element_link_many(session->m_videoIdentity, session->m_colorSpace, session->m_videoSink, NULL); + gst_element_link_many(session->m_videoIdentity, session->m_colorSpace, session->m_videoSink, nullptr); GstState state = GST_STATE_VOID_PENDING; @@ -1108,7 +1106,7 @@ void QGstreamerPlayerSession::setVolume(int volume) m_volume = volume; if (m_volumeElement) - g_object_set(G_OBJECT(m_volumeElement), "volume", m_volume / 100.0, NULL); + g_object_set(G_OBJECT(m_volumeElement), "volume", m_volume / 100.0, nullptr); emit volumeChanged(m_volume); } @@ -1123,7 +1121,7 @@ void QGstreamerPlayerSession::setMuted(bool muted) m_muted = muted; if (m_volumeElement) - g_object_set(G_OBJECT(m_volumeElement), "mute", m_muted ? TRUE : FALSE, NULL); + g_object_set(G_OBJECT(m_volumeElement), "mute", m_muted ? TRUE : FALSE, nullptr); emit mutedStateChanged(m_muted); } @@ -1455,9 +1453,9 @@ void QGstreamerPlayerSession::getStreamsInfo() gint videoStreamsCount = 0; gint textStreamsCount = 0; - g_object_get(G_OBJECT(m_playbin), "n-audio", &audioStreamsCount, NULL); - g_object_get(G_OBJECT(m_playbin), "n-video", &videoStreamsCount, NULL); - g_object_get(G_OBJECT(m_playbin), "n-text", &textStreamsCount, NULL); + g_object_get(G_OBJECT(m_playbin), "n-audio", &audioStreamsCount, nullptr); + g_object_get(G_OBJECT(m_playbin), "n-video", &videoStreamsCount, nullptr); + g_object_get(G_OBJECT(m_playbin), "n-text", &textStreamsCount, nullptr); haveAudio = audioStreamsCount > 0; haveVideo = videoStreamsCount > 0; @@ -1617,7 +1615,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo Q_UNUSED(p); GstElement *source = 0; - g_object_get(o, "source", &source, NULL); + g_object_get(o, "source", &source, nullptr); if (source == 0) return; @@ -1634,7 +1632,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo // defined in extra-headers if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "user-agent") != 0) { g_object_set(G_OBJECT(source), "user-agent", - self->m_request.rawHeader(userAgentString).constData(), NULL); + self->m_request.rawHeader(userAgentString).constData(), nullptr); } // The rest @@ -1659,7 +1657,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo } if (gst_structure_n_fields(extras) > 0) - g_object_set(G_OBJECT(source), "extra-headers", extras, NULL); + g_object_set(G_OBJECT(source), "extra-headers", extras, nullptr); gst_structure_free(extras); } @@ -1675,7 +1673,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo // Gst 0.10 -> microsecond convertedTimeout *= 1000000; #endif - g_object_set(G_OBJECT(source), "timeout", convertedTimeout, NULL); + g_object_set(G_OBJECT(source), "timeout", convertedTimeout, nullptr); self->m_sourceType = UDPSrc; //The udpsrc is always a live source. self->m_isLiveSource = true; @@ -1684,26 +1682,26 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo const QString var = QLatin1String("udpsrc.caps"); if (query.hasQueryItem(var)) { GstCaps *caps = gst_caps_from_string(query.queryItemValue(var).toLatin1().constData()); - g_object_set(G_OBJECT(source), "caps", caps, NULL); + g_object_set(G_OBJECT(source), "caps", caps, nullptr); gst_caps_unref(caps); } } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstSoupHTTPSrc") == 0) { //souphttpsrc timeout unit = second - g_object_set(G_OBJECT(source), "timeout", guint(timeout), NULL); + g_object_set(G_OBJECT(source), "timeout", guint(timeout), nullptr); self->m_sourceType = SoupHTTPSrc; //since gst_base_src_is_live is not reliable, so we check the source property directly gboolean isLive = false; - g_object_get(G_OBJECT(source), "is-live", &isLive, NULL); + g_object_get(G_OBJECT(source), "is-live", &isLive, nullptr); self->m_isLiveSource = isLive; } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstMMSSrc") == 0) { self->m_sourceType = MMSSrc; self->m_isLiveSource = gst_base_src_is_live(GST_BASE_SRC(source)); - g_object_set(G_OBJECT(source), "tcp-timeout", G_GUINT64_CONSTANT(timeout*1000000), NULL); + g_object_set(G_OBJECT(source), "tcp-timeout", G_GUINT64_CONSTANT(timeout*1000000), nullptr); } else if (qstrcmp(G_OBJECT_CLASS_NAME(G_OBJECT_GET_CLASS(source)), "GstRTSPSrc") == 0) { //rtspsrc acts like a live source and will therefore only generate data in the PLAYING state. self->m_sourceType = RTSPSrc; self->m_isLiveSource = true; - g_object_set(G_OBJECT(source), "buffer-mode", 1, NULL); + g_object_set(G_OBJECT(source), "buffer-mode", 1, nullptr); } else { self->m_sourceType = UnknownSrc; self->m_isLiveSource = gst_base_src_is_live(GST_BASE_SRC(source)); @@ -1717,7 +1715,7 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo #endif if (self->m_videoSink) - g_object_set(G_OBJECT(self->m_videoSink), "sync", !self->m_isLiveSource, NULL); + g_object_set(G_OBJECT(self->m_videoSink), "sync", !self->m_isLiveSource, nullptr); gst_object_unref(source); } @@ -1738,7 +1736,7 @@ void QGstreamerPlayerSession::handleVolumeChange(GObject *o, GParamSpec *p, gpoi void QGstreamerPlayerSession::updateVolume() { double volume = 1.0; - g_object_get(m_playbin, "volume", &volume, NULL); + g_object_get(m_playbin, "volume", &volume, nullptr); if (m_volume != int(volume*100 + 0.5)) { m_volume = int(volume*100 + 0.5); @@ -1760,7 +1758,7 @@ void QGstreamerPlayerSession::handleMutedChange(GObject *o, GParamSpec *p, gpoin void QGstreamerPlayerSession::updateMuted() { gboolean muted = FALSE; - g_object_get(G_OBJECT(m_playbin), "mute", &muted, NULL); + g_object_get(G_OBJECT(m_playbin), "mute", &muted, nullptr); if (m_muted != muted) { m_muted = muted; #ifdef DEBUG_PLAYBIN @@ -1775,8 +1773,8 @@ static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstC { GList *templates; - g_return_val_if_fail(factory != NULL, FALSE); - g_return_val_if_fail(caps != NULL, FALSE); + g_return_val_if_fail(factory != nullptr, FALSE); + g_return_val_if_fail(caps != nullptr, FALSE); templates = factory->staticpadtemplates; @@ -1813,7 +1811,7 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi if (g_str_has_prefix(factoryName, "vaapi")) { GstPad *sinkPad = gst_element_get_static_pad(session->m_videoSink, "sink"); #if GST_CHECK_VERSION(1,0,0) - GstCaps *sinkCaps = gst_pad_query_caps(sinkPad, NULL); + GstCaps *sinkCaps = gst_pad_query_caps(sinkPad, nullptr); #else GstCaps *sinkCaps = gst_pad_get_caps(sinkPad); #endif @@ -1843,7 +1841,7 @@ void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *elemen if (g_str_has_prefix(elementName, "queue2")) { // Disable on-disk buffering. - g_object_set(G_OBJECT(element), "temp-template", NULL, NULL); + g_object_set(G_OBJECT(element), "temp-template", nullptr, nullptr); } else if (g_str_has_prefix(elementName, "uridecodebin") || #if GST_CHECK_VERSION(1,0,0) g_str_has_prefix(elementName, "decodebin")) { @@ -1851,7 +1849,7 @@ void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *elemen g_str_has_prefix(elementName, "decodebin2")) { if (g_str_has_prefix(elementName, "uridecodebin")) { // Add video/x-surface (VAAPI) to default raw formats - g_object_set(G_OBJECT(element), "caps", gst_static_caps_get(&static_RawCaps), NULL); + g_object_set(G_OBJECT(element), "caps", gst_static_caps_get(&static_RawCaps), nullptr); // listen for uridecodebin autoplug-select to skip VAAPI usage when the current // video sink doesn't support it g_signal_connect(element, "autoplug-select", G_CALLBACK(handleAutoplugSelect), session); @@ -1894,7 +1892,7 @@ void QGstreamerPlayerSession::showPrerollFrames(bool enabled) g_object_class_find_property(G_OBJECT_GET_CLASS(m_videoSink), "show-preroll-frame") != 0) { gboolean value = enabled; - g_object_set(G_OBJECT(m_videoSink), "show-preroll-frame", value, NULL); + g_object_set(G_OBJECT(m_videoSink), "show-preroll-frame", value, nullptr); m_displayPrerolledFrame = enabled; } } diff --git a/src/gsttools/qgstreamervideooverlay.cpp b/src/gsttools/qgstreamervideooverlay.cpp index 6b862e475..d410be7d9 100644 --- a/src/gsttools/qgstreamervideooverlay.cpp +++ b/src/gsttools/qgstreamervideooverlay.cpp @@ -122,7 +122,7 @@ public: { int brightness = 0; if (m_hasBrightness) - g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL); + g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, nullptr); return brightness / 10; } @@ -131,7 +131,7 @@ public: { m_brightness = brightness; if (m_hasBrightness) - g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, NULL); + g_object_set(G_OBJECT(m_videoSink), "brightness", brightness * 10, nullptr); return m_hasBrightness; } @@ -140,7 +140,7 @@ public: { int contrast = 0; if (m_hasContrast) - g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL); + g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, nullptr); return contrast / 10; } @@ -149,7 +149,7 @@ public: { m_contrast = contrast; if (m_hasContrast) - g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, NULL); + g_object_set(G_OBJECT(m_videoSink), "contrast", contrast * 10, nullptr); return m_hasContrast; } @@ -158,7 +158,7 @@ public: { int hue = 0; if (m_hasHue) - g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL); + g_object_get(G_OBJECT(m_videoSink), "hue", &hue, nullptr); return hue / 10; } @@ -167,7 +167,7 @@ public: { m_hue = hue; if (m_hasHue) - g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, NULL); + g_object_set(G_OBJECT(m_videoSink), "hue", hue * 10, nullptr); return m_hasHue; } @@ -176,7 +176,7 @@ public: { int saturation = 0; if (m_hasSaturation) - g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL); + g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, nullptr); return saturation / 10; } @@ -185,7 +185,7 @@ public: { m_saturation = saturation; if (m_hasSaturation) - g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, NULL); + g_object_set(G_OBJECT(m_videoSink), "saturation", saturation * 10, nullptr); return m_hasSaturation; } @@ -195,7 +195,7 @@ public: Qt::AspectRatioMode mode = Qt::KeepAspectRatio; if (m_hasForceAspectRatio) { gboolean forceAR = false; - g_object_get(G_OBJECT(m_videoSink), "force-aspect-ratio", &forceAR, NULL); + g_object_get(G_OBJECT(m_videoSink), "force-aspect-ratio", &forceAR, nullptr); if (!forceAR) mode = Qt::IgnoreAspectRatio; } @@ -210,7 +210,7 @@ public: g_object_set(G_OBJECT(m_videoSink), "force-aspect-ratio", (mode == Qt::KeepAspectRatio), - (const char*)NULL); + nullptr); } } @@ -245,7 +245,7 @@ public: { gfloat brightness = 0; if (m_hasBrightness) - g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, NULL); + g_object_get(G_OBJECT(m_videoSink), "brightness", &brightness, nullptr); return brightness * 100; // [-1,1] -> [-100,100] } @@ -255,7 +255,7 @@ public: m_brightness = brightness; if (m_hasBrightness) { gfloat v = brightness / 100.0; // [-100,100] -> [-1,1] - g_object_set(G_OBJECT(m_videoSink), "brightness", v, NULL); + g_object_set(G_OBJECT(m_videoSink), "brightness", v, nullptr); } return m_hasBrightness; @@ -265,7 +265,7 @@ public: { gfloat contrast = 1; if (m_hasContrast) - g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, NULL); + g_object_get(G_OBJECT(m_videoSink), "contrast", &contrast, nullptr); return (contrast - 1) * 100; // [0,2] -> [-100,100] } @@ -275,7 +275,7 @@ public: m_contrast = contrast; if (m_hasContrast) { gfloat v = (contrast / 100.0) + 1; // [-100,100] -> [0,2] - g_object_set(G_OBJECT(m_videoSink), "contrast", v, NULL); + g_object_set(G_OBJECT(m_videoSink), "contrast", v, nullptr); } return m_hasContrast; @@ -285,7 +285,7 @@ public: { gfloat hue = 0; if (m_hasHue) - g_object_get(G_OBJECT(m_videoSink), "hue", &hue, NULL); + g_object_get(G_OBJECT(m_videoSink), "hue", &hue, nullptr); return hue / 180 * 100; // [-180,180] -> [-100,100] } @@ -295,7 +295,7 @@ public: m_hue = hue; if (m_hasHue) { gfloat v = hue / 100.0 * 180; // [-100,100] -> [-180,180] - g_object_set(G_OBJECT(m_videoSink), "hue", v, NULL); + g_object_set(G_OBJECT(m_videoSink), "hue", v, nullptr); } return m_hasHue; @@ -305,7 +305,7 @@ public: { gfloat saturation = 1; if (m_hasSaturation) - g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, NULL); + g_object_get(G_OBJECT(m_videoSink), "saturation", &saturation, nullptr); return (saturation - 1) * 100; // [0,2] -> [-100,100] } @@ -315,7 +315,7 @@ public: m_saturation = saturation; if (m_hasSaturation) { gfloat v = (saturation / 100.0) + 1; // [-100,100] -> [0,2] - g_object_set(G_OBJECT(m_videoSink), "saturation", v, NULL); + g_object_set(G_OBJECT(m_videoSink), "saturation", v, nullptr); } return m_hasSaturation; @@ -350,7 +350,7 @@ static GstElement *findBestVideoSink() continue; #endif if (platform == QLatin1String(elementMap[i].qtPlatform) - && (choice = gst_element_factory_make(elementMap[i].gstreamerElement, NULL))) { + && (choice = gst_element_factory_make(elementMap[i].gstreamerElement, nullptr))) { if (qt_gst_element_is_functioning(choice)) return choice; @@ -363,13 +363,13 @@ static GstElement *findBestVideoSink() // If none of the known video sinks are available, try to find one that implements the // GstVideoOverlay interface and has autoplugging rank. GList *list = qt_gst_video_sinks(); - for (GList *item = list; item != NULL; item = item->next) { + for (GList *item = list; item != nullptr; item = item->next) { GstElementFactory *f = GST_ELEMENT_FACTORY(item->data); if (!gst_element_factory_has_interface(f, QT_GSTREAMER_VIDEOOVERLAY_INTERFACE_NAME)) continue; - if (GstElement *el = gst_element_factory_create(f, NULL)) { + if (GstElement *el = gst_element_factory_create(f, nullptr)) { if (qt_gst_element_is_functioning(el)) { choice = el; break; @@ -390,7 +390,7 @@ QGstreamerVideoOverlay::QGstreamerVideoOverlay(QObject *parent, const QByteArray { GstElement *sink = nullptr; if (!elementName.isEmpty()) - sink = gst_element_factory_make(elementName.constData(), NULL); + sink = gst_element_factory_make(elementName.constData(), nullptr); else sink = findBestVideoSink(); @@ -567,7 +567,7 @@ void QGstreamerVideoOverlay::updateIsActive() gboolean showPreroll = true; if (m_sinkProperties->hasShowPrerollFrame()) - g_object_get(G_OBJECT(m_videoSink), "show-preroll-frame", &showPreroll, NULL); + g_object_get(G_OBJECT(m_videoSink), "show-preroll-frame", &showPreroll, nullptr); bool newIsActive = (state == GST_STATE_PLAYING || (state == GST_STATE_PAUSED && showPreroll)); diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index f8a9d79c1..f998c4309 100644 --- a/src/gsttools/qgstutils.cpp +++ b/src/gsttools/qgstutils.cpp @@ -424,7 +424,7 @@ GstCaps *QGstUtils::capsForAudioFormat(const QAudioFormat &format) "format" , G_TYPE_STRING, gst_audio_format_to_string(qt_audioLookup[i].format), "rate" , G_TYPE_INT , format.sampleRate(), "channels", G_TYPE_INT , format.channelCount(), - NULL); + nullptr); } return 0; #else @@ -432,29 +432,29 @@ GstCaps *QGstUtils::capsForAudioFormat(const QAudioFormat &format) if (format.isValid()) { if (format.sampleType() == QAudioFormat::SignedInt || format.sampleType() == QAudioFormat::UnSignedInt) { - structure = gst_structure_new("audio/x-raw-int", NULL); + structure = gst_structure_new("audio/x-raw-int", nullptr); } else if (format.sampleType() == QAudioFormat::Float) { - structure = gst_structure_new("audio/x-raw-float", NULL); + structure = gst_structure_new("audio/x-raw-float", nullptr); } } GstCaps *caps = 0; if (structure) { - gst_structure_set(structure, "rate", G_TYPE_INT, format.sampleRate(), NULL); - gst_structure_set(structure, "channels", G_TYPE_INT, format.channelCount(), NULL); - gst_structure_set(structure, "width", G_TYPE_INT, format.sampleSize(), NULL); - gst_structure_set(structure, "depth", G_TYPE_INT, format.sampleSize(), NULL); + gst_structure_set(structure, "rate", G_TYPE_INT, format.sampleRate(), nullptr); + gst_structure_set(structure, "channels", G_TYPE_INT, format.channelCount(), nullptr); + gst_structure_set(structure, "width", G_TYPE_INT, format.sampleSize(), nullptr); + gst_structure_set(structure, "depth", G_TYPE_INT, format.sampleSize(), nullptr); if (format.byteOrder() == QAudioFormat::LittleEndian) - gst_structure_set(structure, "endianness", G_TYPE_INT, 1234, NULL); + gst_structure_set(structure, "endianness", G_TYPE_INT, 1234, nullptr); else if (format.byteOrder() == QAudioFormat::BigEndian) - gst_structure_set(structure, "endianness", G_TYPE_INT, 4321, NULL); + gst_structure_set(structure, "endianness", G_TYPE_INT, 4321, nullptr); if (format.sampleType() == QAudioFormat::SignedInt) - gst_structure_set(structure, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + gst_structure_set(structure, "signed", G_TYPE_BOOLEAN, TRUE, nullptr); else if (format.sampleType() == QAudioFormat::UnSignedInt) - gst_structure_set(structure, "signed", G_TYPE_BOOLEAN, FALSE, NULL); + gst_structure_set(structure, "signed", G_TYPE_BOOLEAN, FALSE, nullptr); caps = gst_caps_new_empty(); Q_ASSERT(caps); @@ -470,7 +470,7 @@ void QGstUtils::initializeGst() static bool initialized = false; if (!initialized) { initialized = true; - gst_init(NULL, NULL); + gst_init(nullptr, nullptr); } } @@ -606,8 +606,8 @@ QVector<QGstUtils::CameraInfo> QGstUtils::enumerateCameras(GstElementFactory *fa // no-op } else for (int i = 0; i < 2; ++i) { gint orientation = 0; - g_object_set(G_OBJECT(camera), "camera-device", i, NULL); - g_object_get(G_OBJECT(camera), "sensor-mount-angle", &orientation, NULL); + g_object_set(G_OBJECT(camera), "camera-device", i, nullptr); + g_object_get(G_OBJECT(camera), "sensor-mount-angle", &orientation, nullptr); devices[i].orientation = (720 - orientation) % 360; } @@ -807,7 +807,7 @@ QSet<QString> QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac QSet<QString> supportedMimeTypes; //enumerate supported mime types - gst_init(NULL, NULL); + gst_init(nullptr, nullptr); #if GST_CHECK_VERSION(1,0,0) GstRegistry *registry = gst_registry_get(); @@ -829,7 +829,7 @@ QSet<QString> QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac GList *orig_features = gst_registry_get_feature_list_by_plugin( registry, gst_plugin_get_name(plugin)); for (GList *features = orig_features; features; features = g_list_next(features)) { - if (G_UNLIKELY(features->data == NULL)) + if (G_UNLIKELY(features->data == nullptr)) continue; GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data); @@ -1238,7 +1238,7 @@ GstCaps *QGstUtils::capsForFormats(const QList<QVideoFrame::PixelFormat> &format gst_caps_append_structure(caps, gst_structure_new( "video/x-raw", "format" , G_TYPE_STRING, gst_video_format_to_string(qt_videoFormatLookup[index].gstFormat), - NULL)); + nullptr)); } } #else @@ -1249,7 +1249,7 @@ GstCaps *QGstUtils::capsForFormats(const QList<QVideoFrame::PixelFormat> &format gst_caps_append_structure(caps, gst_structure_new( "video/x-raw-yuv", "format", GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc, - NULL)); + nullptr)); continue; } @@ -1265,11 +1265,11 @@ GstCaps *QGstUtils::capsForFormats(const QList<QVideoFrame::PixelFormat> &format "red_mask" , G_TYPE_INT, qt_rgbColorLookup[i].red, "green_mask", G_TYPE_INT, qt_rgbColorLookup[i].green, "blue_mask" , G_TYPE_INT, qt_rgbColorLookup[i].blue, - NULL); + nullptr); if (qt_rgbColorLookup[i].alpha != 0) { gst_structure_set( - structure, "alpha_mask", G_TYPE_INT, qt_rgbColorLookup[i].alpha, NULL); + structure, "alpha_mask", G_TYPE_INT, qt_rgbColorLookup[i].alpha, nullptr); } gst_caps_append_structure(caps, structure); } @@ -1282,7 +1282,7 @@ GstCaps *QGstUtils::capsForFormats(const QList<QVideoFrame::PixelFormat> &format "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1, "width" , GST_TYPE_INT_RANGE, 1, INT_MAX, "height" , GST_TYPE_INT_RANGE, 1, INT_MAX, - NULL); + nullptr); return caps; } @@ -1317,7 +1317,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap<QByteArray, QVariant GST_TAG_MERGE_REPLACE, tagName.toUtf8().constData(), tagValue.toString().toUtf8().constData(), - NULL); + nullptr); break; case QVariant::Int: case QVariant::LongLong: @@ -1325,14 +1325,14 @@ void QGstUtils::setMetaData(GstElement *element, const QMap<QByteArray, QVariant GST_TAG_MERGE_REPLACE, tagName.toUtf8().constData(), tagValue.toInt(), - NULL); + nullptr); break; case QVariant::Double: gst_tag_setter_add_tags(GST_TAG_SETTER(element), GST_TAG_MERGE_REPLACE, tagName.toUtf8().constData(), tagValue.toDouble(), - NULL); + nullptr); break; #if GST_CHECK_VERSION(0, 10, 31) case QVariant::DateTime: { @@ -1343,7 +1343,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap<QByteArray, QVariant gst_date_time_new_local_time( date.date().year(), date.date().month(), date.date().day(), date.time().hour(), date.time().minute(), date.time().second()), - NULL); + nullptr); break; } #endif @@ -1604,7 +1604,7 @@ GstCaps *qt_gst_pad_get_current_caps(GstPad *pad) GstCaps *qt_gst_pad_get_caps(GstPad *pad) { #if GST_CHECK_VERSION(1,0,0) - return gst_pad_query_caps(pad, NULL); + return gst_pad_query_caps(pad, nullptr); #elif GST_CHECK_VERSION(0, 10, 26) return gst_pad_get_caps_reffed(pad); #else @@ -1617,7 +1617,7 @@ GstStructure *qt_gst_structure_new_empty(const char *name) #if GST_CHECK_VERSION(1,0,0) return gst_structure_new_empty(name); #else - return gst_structure_new(name, NULL); + return gst_structure_new(name, nullptr); #endif } @@ -1709,7 +1709,7 @@ static gint qt_gst_compare_ranks(GstPluginFeature *f1, GstPluginFeature *f2) GList *qt_gst_video_sinks() { - GList *list = NULL; + GList *list = nullptr; #if GST_CHECK_VERSION(0, 10, 31) list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, @@ -1717,7 +1717,7 @@ GList *qt_gst_video_sinks() #else list = gst_registry_feature_filter(gst_registry_get_default(), (GstPluginFeatureFilter)qt_gst_videosink_factory_filter, - FALSE, NULL); + FALSE, nullptr); list = g_list_sort(list, (GCompareFunc)qt_gst_compare_ranks); #endif diff --git a/src/gsttools/qgstvideorenderersink.cpp b/src/gsttools/qgstvideorenderersink.cpp index 3b458a978..9eb2531a1 100644 --- a/src/gsttools/qgstvideorenderersink.cpp +++ b/src/gsttools/qgstvideorenderersink.cpp @@ -170,8 +170,8 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate(QAbstractVideoSurface *surfac { const auto instances = rendererLoader()->instances(QGstVideoRendererPluginKey); for (QObject *instance : instances) { - QGstVideoRendererInterface* plugin = qobject_cast<QGstVideoRendererInterface*>(instance); - if (QGstVideoRenderer *renderer = plugin ? plugin->createRenderer() : 0) + auto plugin = qobject_cast<QGstVideoRendererInterface*>(instance); + if (QGstVideoRenderer *renderer = plugin ? plugin->createRenderer() : nullptr) m_renderers.append(renderer); } @@ -304,7 +304,7 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) #if QT_CONFIG(gstreamer_gl) static GstGLContext *gstGLDisplayContext(QAbstractVideoSurface *surface) { - QOpenGLContext *glContext = qobject_cast<QOpenGLContext*>(surface->property("GLContext").value<QObject*>()); + auto glContext = qobject_cast<QOpenGLContext*>(surface->property("GLContext").value<QObject*>()); // Context is not ready yet. if (!glContext) return nullptr; @@ -360,7 +360,7 @@ static GstGLContext *gstGLDisplayContext(QAbstractVideoSurface *surface) qWarning() << "Could not create wrappped context for platform:" << glPlatform; GstGLContext *displayContext = nullptr; - GError *error = NULL; + GError *error = nullptr; gst_gl_display_create_context(display, appContext, &displayContext, &error); if (error) { qWarning() << "Could not create display context:" << error->message; @@ -393,14 +393,14 @@ bool QVideoSurfaceGstDelegate::query(GstQuery *query) if (!m_gstGLDisplayContext) return false; - GstContext *context = NULL; + GstContext *context = nullptr; gst_query_parse_context(query, &context); context = context ? gst_context_copy(context) : gst_context_new(type, FALSE); GstStructure *structure = gst_context_writable_structure(context); #if GST_CHECK_VERSION(1,11,1) - gst_structure_set(structure, "context", GST_TYPE_GL_CONTEXT, m_gstGLDisplayContext, NULL); + gst_structure_set(structure, "context", GST_TYPE_GL_CONTEXT, m_gstGLDisplayContext, nullptr); #else - gst_structure_set(structure, "context", GST_GL_TYPE_CONTEXT, m_gstGLDisplayContext, NULL); + gst_structure_set(structure, "context", GST_GL_TYPE_CONTEXT, m_gstGLDisplayContext, nullptr); #endif gst_query_set_context(query, context); gst_context_unref(context); @@ -583,10 +583,10 @@ GType QGstVideoRendererSink::get_type() { sizeof(QGstVideoRendererSinkClass), // class_size base_init, // base_init - NULL, // base_finalize + nullptr, // base_finalize class_init, // class_init - NULL, // class_finalize - NULL, // class_data + nullptr, // class_finalize + nullptr, // class_data sizeof(QGstVideoRendererSink), // instance_size 0, // n_preallocs instance_init, // instance_init @@ -694,12 +694,12 @@ void QGstVideoRendererSink::handleShowPrerollChange(GObject *o, GParamSpec *p, g QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(d); gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default - g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL); + g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, nullptr); if (!showPrerollFrame) { GstState state = GST_STATE_VOID_PENDING; GstClockTime timeout = 10000000; // 10 ms - gst_element_get_state(GST_ELEMENT(sink), &state, NULL, timeout); + gst_element_get_state(GST_ELEMENT(sink), &state, nullptr, timeout); // show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means // the QMediaPlayer was stopped from the paused state. // We need to flush the current frame. @@ -714,7 +714,7 @@ GstStateChangeReturn QGstVideoRendererSink::change_state( QGstVideoRendererSink *sink = reinterpret_cast<QGstVideoRendererSink *>(element); gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default - g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, NULL); + g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, nullptr); // If show-preroll-frame is 'false' when transitioning from GST_STATE_PLAYING to // GST_STATE_PAUSED, it means the QMediaPlayer was stopped. diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp index c63eea9a6..c6951bdef 100644 --- a/src/gsttools/qvideosurfacegstsink.cpp +++ b/src/gsttools/qvideosurfacegstsink.cpp @@ -69,7 +69,7 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate( if (m_surface) { const auto instances = bufferPoolLoader()->instances(QGstBufferPoolPluginKey); for (QObject *instance : instances) { - QGstBufferPoolInterface* plugin = qobject_cast<QGstBufferPoolInterface*>(instance); + auto plugin = qobject_cast<QGstBufferPoolInterface*>(instance); if (plugin) { m_pools.append(plugin); @@ -356,10 +356,10 @@ GType QVideoSurfaceGstSink::get_type() { sizeof(QVideoSurfaceGstSinkClass), // class_size base_init, // base_init - NULL, // base_finalize + nullptr, // base_finalize class_init, // class_init - NULL, // class_finalize - NULL, // class_data + nullptr, // class_finalize + nullptr, // class_data sizeof(QVideoSurfaceGstSink), // instance_size 0, // n_preallocs instance_init, // instance_init @@ -460,11 +460,11 @@ void QVideoSurfaceGstSink::handleShowPrerollChange(GObject *o, GParamSpec *p, gp QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(d); gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default - g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL); + g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, nullptr); if (!showPrerollFrame) { GstState state = GST_STATE_VOID_PENDING; - gst_element_get_state(GST_ELEMENT(sink), &state, NULL, GST_CLOCK_TIME_NONE); + gst_element_get_state(GST_ELEMENT(sink), &state, nullptr, GST_CLOCK_TIME_NONE); // show-preroll-frame being set to 'false' while in GST_STATE_PAUSED means // the QMediaPlayer was stopped from the paused state. // We need to flush the current frame. @@ -478,7 +478,7 @@ GstStateChangeReturn QVideoSurfaceGstSink::change_state(GstElement *element, Gst QVideoSurfaceGstSink *sink = reinterpret_cast<QVideoSurfaceGstSink *>(element); gboolean showPrerollFrame = true; // "show-preroll-frame" property is true by default - g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, NULL); + g_object_get(G_OBJECT(element), "show-preroll-frame", &showPrerollFrame, nullptr); // If show-preroll-frame is 'false' when transitioning from GST_STATE_PLAYING to // GST_STATE_PAUSED, it means the QMediaPlayer was stopped. @@ -576,7 +576,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( if (!buffer) return GST_FLOW_ERROR; - *buffer = NULL; + *buffer = nullptr; if (!sink->delegate->pool()) return GST_FLOW_OK; @@ -694,7 +694,7 @@ GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer { VO_SINK(base); gboolean showPrerollFrame = true; - g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL); + g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, nullptr); if (showPrerollFrame) return sink->delegate->render(buffer); diff --git a/src/imports/multimedia/multimedia.cpp b/src/imports/multimedia/multimedia.cpp index 8aed83d33..6106bb45d 100644 --- a/src/imports/multimedia/multimedia.cpp +++ b/src/imports/multimedia/multimedia.cpp @@ -60,6 +60,7 @@ #include "qdeclarativecameraimageprocessing_p.h" #include "qdeclarativecameraviewfinder_p.h" #include "qdeclarativetorch_p.h" +#include <QAbstractVideoSurface> QML_DECLARE_TYPE(QSoundEffect) @@ -160,6 +161,10 @@ public: // 5.13 types qmlRegisterType<QDeclarativeVideoOutput, 13>(uri, 5, 13, "VideoOutput"); + // 5.15 types + qmlRegisterType<QDeclarativeVideoOutput, 15>(uri, 5, 15, "VideoOutput"); + qmlRegisterType<QAbstractVideoSurface>(); + // Auto-increment the import to stay in sync with ALL future QtQuick minor versions from 5.11 onward qmlRegisterModule(uri, 5, QT_VERSION_MINOR); } diff --git a/src/multimedia/doc/snippets/multimedia-snippets/video.cpp b/src/multimedia/doc/snippets/multimedia-snippets/video.cpp index 3c14f7009..46327e3d6 100644 --- a/src/multimedia/doc/snippets/multimedia-snippets/video.cpp +++ b/src/multimedia/doc/snippets/multimedia-snippets/video.cpp @@ -117,6 +117,7 @@ public: void VideoWidget(); void VideoWindowControl(); void VideoWidgetControl(); + void VideoSurface(); private: // Common naming @@ -163,6 +164,28 @@ void VideoExample::VideoWidget() //! [Setting surface in player] } +void VideoExample::VideoSurface() +{ + //! [Widget Surface] + QImage img = QImage("images/qt-logo.png").convertToFormat(QImage::Format_ARGB32); + QVideoSurfaceFormat format(img.size(), QVideoFrame::Format_ARGB32); + videoWidget = new QVideoWidget; + videoWidget->videoSurface()->start(format); + videoWidget->videoSurface()->present(img); + videoWidget->show(); + //! [Widget Surface] + + //! [GraphicsVideoItem Surface] + QGraphicsVideoItem *item = new QGraphicsVideoItem; + graphicsView->scene()->addItem(item); + graphicsView->show(); + QImage img = QImage("images/qt-logo.png").convertToFormat(QImage::Format_ARGB32); + QVideoSurfaceFormat format(img.size(), QVideoFrame::Format_ARGB32); + item->videoSurface()->start(format); + item->videoSurface()->present(img); + //! [GraphicsVideoItem Surface] +} + void VideoExample::VideoWidgetControl() { //! [Video widget control] diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp index 48db0335e..9b51bcddf 100644 --- a/src/multimedia/playback/qmediaplayer.cpp +++ b/src/multimedia/playback/qmediaplayer.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qmediaplayer.h" +#include "qvideosurfaces_p.h" #include "qvideosurfaceoutput_p.h" #include "qmediaobject_p.h" @@ -555,7 +556,7 @@ static QMediaService *playerService(QMediaPlayer::Flags flags) { QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider(); if (flags) { - QMediaServiceProviderHint::Features features = 0; + QMediaServiceProviderHint::Features features; if (flags & QMediaPlayer::LowLatency) features |= QMediaServiceProviderHint::LowLatencyPlayback; @@ -1168,6 +1169,24 @@ void QMediaPlayer::setVideoOutput(QAbstractVideoSurface *surface) } } +/*! + \since 5.15 + Sets multiple video surfaces as the video output of a media player. + This allows the media player to render video frames on different surfaces. + + All video surfaces must support at least one shared \c QVideoFrame::PixelFormat. + + If a video output has already been set on the media player the new surfaces + will replace it. + + \sa QAbstractVideoSurface::supportedPixelFormats +*/ + +void QMediaPlayer::setVideoOutput(const QVector<QAbstractVideoSurface *> &surfaces) +{ + setVideoOutput(new QVideoSurfaces(surfaces, this)); +} + /*! \reimp */ QMultimedia::AvailabilityStatus QMediaPlayer::availability() const { diff --git a/src/multimedia/playback/qmediaplayer.h b/src/multimedia/playback/qmediaplayer.h index 5d9a393e1..7ebed84da 100644 --- a/src/multimedia/playback/qmediaplayer.h +++ b/src/multimedia/playback/qmediaplayer.h @@ -131,6 +131,7 @@ public: void setVideoOutput(QVideoWidget *); void setVideoOutput(QGraphicsVideoItem *); void setVideoOutput(QAbstractVideoSurface *surface); + void setVideoOutput(const QVector<QAbstractVideoSurface *> &surfaces); QMediaContent media() const; const QIODevice *mediaStream() const; diff --git a/src/multimedia/qmediaserviceprovider.cpp b/src/multimedia/qmediaserviceprovider.cpp index d8ffe42ae..93b560d8c 100644 --- a/src/multimedia/qmediaserviceprovider.cpp +++ b/src/multimedia/qmediaserviceprovider.cpp @@ -56,7 +56,7 @@ class QMediaServiceProviderHintPrivate : public QSharedData { public: QMediaServiceProviderHintPrivate(QMediaServiceProviderHint::Type type) - :type(type), cameraPosition(QCamera::UnspecifiedPosition), features(nullptr) + : type(type) { } @@ -77,7 +77,7 @@ public: QMediaServiceProviderHint::Type type; QByteArray device; - QCamera::Position cameraPosition; + QCamera::Position cameraPosition = QCamera::UnspecifiedPosition; QString mimeType; QStringList codecs; QMediaServiceProviderHint::Features features; @@ -712,7 +712,7 @@ QMediaServiceProviderHint::Features QMediaServiceProvider::supportedFeatures(con { Q_UNUSED(service); - return QMediaServiceProviderHint::Features(nullptr); + return {}; } /*! diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp index 5e2d6df39..fd7b74075 100644 --- a/src/multimedia/video/qvideoframe.cpp +++ b/src/multimedia/video/qvideoframe.cpp @@ -39,7 +39,6 @@ #include "qvideoframe.h" -#include "qvideoframe_p.h" #include "qimagevideobuffer_p.h" #include "qmemoryvideobuffer_p.h" #include "qvideoframeconversionhelper_p.h" @@ -1112,11 +1111,12 @@ static void qInitConvertFuncsAsm() } /*! - \internal + Based on the pixel format converts current video frame to image. + \since 5.15 */ -QImage qt_imageFromVideoFrame(const QVideoFrame &f) +QImage QVideoFrame::image() const { - QVideoFrame &frame = const_cast<QVideoFrame&>(f); + QVideoFrame frame = *this; QImage result; if (!frame.isValid() || !frame.map(QAbstractVideoBuffer::ReadOnly)) diff --git a/src/multimedia/video/qvideoframe.h b/src/multimedia/video/qvideoframe.h index 8fcf47fc4..d043442a3 100644 --- a/src/multimedia/video/qvideoframe.h +++ b/src/multimedia/video/qvideoframe.h @@ -166,6 +166,8 @@ public: QVariant metaData(const QString &key) const; void setMetaData(const QString &key, const QVariant &value); + QImage image() const; + static PixelFormat pixelFormatFromImageFormat(QImage::Format format); static QImage::Format imageFormatFromPixelFormat(PixelFormat format); diff --git a/src/multimedia/video/qvideosurfaces.cpp b/src/multimedia/video/qvideosurfaces.cpp new file mode 100644 index 000000000..459a6675a --- /dev/null +++ b/src/multimedia/video/qvideosurfaces.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvideosurfaces_p.h" + +QT_BEGIN_NAMESPACE + +QVideoSurfaces::QVideoSurfaces(const QVector<QAbstractVideoSurface *> &s, QObject *parent) + : QAbstractVideoSurface(parent) + , m_surfaces(s) +{ +} + +QVideoSurfaces::~QVideoSurfaces() +{ +} + +QList<QVideoFrame::PixelFormat> QVideoSurfaces::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const +{ + QList<QVideoFrame::PixelFormat> result; + QMap<QVideoFrame::PixelFormat, int> formats; + for (auto &s : m_surfaces) { + for (auto &p : s->supportedPixelFormats(type)) { + if (++formats[p] == m_surfaces.size()) + result << p; + } + } + + return result; +} + +bool QVideoSurfaces::start(const QVideoSurfaceFormat &format) +{ + bool result = true; + for (auto &s : m_surfaces) + result &= s->start(format); + + return result && QAbstractVideoSurface::start(format); +} + +void QVideoSurfaces::stop() +{ + for (auto &s : m_surfaces) + s->stop(); + + QAbstractVideoSurface::stop(); +} + +bool QVideoSurfaces::present(const QVideoFrame &frame) +{ + bool result = true; + for (auto &s : m_surfaces) + result &= s->present(frame); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/multimedia/video/qvideoframe_p.h b/src/multimedia/video/qvideosurfaces_p.h index d7b9dd348..67831e74e 100644 --- a/src/multimedia/video/qvideoframe_p.h +++ b/src/multimedia/video/qvideosurfaces_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Toolkit. @@ -37,10 +37,8 @@ ** ****************************************************************************/ -#ifndef QVIDEOFRAME_P_H -#define QVIDEOFRAME_P_H - -#include <QtMultimedia/qvideoframe.h> +#ifndef QVIDEOSURFACES_P_H +#define QVIDEOSURFACES_P_H // // W A R N I N G @@ -53,11 +51,27 @@ // We mean it. // +#include <QAbstractVideoSurface> +#include <QVector> + QT_BEGIN_NAMESPACE -Q_MULTIMEDIA_EXPORT QImage qt_imageFromVideoFrame(const QVideoFrame &frame); +class QVideoSurfaces : public QAbstractVideoSurface +{ +public: + QVideoSurfaces(const QVector<QAbstractVideoSurface *> &surfaces, QObject *parent = nullptr); + ~QVideoSurfaces(); -QT_END_NAMESPACE + QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const override; + bool start(const QVideoSurfaceFormat &format) override; + void stop() override; + bool present(const QVideoFrame &frame) override; -#endif // QVIDEOFRAME_P_H +private: + QVector<QAbstractVideoSurface *> m_surfaces; + Q_DISABLE_COPY(QVideoSurfaces) +}; + +QT_END_NAMESPACE +#endif // QVIDEOSURFACES_P_H diff --git a/src/multimedia/video/video.pri b/src/multimedia/video/video.pri index e5fa697ce..a3668ba4a 100644 --- a/src/multimedia/video/video.pri +++ b/src/multimedia/video/video.pri @@ -15,8 +15,8 @@ PRIVATE_HEADERS += \ video/qmemoryvideobuffer_p.h \ video/qvideooutputorientationhandler_p.h \ video/qvideosurfaceoutput_p.h \ - video/qvideoframe_p.h \ - video/qvideoframeconversionhelper_p.h + video/qvideoframeconversionhelper_p.h \ + video/qvideosurfaces_p.h SOURCES += \ video/qabstractvideobuffer.cpp \ @@ -29,7 +29,8 @@ SOURCES += \ video/qvideosurfaceoutput.cpp \ video/qvideoprobe.cpp \ video/qabstractvideofilter.cpp \ - video/qvideoframeconversionhelper.cpp + video/qvideoframeconversionhelper.cpp \ + video/qvideosurfaces.cpp SSE2_SOURCES += video/qvideoframeconversionhelper_sse2.cpp SSSE3_SOURCES += video/qvideoframeconversionhelper_ssse3.cpp diff --git a/src/multimediawidgets/qgraphicsvideoitem.cpp b/src/multimediawidgets/qgraphicsvideoitem.cpp index 2db8987fb..fae1f9048 100644 --- a/src/multimediawidgets/qgraphicsvideoitem.cpp +++ b/src/multimediawidgets/qgraphicsvideoitem.cpp @@ -232,6 +232,22 @@ QMediaObject *QGraphicsVideoItem::mediaObject() const } /*! + \since 5.15 + \property QGraphicsVideoItem::videoSurface + \brief Returns the underlying video surface that can render video frames + to the current item. + This property is never \c nullptr. + Example of how to render video frames to QGraphicsVideoItem: + \snippet multimedia-snippets/video.cpp GraphicsVideoItem Surface + \sa QMediaPlayer::setVideoOutput +*/ + +QAbstractVideoSurface *QGraphicsVideoItem::videoSurface() const +{ + return d_func()->surface; +} + +/*! \internal */ bool QGraphicsVideoItem::setMediaObject(QMediaObject *object) diff --git a/src/multimediawidgets/qgraphicsvideoitem.h b/src/multimediawidgets/qgraphicsvideoitem.h index 5aa3bd75c..de73458fd 100644 --- a/src/multimediawidgets/qgraphicsvideoitem.h +++ b/src/multimediawidgets/qgraphicsvideoitem.h @@ -60,11 +60,13 @@ class Q_MULTIMEDIAWIDGETS_EXPORT QGraphicsVideoItem : public QGraphicsObject, pu Q_PROPERTY(QPointF offset READ offset WRITE setOffset) Q_PROPERTY(QSizeF size READ size WRITE setSize) Q_PROPERTY(QSizeF nativeSize READ nativeSize NOTIFY nativeSizeChanged) + Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface) public: explicit QGraphicsVideoItem(QGraphicsItem *parent = nullptr); ~QGraphicsVideoItem(); QMediaObject *mediaObject() const override; + QAbstractVideoSurface *videoSurface() const; Qt::AspectRatioMode aspectRatioMode() const; void setAspectRatioMode(Qt::AspectRatioMode mode); diff --git a/src/multimediawidgets/qpaintervideosurface.cpp b/src/multimediawidgets/qpaintervideosurface.cpp index 944ea23a7..1c8e2dd63 100644 --- a/src/multimediawidgets/qpaintervideosurface.cpp +++ b/src/multimediawidgets/qpaintervideosurface.cpp @@ -1473,29 +1473,28 @@ void QPainterVideoSurface::stop() bool QPainterVideoSurface::present(const QVideoFrame &frame) { if (!m_ready) { - if (!isActive()) + if (!isActive()) { setError(StoppedError); + return false; + } } else if (frame.isValid() && (frame.pixelFormat() != m_pixelFormat || frame.size() != m_frameSize)) { setError(IncorrectFormatError); stop(); + return false; } else { QAbstractVideoSurface::Error error = m_painter->setCurrentFrame(frame); - if (error != QAbstractVideoSurface::NoError) { setError(error); - stop(); - } else { - m_ready = false; - - emit frameChanged(); - - return true; + return false; } + + m_ready = false; + emit frameChanged(); } - return false; + return true; } /*! diff --git a/src/multimediawidgets/qvideowidget.cpp b/src/multimediawidgets/qvideowidget.cpp index a7d3665f8..723a9bbb3 100644 --- a/src/multimediawidgets/qvideowidget.cpp +++ b/src/multimediawidgets/qvideowidget.cpp @@ -145,7 +145,8 @@ QRendererVideoWidgetBackend::QRendererVideoWidgetBackend( connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)), this, SLOT(formatChanged(QVideoSurfaceFormat))); - m_rendererControl->setSurface(m_surface); + if (m_rendererControl) + m_rendererControl->setSurface(m_surface); } QRendererVideoWidgetBackend::~QRendererVideoWidgetBackend() @@ -153,14 +154,21 @@ QRendererVideoWidgetBackend::~QRendererVideoWidgetBackend() delete m_surface; } +QAbstractVideoSurface *QRendererVideoWidgetBackend::videoSurface() const +{ + return m_surface; +} + void QRendererVideoWidgetBackend::releaseControl() { - m_service->releaseControl(m_rendererControl); + if (m_service && m_rendererControl) + m_service->releaseControl(m_rendererControl); } void QRendererVideoWidgetBackend::clearSurface() { - m_rendererControl->setSurface(0); + if (m_rendererControl) + m_rendererControl->setSurface(0); } void QRendererVideoWidgetBackend::setBrightness(int brightness) @@ -469,7 +477,7 @@ void QVideoWidgetPrivate::clearService() delete rendererBackend; rendererBackend = 0; - } else { + } else if (windowBackend) { windowBackend->releaseControl(); delete windowBackend; @@ -515,18 +523,15 @@ bool QVideoWidgetPrivate::createWindowBackend() bool QVideoWidgetPrivate::createRendererBackend() { - if (QMediaControl *control = service->requestControl(QVideoRendererControl_iid)) { - if (QVideoRendererControl *rendererControl = qobject_cast<QVideoRendererControl *>(control)) { - rendererBackend = new QRendererVideoWidgetBackend(service, rendererControl, q_func()); - currentBackend = rendererBackend; - - setCurrentControl(rendererBackend); + QMediaControl *control = service + ? service->requestControl(QVideoRendererControl_iid) + : nullptr; + rendererBackend = new QRendererVideoWidgetBackend(service, + qobject_cast<QVideoRendererControl *>(control), q_func()); + currentBackend = rendererBackend; + setCurrentControl(rendererBackend); - return true; - } - service->releaseControl(control); - } - return false; + return !service || (service && control); } void QVideoWidgetPrivate::_q_serviceDestroyed() @@ -611,7 +616,7 @@ void QVideoWidgetPrivate::_q_dimensionsChanged() The \a parent is passed to QWidget. */ QVideoWidget::QVideoWidget(QWidget *parent) - : QWidget(parent, 0) + : QWidget(parent, {}) , d_ptr(new QVideoWidgetPrivate) { d_ptr->q_ptr = this; @@ -621,7 +626,7 @@ QVideoWidget::QVideoWidget(QWidget *parent) \internal */ QVideoWidget::QVideoWidget(QVideoWidgetPrivate &dd, QWidget *parent) - : QWidget(parent, 0) + : QWidget(parent, {}) , d_ptr(&dd) { d_ptr->q_ptr = this; @@ -696,6 +701,29 @@ bool QVideoWidget::setMediaObject(QMediaObject *object) } /*! + \since 5.15 + \property QVideoWidget::videoSurface + \brief Returns the underlaying video surface that can render video frames + to the current widget. + This property is never \c nullptr. + Example of how to render video frames to QVideoWidget: + \snippet multimedia-snippets/video.cpp Widget Surface + \sa QMediaPlayer::setVideoOutput +*/ + +QAbstractVideoSurface *QVideoWidget::videoSurface() const +{ + auto d = const_cast<QVideoWidgetPrivate *>(d_func()); + + if (!d->rendererBackend) { + d->clearService(); + d->createRendererBackend(); + } + + return d->rendererBackend->videoSurface(); +} + +/*! \property QVideoWidget::aspectRatioMode \brief how video is scaled with respect to its aspect ratio. */ diff --git a/src/multimediawidgets/qvideowidget.h b/src/multimediawidgets/qvideowidget.h index fff1153ca..c5abe2ce3 100644 --- a/src/multimediawidgets/qvideowidget.h +++ b/src/multimediawidgets/qvideowidget.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE class QMediaObject; class QVideoWidgetPrivate; +class QAbstractVideoSurface; class Q_MULTIMEDIAWIDGETS_EXPORT QVideoWidget : public QWidget, public QMediaBindableInterface { Q_OBJECT @@ -62,12 +63,14 @@ class Q_MULTIMEDIAWIDGETS_EXPORT QVideoWidget : public QWidget, public QMediaBin Q_PROPERTY(int contrast READ contrast WRITE setContrast NOTIFY contrastChanged) Q_PROPERTY(int hue READ hue WRITE setHue NOTIFY hueChanged) Q_PROPERTY(int saturation READ saturation WRITE setSaturation NOTIFY saturationChanged) + Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface) public: explicit QVideoWidget(QWidget *parent = nullptr); ~QVideoWidget(); QMediaObject *mediaObject() const override; + QAbstractVideoSurface *videoSurface() const; #ifdef Q_QDOC bool isFullScreen() const; diff --git a/src/multimediawidgets/qvideowidget_p.h b/src/multimediawidgets/qvideowidget_p.h index ef417b222..1db91f3f9 100644 --- a/src/multimediawidgets/qvideowidget_p.h +++ b/src/multimediawidgets/qvideowidget_p.h @@ -131,6 +131,8 @@ public: QRendererVideoWidgetBackend(QMediaService *service, QVideoRendererControl *control, QWidget *widget); ~QRendererVideoWidgetBackend(); + QAbstractVideoSurface *videoSurface() const; + void releaseControl(); void clearSurface(); @@ -222,40 +224,21 @@ class QVideoWidgetPrivate { Q_DECLARE_PUBLIC(QVideoWidget) public: - QVideoWidgetPrivate() - : q_ptr(0) - , mediaObject(0) - , service(0) - , widgetBackend(0) - , windowBackend(0) - , rendererBackend(0) - , currentControl(0) - , currentBackend(0) - , brightness(0) - , contrast(0) - , hue(0) - , saturation(0) - , aspectRatioMode(Qt::KeepAspectRatio) - , nonFullScreenFlags(0) - , wasFullScreen(false) - { - } - - QVideoWidget *q_ptr; + QVideoWidget *q_ptr = nullptr; QPointer<QMediaObject> mediaObject; - QMediaService *service; - QVideoWidgetControlBackend *widgetBackend; - QWindowVideoWidgetBackend *windowBackend; - QRendererVideoWidgetBackend *rendererBackend; - QVideoWidgetControlInterface *currentControl; - QVideoWidgetBackend *currentBackend; - int brightness; - int contrast; - int hue; - int saturation; - Qt::AspectRatioMode aspectRatioMode; + QMediaService *service = nullptr; + QVideoWidgetControlBackend *widgetBackend = nullptr; + QWindowVideoWidgetBackend *windowBackend = nullptr; + QRendererVideoWidgetBackend *rendererBackend = nullptr; + QVideoWidgetControlInterface *currentControl = nullptr; + QVideoWidgetBackend *currentBackend = nullptr; + int brightness = 0; + int contrast = 0; + int hue = 0; + int saturation = 0; + Qt::AspectRatioMode aspectRatioMode = Qt::KeepAspectRatio; Qt::WindowFlags nonFullScreenFlags; - bool wasFullScreen; + bool wasFullScreen = false; bool createWidgetBackend(); bool createWindowBackend(); diff --git a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp index f3ad84836..a0f809376 100644 --- a/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp +++ b/src/plugins/android/src/mediacapture/qandroidcamerasession.cpp @@ -53,7 +53,6 @@ #include <qdebug.h> #include <qvideoframe.h> #include <private/qmemoryvideobuffer_p.h> -#include <private/qvideoframe_p.h> #include <QtCore/private/qjnihelpers_p.h> QT_BEGIN_NAMESPACE @@ -749,7 +748,7 @@ void QAndroidCameraSession::processPreviewImage(int id, const QVideoFrame &frame transform.scale(-1, 1); transform.rotate(rotation); - emit imageCaptured(id, qt_imageFromVideoFrame(frame).transformed(transform)); + emit imageCaptured(id, frame.image().transformed(transform)); } void QAndroidCameraSession::onNewPreviewFrame(const QVideoFrame &frame) diff --git a/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm b/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm index dbaf3ed41..55a20b1bd 100644 --- a/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm +++ b/src/plugins/avfoundation/camera/avfimagecapturecontrol.mm @@ -48,7 +48,6 @@ #include <QtCore/qbuffer.h> #include <QtConcurrent/qtconcurrentrun.h> #include <QtGui/qimagereader.h> -#include <private/qvideoframe_p.h> QT_USE_NAMESPACE @@ -214,7 +213,7 @@ void AVFImageCaptureControl::makeCapturePreview(CaptureRequest request, QTransform transform; transform.rotate(rotation); - Q_EMIT imageCaptured(request.captureId, qt_imageFromVideoFrame(frame).transformed(transform)); + Q_EMIT imageCaptured(request.captureId, frame.image().transformed(transform)); request.previewReady->release(); } diff --git a/src/plugins/directshow/camera/dscamerasession.cpp b/src/plugins/directshow/camera/dscamerasession.cpp index a0c120816..cee3e9c56 100644 --- a/src/plugins/directshow/camera/dscamerasession.cpp +++ b/src/plugins/directshow/camera/dscamerasession.cpp @@ -44,7 +44,6 @@ #include <QtMultimedia/qvideosurfaceformat.h> #include <QtMultimedia/qcameraimagecapture.h> #include <private/qmemoryvideobuffer_p.h> -#include <private/qvideoframe_p.h> #include "dscamerasession.h" #include "dsvideorenderer.h" @@ -637,7 +636,7 @@ void DSCameraSession::presentFrame() if (m_capturedFrame.isValid()) { - captureImage = qt_imageFromVideoFrame(m_capturedFrame); + captureImage = m_capturedFrame.image(); const bool needsVerticalMirroring = m_previewSurfaceFormat.scanLineDirection() != QVideoSurfaceFormat::TopToBottom; captureImage = captureImage.mirrored(m_needsHorizontalMirroring, needsVerticalMirroring); // also causes a deep copy of the data diff --git a/src/plugins/gstreamer/camerabin/camerabinzoom.cpp b/src/plugins/gstreamer/camerabin/camerabinzoom.cpp index bb3659493..401e13207 100644 --- a/src/plugins/gstreamer/camerabin/camerabinzoom.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinzoom.cpp @@ -51,7 +51,9 @@ CameraBinZoom::CameraBinZoom(CameraBinSession *session) , m_requestedOpticalZoom(1.0) , m_requestedDigitalZoom(1.0) { - + GstElement *camerabin = m_session->cameraBin(); + g_signal_connect(G_OBJECT(camerabin), "notify::zoom", G_CALLBACK(updateZoom), this); + g_signal_connect(G_OBJECT(camerabin), "notify::max-zoom", G_CALLBACK(updateMaxZoom), this); } CameraBinZoom::~CameraBinZoom() @@ -114,4 +116,32 @@ void CameraBinZoom::zoomTo(qreal optical, qreal digital) emit currentDigitalZoomChanged(digital); } +void CameraBinZoom::updateZoom(GObject *o, GParamSpec *p, gpointer d) +{ + Q_UNUSED(p); + + gfloat zoomFactor = 1.0; + g_object_get(o, ZOOM_PROPERTY, &zoomFactor, NULL); + + CameraBinZoom *zoom = reinterpret_cast<CameraBinZoom *>(d); + + QMetaObject::invokeMethod(zoom, "currentDigitalZoomChanged", + Qt::QueuedConnection, + Q_ARG(qreal, zoomFactor)); +} + +void CameraBinZoom::updateMaxZoom(GObject *o, GParamSpec *p, gpointer d) +{ + Q_UNUSED(p); + + gfloat zoomFactor = 1.0; + g_object_get(o, MAX_ZOOM_PROPERTY, &zoomFactor, NULL); + + CameraBinZoom *zoom = reinterpret_cast<CameraBinZoom *>(d); + + QMetaObject::invokeMethod(zoom, "maximumDigitalZoomChanged", + Qt::QueuedConnection, + Q_ARG(qreal, zoomFactor)); +} + QT_END_NAMESPACE diff --git a/src/plugins/gstreamer/camerabin/camerabinzoom.h b/src/plugins/gstreamer/camerabin/camerabinzoom.h index 8ad4764b2..858ada2da 100644 --- a/src/plugins/gstreamer/camerabin/camerabinzoom.h +++ b/src/plugins/gstreamer/camerabin/camerabinzoom.h @@ -41,6 +41,7 @@ #define CAMERABINZOOMCONTROL_H #include <qcamerazoomcontrol.h> +#include <gst/gst.h> QT_BEGIN_NAMESPACE @@ -64,6 +65,9 @@ public: void zoomTo(qreal optical, qreal digital) override; private: + static void updateZoom(GObject *o, GParamSpec *p, gpointer d); + static void updateMaxZoom(GObject *o, GParamSpec *p, gpointer d); + CameraBinSession *m_session; qreal m_requestedOpticalZoom; qreal m_requestedDigitalZoom; diff --git a/src/plugins/m3u/qm3uhandler.cpp b/src/plugins/m3u/qm3uhandler.cpp index 017c32d92..5e05994ef 100644 --- a/src/plugins/m3u/qm3uhandler.cpp +++ b/src/plugins/m3u/qm3uhandler.cpp @@ -163,7 +163,7 @@ public: virtual bool writeItem(const QMediaContent& item) { - *m_textStream << item.request().url().toString() << endl; + *m_textStream << item.request().url().toString() << Qt::endl; return true; } diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp index 32166502d..128d0a616 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp @@ -138,6 +138,7 @@ QDeclarativeVideoOutput::QDeclarativeVideoOutput(QQuickItem *parent) : { initResource(); setFlag(ItemHasContents, true); + m_backend.reset(new QDeclarativeVideoRendererBackend(this)); } QDeclarativeVideoOutput::~QDeclarativeVideoOutput() @@ -148,6 +149,22 @@ QDeclarativeVideoOutput::~QDeclarativeVideoOutput() } /*! + \qmlproperty object QtMultimedia::VideoOutput::videoSurface + \since 5.15 + + This property holds the underlaying video surface that can be used + to render the video frames to this VideoOutput element. + It is similar to setting a QObject with \c videoSurface property as a source, + where this video surface will be set. + \sa setSource +*/ + +QAbstractVideoSurface *QDeclarativeVideoOutput::videoSurface() const +{ + return m_backend->videoSurface(); +} + +/*! \qmlproperty variant QtMultimedia::VideoOutput::source This property holds the source item providing the video frames like MediaPlayer or Camera. @@ -251,7 +268,8 @@ bool QDeclarativeVideoOutput::createBackend(QMediaService *service) } #if QT_CONFIG(opengl) if (!backendAvailable) { - m_backend.reset(new QDeclarativeVideoRendererBackend(this)); + if (!m_backend) + m_backend.reset(new QDeclarativeVideoRendererBackend(this)); if (m_backend->init(service)) backendAvailable = true; } @@ -293,9 +311,6 @@ void QDeclarativeVideoOutput::_q_updateMediaObject() if (m_mediaObject.data() == mediaObject) return; - if (m_sourceType != VideoSurfaceSource) - m_backend.reset(); - m_mediaObject.clear(); m_service.clear(); diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h b/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h index 8ea0dc338..9e826d0ff 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_p.h @@ -67,6 +67,7 @@ class QMediaObject; class QMediaService; class QDeclarativeVideoBackend; class QVideoOutputOrientationHandler; +class QAbstractVideoSurface; class Q_MULTIMEDIAQUICK_EXPORT QDeclarativeVideoOutput : public QQuickItem { @@ -80,6 +81,7 @@ class Q_MULTIMEDIAQUICK_EXPORT QDeclarativeVideoOutput : public QQuickItem Q_PROPERTY(QRectF contentRect READ contentRect NOTIFY contentRectChanged) Q_PROPERTY(QQmlListProperty<QAbstractVideoFilter> filters READ filters); Q_PROPERTY(FlushMode flushMode READ flushMode WRITE setFlushMode NOTIFY flushModeChanged REVISION 13) + Q_PROPERTY(QAbstractVideoSurface* videoSurface READ videoSurface REVISION 15) Q_ENUMS(FlushMode) Q_ENUMS(FillMode) @@ -102,6 +104,8 @@ public: QDeclarativeVideoOutput(QQuickItem *parent = 0); ~QDeclarativeVideoOutput(); + QAbstractVideoSurface *videoSurface() const; + QObject *source() const { return m_source.data(); } void setSource(QObject *source); diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp index 863cefa4e..bdfa23dfb 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput_render.cpp @@ -46,7 +46,6 @@ #include <QtCore/qloggingcategory.h> #include <private/qmediapluginloader_p.h> #include <private/qsgvideonode_p.h> -#include <private/qvideoframe_p.h> #include <QtGui/QOpenGLContext> #include <QtQuick/QQuickWindow> @@ -304,7 +303,7 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode, if (!runnable) continue; - QVideoFilterRunnable::RunFlags flags = 0; + QVideoFilterRunnable::RunFlags flags; if (i == m_filters.count() - 1) flags |= QVideoFilterRunnable::LastInChain; @@ -363,7 +362,7 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode, videoNode->setTexturedRectGeometry(m_renderedRect, m_sourceTextureRect, qNormalizedOrientation(q->orientation())); if (m_frameChanged) { - QSGVideoNode::FrameFlags flags = 0; + QSGVideoNode::FrameFlags flags; if (isFrameModified) flags |= QSGVideoNode::FrameFiltered; videoNode->setCurrentFrame(m_frame, flags); @@ -372,7 +371,7 @@ QSGNode *QDeclarativeVideoRendererBackend::updatePaintNode(QSGNode *oldNode, || q->flushMode() == QDeclarativeVideoOutput::LastFrame) { m_frameOnFlush = m_surfaceFormat.handleType() == QAbstractVideoBuffer::NoHandle ? m_frame - : qt_imageFromVideoFrame(m_frame); + : m_frame.image(); } //don't keep the frame for more than really necessary diff --git a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp index 894486230..27fc014aa 100644 --- a/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp +++ b/tests/auto/integration/qcamerabackend/tst_qcamerabackend.cpp @@ -49,7 +49,6 @@ #include <qcameraimagecapture.h> #include <qvideorenderercontrol.h> #include <private/qmediaserviceprovider_p.h> -#include <private/qvideoframe_p.h> QT_USE_NAMESPACE @@ -451,7 +450,7 @@ void tst_QCameraBackend::testCaptureToBuffer() QCOMPARE(imageAvailableSignal.first().first().toInt(), id); QVideoFrame frame = imageAvailableSignal.first().last().value<QVideoFrame>(); - QVERIFY(!qt_imageFromVideoFrame(frame).isNull()); + QVERIFY(!frame.image().isNull()); frame = QVideoFrame(); capturedSignal.clear(); @@ -509,7 +508,7 @@ void tst_QCameraBackend::testCaptureToBuffer() QCOMPARE(imageAvailableSignal.first().first().toInt(), id); frame = imageAvailableSignal.first().last().value<QVideoFrame>(); - QVERIFY(!qt_imageFromVideoFrame(frame).isNull()); + QVERIFY(!frame.image().isNull()); QString fileName = savedSignal.first().last().toString(); QVERIFY(QFileInfo(fileName).exists()); diff --git a/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp b/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp index 798b63f96..27c7d85de 100644 --- a/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp +++ b/tests/auto/integration/qdeclarativevideooutput/tst_qdeclarativevideooutput.cpp @@ -32,6 +32,7 @@ #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> +#include <QQuickView> #include "private/qdeclarativevideooutput_p.h" @@ -109,6 +110,7 @@ private slots: void flushMode(); void orientation(); void surfaceSource(); + void paintSurface(); void sourceRect(); void contentRect(); @@ -349,6 +351,45 @@ void tst_QDeclarativeVideoOutput::surfaceSource() delete videoOutput2; } +static const uchar rgb32ImageData[] = +{// B G R A + 0x00, 0x01, 0x02, 0xff, 0x03, 0x04, 0x05, 0xff, + 0x06, 0x07, 0x08, 0xff, 0x09, 0x0a, 0x0b, 0xff +}; + +void tst_QDeclarativeVideoOutput::paintSurface() +{ + QQuickView window; + window.setSource(QUrl("qrc:/main.qml")); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + + auto videoOutput = qobject_cast<QDeclarativeVideoOutput *>(window.rootObject()); + QVERIFY(videoOutput); + + auto surface = videoOutput->property("videoSurface").value<QAbstractVideoSurface *>(); + QVERIFY(surface); + QVERIFY(!surface->isActive()); + videoOutput->setSize(QSize(2, 2)); + QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32); + QVERIFY(surface->isFormatSupported(format)); + QVERIFY(surface->start(format)); + QVERIFY(surface->isActive()); + + QImage img(rgb32ImageData, 2, 2, 8, QImage::Format_RGB32); + QVERIFY(surface->present(img)); + + if (QGuiApplication::platformName() == QLatin1String("offscreen") + || QGuiApplication::platformName() == QLatin1String("minimal")) + return; + + QImage capture = window.grabWindow(); + QCOMPARE(capture.pixelColor(0, 0), QColor(rgb32ImageData[2], rgb32ImageData[1], rgb32ImageData[0], rgb32ImageData[3])); + QCOMPARE(capture.pixelColor(1, 0), QColor(rgb32ImageData[6], rgb32ImageData[5], rgb32ImageData[4], rgb32ImageData[7])); + QCOMPARE(capture.pixelColor(0, 1), QColor(rgb32ImageData[10], rgb32ImageData[9], rgb32ImageData[8], rgb32ImageData[11])); + QCOMPARE(capture.pixelColor(1, 1), QColor(rgb32ImageData[14], rgb32ImageData[13], rgb32ImageData[12], rgb32ImageData[15])); +} + void tst_QDeclarativeVideoOutput::sourceRect() { QQmlComponent component(&m_engine); diff --git a/tests/auto/integration/qmediaplayerbackend/BLACKLIST b/tests/auto/integration/qmediaplayerbackend/BLACKLIST index c2833f1f7..e91f47755 100644 --- a/tests/auto/integration/qmediaplayerbackend/BLACKLIST +++ b/tests/auto/integration/qmediaplayerbackend/BLACKLIST @@ -5,6 +5,7 @@ windows-7 windows-7sp1 windows-10 msvc-2015 windows-10 msvc-2017 +windows-10 msvc-2019 # Media player plugin not built at the moment on this platform opensuse-13.1 64bit diff --git a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp index 9cd3b7fa9..f1be070e8 100644 --- a/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp +++ b/tests/auto/integration/qmediaplayerbackend/tst_qmediaplayerbackend.cpp @@ -78,6 +78,7 @@ private slots: void playlistObject(); void surfaceTest_data(); void surfaceTest(); + void multipleSurfaces(); void metadata(); void playerStateAtEOS(); @@ -1393,6 +1394,33 @@ void tst_QMediaPlayerBackend::surfaceTest() QVERIFY2(surface.m_totalFrames >= 25, qPrintable(QString("Expected >= 25, got %1").arg(surface.m_totalFrames))); } +void tst_QMediaPlayerBackend::multipleSurfaces() +{ + if (localVideoFile.isNull()) + QSKIP("No supported video file"); + + QList<QVideoFrame::PixelFormat> formats1; + formats1 << QVideoFrame::Format_RGB32 + << QVideoFrame::Format_ARGB32; + QList<QVideoFrame::PixelFormat> formats2; + formats2 << QVideoFrame::Format_YUV420P + << QVideoFrame::Format_RGB32; + + TestVideoSurface surface1(false); + surface1.setSupportedFormats(formats1); + TestVideoSurface surface2(false); + surface2.setSupportedFormats(formats2); + + QMediaPlayer player; + player.setVideoOutput(QVector<QAbstractVideoSurface *>() << &surface1 << &surface2); + player.setMedia(localVideoFile); + player.play(); + QTRY_VERIFY(player.position() >= 1000); + QVERIFY2(surface1.m_totalFrames >= 25, qPrintable(QString("Expected >= 25, got %1").arg(surface1.m_totalFrames))); + QVERIFY2(surface2.m_totalFrames >= 25, qPrintable(QString("Expected >= 25, got %1").arg(surface2.m_totalFrames))); + QCOMPARE(surface1.m_totalFrames, surface2.m_totalFrames); +} + void tst_QMediaPlayerBackend::metadata() { if (localFileWithMetadata.isNull()) diff --git a/tests/auto/unit/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp b/tests/auto/unit/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp index f4759bbf7..41805f49a 100644 --- a/tests/auto/unit/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp +++ b/tests/auto/unit/qgraphicsvideoitem/tst_qgraphicsvideoitem.cpp @@ -70,6 +70,7 @@ private slots: void boundingRect(); void paint(); + void paintSurface(); }; Q_DECLARE_METATYPE(const uchar *) @@ -656,6 +657,48 @@ void tst_QGraphicsVideoItem::paint() QCOMPARE(surface->isReady(), true); } +void tst_QGraphicsVideoItem::paintSurface() +{ + QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem; + QVERIFY(item->videoSurface()); + + QGraphicsScene graphicsScene; + graphicsScene.addItem(item); + QGraphicsView graphicsView(&graphicsScene); + graphicsView.show(); + QVERIFY(item->waitForPaint(1)); + + QPainterVideoSurface *surface = qobject_cast<QPainterVideoSurface *>( + item->videoSurface()); + if (!surface) + QSKIP("QGraphicsVideoItem is not QPainterVideoSurface based"); + + QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32); + + QVERIFY(surface->start(format)); + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); + + QVERIFY(item->waitForPaint(1)); + + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); + + QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32); + + frame.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes()); + frame.unmap(); + + QVERIFY(surface->present(frame)); + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), false); + + QVERIFY(item->waitForPaint(1)); + + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); +} QTEST_MAIN(tst_QGraphicsVideoItem) diff --git a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.cpp b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.cpp index 66ace2045..4167b18ea 100644 --- a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.cpp +++ b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin2/mockserviceplugin2.cpp @@ -75,10 +75,10 @@ public: QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const { + QMediaServiceProviderHint::Features result; if (service == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) - return QMediaServiceProviderHint::LowLatencyPlayback; - else - return 0; + result |= QMediaServiceProviderHint::LowLatencyPlayback; + return result; } }; diff --git a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.cpp b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.cpp index 92707169c..6a7725fee 100644 --- a/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.cpp +++ b/tests/auto/unit/qmediaserviceprovider/mockserviceplugin4/mockserviceplugin4.cpp @@ -75,10 +75,10 @@ public: QMediaServiceProviderHint::Features supportedFeatures(const QByteArray &service) const { + QMediaServiceProviderHint::Features result; if (service == QByteArray(Q_MEDIASERVICE_MEDIAPLAYER)) - return QMediaServiceProviderHint::StreamPlayback; - else - return 0; + result |= QMediaServiceProviderHint::StreamPlayback; + return result; } }; diff --git a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp index 7ba631e58..6aaeab855 100644 --- a/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp +++ b/tests/auto/unit/qpaintervideosurface/tst_qpaintervideosurface.cpp @@ -481,8 +481,7 @@ void tst_QPainterVideoSurface::present() QCOMPARE(surface.isActive(), true); QCOMPARE(surface.isReady(), false); - // Not ready. - QVERIFY(!surface.present(frameA)); + QVERIFY(surface.present(frameA)); QCOMPARE(frameSpy.count(), 1); surface.setReady(true); @@ -1093,8 +1092,9 @@ void tst_QPainterVideoSurface::shaderPresent() QCOMPARE(surface.isActive(), true); QCOMPARE(surface.isReady(), false); - // Not ready. - QVERIFY(!surface.present(frameA)); + // If present() fails for any other reason the surface should immediately enter the stopped state + // and an error() value will be set. + QVERIFY(surface.present(frameA)); QCOMPARE(frameSpy.count(), 1); surface.setReady(true); diff --git a/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp b/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp index 6be039108..943051435 100644 --- a/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp +++ b/tests/auto/unit/qvideoframe/tst_qvideoframe.cpp @@ -33,6 +33,7 @@ #include <qvideoframe.h> #include <QtGui/QImage> #include <QtCore/QPointer> +#include <QtMultimedia/private/qtmultimedia-config_p.h> // Adds an enum, and the stringized version #define ADD_ENUM_TEST(x) \ @@ -85,6 +86,9 @@ private slots: void isMapped(); void isReadable(); void isWritable(); + + void image_data(); + void image(); }; Q_DECLARE_METATYPE(QImage::Format) @@ -1128,6 +1132,173 @@ void tst_QVideoFrame::isWritable() frame.unmap(); } +void tst_QVideoFrame::image_data() +{ + QTest::addColumn<QSize>("size"); + QTest::addColumn<QVideoFrame::PixelFormat>("pixelFormat"); + QTest::addColumn<int>("bytes"); + QTest::addColumn<int>("bytesPerLine"); + QTest::addColumn<QImage::Format>("imageFormat"); + + QTest::newRow("64x64 ARGB32") + << QSize(64, 64) + << QVideoFrame::Format_ARGB32 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 ARGB32_Premultiplied") + << QSize(64, 64) + << QVideoFrame::Format_ARGB32_Premultiplied + << 16384 + << 256 + << QImage::Format_ARGB32_Premultiplied; + + QTest::newRow("64x64 RGB32") + << QSize(64, 64) + << QVideoFrame::Format_RGB32 + << 16384 + << 256 + << QImage::Format_RGB32; + + QTest::newRow("64x64 RGB24") + << QSize(64, 64) + << QVideoFrame::Format_RGB24 + << 16384 + << 192 + << QImage::Format_RGB888; + + QTest::newRow("64x64 RGB565") + << QSize(64, 64) + << QVideoFrame::Format_RGB565 + << 16384 + << 128 + << QImage::Format_RGB16; + + QTest::newRow("64x64 RGB555") + << QSize(64, 64) + << QVideoFrame::Format_RGB555 + << 16384 + << 128 + << QImage::Format_RGB555; + + QTest::newRow("64x64 BGRA32") + << QSize(64, 64) + << QVideoFrame::Format_BGRA32 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 BGRA32_Premultiplied") + << QSize(64, 64) + << QVideoFrame::Format_BGRA32_Premultiplied + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 BGR32") + << QSize(64, 64) + << QVideoFrame::Format_BGR32 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 BGR24") + << QSize(64, 64) + << QVideoFrame::Format_BGR24 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 BGR565") + << QSize(64, 64) + << QVideoFrame::Format_BGR565 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 BGR555") + << QSize(64, 64) + << QVideoFrame::Format_BGR555 + << 16384 + << 256 + << QImage::Format_ARGB32; +#if !QT_CONFIG(directshow) + QTest::newRow("64x64 AYUV444") + << QSize(64, 64) + << QVideoFrame::Format_AYUV444 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 YUV444") + << QSize(64, 64) + << QVideoFrame::Format_YUV444 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 YUV420P") + << QSize(64, 64) + << QVideoFrame::Format_YUV420P + << 13288 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 YV12") + << QSize(64, 64) + << QVideoFrame::Format_YV12 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 UYVY") + << QSize(64, 64) + << QVideoFrame::Format_UYVY + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 YUYV") + << QSize(64, 64) + << QVideoFrame::Format_YUYV + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 NV12") + << QSize(64, 64) + << QVideoFrame::Format_NV12 + << 16384 + << 256 + << QImage::Format_ARGB32; + + QTest::newRow("64x64 NV21") + << QSize(64, 64) + << QVideoFrame::Format_NV21 + << 16384 + << 256 + << QImage::Format_ARGB32; +#endif +} + +void tst_QVideoFrame::image() +{ + QFETCH(QSize, size); + QFETCH(QVideoFrame::PixelFormat, pixelFormat); + QFETCH(int, bytes); + QFETCH(int, bytesPerLine); + QFETCH(QImage::Format, imageFormat); + + QVideoFrame frame(bytes, size, bytesPerLine, pixelFormat); + QImage img = frame.image(); + + QVERIFY(!img.isNull()); + QCOMPARE(img.format(), imageFormat); + QCOMPARE(img.size(), size); + QCOMPARE(img.bytesPerLine(), bytesPerLine); +} + QTEST_MAIN(tst_QVideoFrame) #include "tst_qvideoframe.moc" diff --git a/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp b/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp index 3baa72281..bcc4acb3a 100644 --- a/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp +++ b/tests/auto/unit/qvideowidget/tst_qvideowidget.cpp @@ -100,6 +100,7 @@ private slots: void saturationRendererControl(); void paintRendererControl(); + void paintSurface(); private: void sizeHint_data(); @@ -1609,6 +1610,34 @@ void tst_QVideoWidget::paintRendererControl() QCOMPARE(surface->isReady(), true); } +void tst_QVideoWidget::paintSurface() +{ + QtTestVideoWidget widget; + widget.resize(640,480); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + QVERIFY(widget.videoSurface()); + auto surface = qobject_cast<QPainterVideoSurface *>( + widget.videoSurface()); + QVERIFY(surface); + + QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32); + QVERIFY(surface->start(format)); + QCOMPARE(surface->isActive(), true); + + QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32); + frame.map(QAbstractVideoBuffer::WriteOnly); + memcpy(frame.bits(), rgb32ImageData, frame.mappedBytes()); + frame.unmap(); + + QVERIFY(surface->present(frame)); + QCOMPARE(surface->isReady(), false); + QTRY_COMPARE(surface->isReady(), true); + QCOMPARE(surface->isActive(), true); + QCOMPARE(surface->isReady(), true); +} + QTEST_MAIN(tst_QVideoWidget) #include "tst_qvideowidget.moc" |