diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 new file mode 100644 index 00000000..d81d815b --- /dev/null +++ b/dist/changes-5.5.1 @@ -0,0 +1,68 @@ +Qt 5.5.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.5.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.5/ + +The Qt version 5.5 series is binary compatible with the 5.4.x series. +Applications compiled for 5.4 will continue to run with 5.5. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Library * +**************************************************************************** + +QtMultimedia +------------ + + - The environment variable QT_QUICK_NO_TEXTURE_VIDEOFRAMES can now be used + to disable OpenGL texture based video frames when using the VideoOutput + QML type. This can be useful in applications that wish to filter and + process the video frames using QAbstractVideoFilter and are not GPU + based. + - QCamera's viewfinder capabilities functions now report correct values + when filtering by pixel aspect ratio. + - [QTBUG-46359] fixed crash after using moveToThread() on a QSoundEffect. + - [QTBUG-47205] fixed VideoOutput (QML) rendering frames from the wrong + source when having multiple VideoOutputs using different sources. + - [QTBUG-47630] fixed Camera.supportedViewfinderFrameRateRanges() (QML) + returning incorrect values when the argument is not of type 'size'. + - [QTBUG-47859] fixed crash when using Radio.radioData (QML) without + a radio backend available. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Android +------- + + - Fixed QVideoProbe stopping to work when using QMediaRecorder to record + the camera. + - Video frames passed to a QAbstractVideoFilter can now be mapped to + system memory. + +Linux +----- + + - QCameraImageProcessing::isWhiteBalanceModeSupported() now correctly + reports if a given white balance mode is supported. + - [QTBUG-45707] fixed QAudioRecorder::stop() sometimes failing to + actually stop the recording. + + WinRT +----- + + - [QTBUG-46456] QCameraImageCapture: getting the list of supported + image capture resolutions and setting the image capture resolution is + now supported. + - [QTBUG-47373] fixed crash occurring with some camera operations. diff --git a/src/gsttools/qgstreamervideooverlay.cpp b/src/gsttools/qgstreamervideooverlay.cpp index 1dcedbcd..06f93ef6 100644 --- a/src/gsttools/qgstreamervideooverlay.cpp +++ b/src/gsttools/qgstreamervideooverlay.cpp @@ -148,9 +148,7 @@ GstElement *QGstreamerVideoOverlay::findBestVideoSink() const // If none of the known video sinks are available, try to find one that implements the // GstVideoOverlay interface and has autoplugging rank. - GList *list = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO, - GST_RANK_MARGINAL); - + GList *list = qt_gst_video_sinks(); for (GList *item = list; item != NULL; item = item->next) { GstElementFactory *f = GST_ELEMENT_FACTORY(item->data); @@ -242,12 +240,17 @@ void QGstreamerVideoOverlay::setRenderRectangle(const QRect &rect) h = rect.height(); } -#if !GST_CHECK_VERSION(1,0,0) +#if GST_CHECK_VERSION(1,0,0) + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) + gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h); +#elif GST_CHECK_VERSION(0, 10, 29) if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) gst_x_overlay_set_render_rectangle(GST_X_OVERLAY(m_videoSink), x, y , w , h); #else - if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) - gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), x, y, w, h); + Q_UNUSED(x) + Q_UNUSED(y) + Q_UNUSED(w) + Q_UNUSED(h) #endif } diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index b13038c2..50a56232 100644 --- a/src/gsttools/qgstutils.cpp +++ b/src/gsttools/qgstutils.cpp @@ -774,6 +774,7 @@ QSet QGstUtils::supportedMimeTypes(bool (*isValidFactory)(GstElementFac return supportedMimeTypes; } +#if GST_CHECK_VERSION(1, 0, 0) namespace { struct ColorFormat { QImage::Format imageFormat; GstVideoFormat gstFormat; }; @@ -786,6 +787,7 @@ static const ColorFormat qt_colorLookup[] = }; } +#endif #if GST_CHECK_VERSION(1,0,0) QImage QGstUtils::bufferToImage(GstBuffer *buffer, const GstVideoInfo &videoInfo) @@ -1212,6 +1214,7 @@ void QGstUtils::setMetaData(GstElement *element, const QMap(g_type_class_peek_parent(g_class)); - GstVideoSinkClass *video_sink_class = reinterpret_cast(g_class); - video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame; - GstBaseSinkClass *base_sink_class = reinterpret_cast(g_class); base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps; base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps; @@ -387,6 +384,14 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) base_sink_class->stop = QVideoSurfaceGstSink::stop; base_sink_class->unlock = QVideoSurfaceGstSink::unlock; +#if GST_CHECK_VERSION(0, 10, 25) + GstVideoSinkClass *video_sink_class = reinterpret_cast(g_class); + video_sink_class->show_frame = QVideoSurfaceGstSink::show_frame; +#else + base_sink_class->preroll = QVideoSurfaceGstSink::preroll; + base_sink_class->render = QVideoSurfaceGstSink::render; +#endif + GstElementClass *element_class = reinterpret_cast(g_class); element_class->change_state = QVideoSurfaceGstSink::change_state; @@ -674,10 +679,30 @@ gboolean QVideoSurfaceGstSink::unlock(GstBaseSink *base) return TRUE; } +#if GST_CHECK_VERSION(0, 10, 25) GstFlowReturn QVideoSurfaceGstSink::show_frame(GstVideoSink *base, GstBuffer *buffer) { VO_SINK(base); return sink->delegate->render(buffer); } +#else +GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer) +{ + VO_SINK(base); + gboolean showPrerollFrame = true; + g_object_get(G_OBJECT(sink), "show-preroll-frame", &showPrerollFrame, NULL); + + if (showPrerollFrame) + return sink->delegate->render(buffer); + + return GST_FLOW_OK; +} + +GstFlowReturn QVideoSurfaceGstSink::render(GstBaseSink *base, GstBuffer *buffer) +{ + VO_SINK(base); + return sink->delegate->render(buffer); +} +#endif QT_END_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h index 31fb8584..cf677c32 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -150,6 +150,8 @@ gboolean qt_gst_element_query_position(GstElement *element, GstFormat format, gi gboolean qt_gst_element_query_duration(GstElement *element, GstFormat format, gint64 *cur); GstCaps *qt_gst_caps_normalize(GstCaps *caps); const gchar *qt_gst_element_get_factory_name(GstElement *element); +gboolean qt_gst_caps_can_intersect(const GstCaps * caps1, const GstCaps * caps2); +GList *qt_gst_video_sinks(); QDebug operator <<(QDebug debug, GstCaps *caps); diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h index a1ef5616..9c04b980 100644 --- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h +++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h @@ -157,7 +157,12 @@ private: static gboolean unlock(GstBaseSink *sink); +#if GST_CHECK_VERSION(0, 10, 25) static GstFlowReturn show_frame(GstVideoSink *sink, GstBuffer *buffer); +#else + static GstFlowReturn preroll(GstBaseSink *sink, GstBuffer *buffer); + static GstFlowReturn render(GstBaseSink *sink, GstBuffer *buffer); +#endif private: QVideoSurfaceGstDelegate *delegate; diff --git a/src/multimedia/video/qvideooutputorientationhandler_p.h b/src/multimedia/video/qvideooutputorientationhandler_p.h index 252ee292..c690cafa 100644 --- a/src/multimedia/video/qvideooutputorientationhandler_p.h +++ b/src/multimedia/video/qvideooutputorientationhandler_p.h @@ -59,10 +59,10 @@ public: int currentOrientation() const; -signals: +Q_SIGNALS: void orientationChanged(int angle); -private slots: +private Q_SLOTS: void screenOrientationChanged(Qt::ScreenOrientation orientation); private: diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm index 924c62d9..705ec633 100644 --- a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm +++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm @@ -174,7 +174,7 @@ public: GL_RGBA, CVPixelBufferGetWidth(m_buffer), CVPixelBufferGetHeight(m_buffer), - GL_BGRA, + GL_RGBA, GL_UNSIGNED_BYTE, 0, &m_texture); @@ -240,18 +240,8 @@ private: int width = CVPixelBufferGetWidth(imageBuffer); int height = CVPixelBufferGetHeight(imageBuffer); - QVideoFrame::PixelFormat format; - -#ifdef Q_OS_IOS - bool useTexture = m_renderer->supportsTextures() - && CVPixelBufferGetPixelFormatType(imageBuffer) == kCVPixelFormatType_32BGRA; - - if (useTexture) - format = QVideoFrame::Format_BGRA32; - else -#endif - format = AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(CVPixelBufferGetPixelFormatType(imageBuffer)); - + QVideoFrame::PixelFormat format = + AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(CVPixelBufferGetPixelFormatType(imageBuffer)); if (format == QVideoFrame::Format_Invalid) return; diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp index 6afee943..f919bb1f 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp @@ -70,9 +70,15 @@ QMultimedia::SupportEstimate QGstreamerAudioDecoderServicePlugin::hasSupport(con static bool isDecoderOrDemuxer(GstElementFactory *factory) { +#if GST_CHECK_VERSION(0, 10, 31) return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DEMUXER) - || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER - | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); + || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER + | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); +#else + return (factory + && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 + || qstrcmp(factory->details.klass, "Codec/Demux") == 0)); +#endif } void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp index 0018209c..fca38ecf 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturemetadatacontrol.cpp @@ -77,9 +77,7 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() metadataKeys->insert(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM); metadataKeys->insert(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST); metadataKeys->insert(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER); -#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) metadataKeys->insert(QMediaMetaData::Composer, GST_TAG_COMPOSER); -#endif //metadataKeys->insert(QMediaMetaData::Conductor, 0); //metadataKeys->insert(QMediaMetaData::Lyrics, 0); //metadataKeys->insert(QMediaMetaData::Mood, 0); diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp index a9c66f83..8cbdb671 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercaptureserviceplugin.cpp @@ -113,8 +113,15 @@ QMultimedia::SupportEstimate QGstreamerCaptureServicePlugin::hasSupport(const QS static bool isEncoderOrMuxer(GstElementFactory *factory) { +#if GST_CHECK_VERSION(0, 10, 31) return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_MUXER) || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_ENCODER); +#else + return (factory + && (qstrcmp(factory->details.klass, "Codec/Encoder/Audio") == 0 + || qstrcmp(factory->details.klass, "Codec/Encoder/Video") == 0 + || qstrcmp(factory->details.klass, "Codec/Muxer") == 0 )); +#endif } void QGstreamerCaptureServicePlugin::updateSupportedMimeTypes() const diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp index 77d8987f..31ffa506 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp @@ -628,12 +628,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo } dumpGraph( QString("rebuild_graph_%1_%2").arg(m_pipelineMode).arg(newMode) ); +#ifdef QT_GST_CAPTURE_DEBUG if (m_encodeBin) { QString fileName = QString("rebuild_graph_encode_%1_%2").arg(m_pipelineMode).arg(newMode); -#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - _gst_debug_bin_to_dot_file(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1()); -#endif + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_encodeBin), GST_DEBUG_GRAPH_SHOW_ALL, fileName.toLatin1()); } +#endif if (ok) { addAudioBufferProbe(); @@ -657,12 +657,12 @@ bool QGstreamerCaptureSession::rebuildGraph(QGstreamerCaptureSession::PipelineMo void QGstreamerCaptureSession::dumpGraph(const QString &fileName) { -#if !(GST_DISABLE_GST_DEBUG) && (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - _gst_debug_bin_to_dot_file(GST_BIN(m_pipeline), - GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL |*/ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES), - fileName.toLatin1()); +#ifdef QT_GST_CAPTURE_DEBUG + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_pipeline), + GstDebugGraphDetails(/*GST_DEBUG_GRAPH_SHOW_ALL |*/ GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES), + fileName.toLatin1()); #else - Q_UNUSED(fileName); + Q_UNUSED(fileName) #endif } diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp index ac0fe2a7..fdf43062 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamermetadataprovider.cpp @@ -76,13 +76,10 @@ static const QGstreamerMetaDataKeyLookup *qt_gstreamerMetaDataKeys() // Music metadataKeys->insert(GST_TAG_ALBUM, QMediaMetaData::AlbumTitle); -#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 25) +#if GST_CHECK_VERSION(0, 10, 25) metadataKeys->insert(GST_TAG_ALBUM_ARTIST, QMediaMetaData::AlbumArtist); #endif metadataKeys->insert(GST_TAG_ARTIST, QMediaMetaData::ContributingArtist); -#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19) - metadataKeys->insert(GST_TAG_COMPOSER, QMediaMetaData::Composer); -#endif //metadataKeys->insert(0, QMediaMetaData::Conductor); //metadataKeys->insert(0, QMediaMetaData::Lyrics); //metadataKeys->insert(0, QMediaMetaData::Mood); diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp index 004d561a..b895c4d8 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp @@ -83,8 +83,15 @@ QMultimedia::SupportEstimate QGstreamerPlayerServicePlugin::hasSupport(const QSt static bool isDecoderOrDemuxer(GstElementFactory *factory) { +#if GST_CHECK_VERSION(0, 10 ,31) return gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DEMUXER) || gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_DECODER); +#else + return (factory + && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 + || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0 + || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )); +#endif } void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 4dce3411..c3d20e79 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -388,7 +388,7 @@ QMediaTimeRange QGstreamerPlayerSession::availablePlaybackRanges() const if (duration() <= 0) return ranges; -#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 31) +#if GST_CHECK_VERSION(0, 10, 31) //GST_FORMAT_TIME would be more appropriate, but unfortunately it's not supported. //with GST_FORMAT_PERCENT media is treated as encoded with constant bitrate. GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT); @@ -1637,7 +1637,7 @@ void QGstreamerPlayerSession::updateMuted() } } -#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33)) +#if !GST_CHECK_VERSION(0, 10, 33) static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstCaps *caps) { GList *templates; @@ -1653,7 +1653,7 @@ static gboolean factory_can_src_any_caps (GstElementFactory *factory, const GstC if (templ->direction == GST_PAD_SRC) { GstCaps *templcaps = gst_static_caps_get(&templ->static_caps); - if (gst_caps_can_intersect(caps, templcaps)) { + if (qt_gst_caps_can_intersect(caps, templcaps)) { gst_caps_unref(templcaps); return TRUE; } @@ -1685,7 +1685,7 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi GstCaps *sinkCaps = gst_pad_get_caps(sinkPad); #endif -#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33)) +#if !GST_CHECK_VERSION(0, 10, 33) if (!factory_can_src_any_caps(factory, sinkCaps)) #else if (!gst_element_factory_can_src_any_caps(factory, sinkCaps))