diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-05-12 03:02:00 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-05-12 03:02:00 +0200 |
commit | 19445bb152eec07536ca6186aca78ac8eafe77e1 (patch) | |
tree | 070ed386f717d780ac95a210b17bb0684013ba42 | |
parent | e2d022c48e50aa23469d861cc382910fda594994 (diff) | |
parent | 14a77698a01782f27e395bbc8694b808455d4ba1 (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: If607130a5ae7aaad3bd6323c2ba2beabaee4e096
-rw-r--r-- | dist/changes-5.11.0 | 75 | ||||
-rw-r--r-- | src/multimedia/audio/qsamplecache_p.cpp | 3 | ||||
-rw-r--r-- | src/multimedia/audio/qsoundeffect_qaudio_p.cpp | 7 | ||||
-rw-r--r-- | src/plugins/gstreamer/camerabin/camerabinsession.cpp | 80 | ||||
-rw-r--r-- | src/plugins/gstreamer/camerabin/camerabinsession.h | 3 | ||||
-rw-r--r-- | src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp | 3 | ||||
-rw-r--r-- | src/plugins/qnx/common/windowgrabber.cpp | 42 | ||||
-rw-r--r-- | src/plugins/qnx/common/windowgrabber.h | 1 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioinput.cpp | 25 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudioinput.h | 1 | ||||
-rw-r--r-- | src/plugins/windowsaudio/qwindowsaudiooutput.cpp | 4 | ||||
-rw-r--r-- | src/qtmultimediaquicktools/qdeclarativevideooutput.cpp | 13 | ||||
-rw-r--r-- | tests/auto/integration/qaudioinput/tst_qaudioinput.cpp | 6 |
13 files changed, 182 insertions, 81 deletions
diff --git a/dist/changes-5.11.0 b/dist/changes-5.11.0 new file mode 100644 index 000000000..802eec73b --- /dev/null +++ b/dist/changes-5.11.0 @@ -0,0 +1,75 @@ +Qt 5.11 introduces many new features and improvements as well as bugfixes +over the 5.10.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.11 series is binary compatible with the 5.10.x series. +Applications compiled for 5.10 will continue to run with 5.11. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.11.0 Changes * +**************************************************************************** + +QtMultimedia +------------ + + - Added customAudioRole string property to enable use of audio roles + beyond those available via the audioRole enum property. + - [QTBUG-45336] Added supportedFocusModes and supportedFocusPointModes + to QML CameraFocus. + - [QTBUG-45336] Added property supportedExposureModes to CameraExposure. + - [QTBUG-47606] Added mirrored API to QVideoSurfaceFormat. + - [QTBUG-45336] Added missing capability properties to CameraImageProcessing. + - [QTBUG-65207] Fixed setting QAudioEncoderSettings::bitRate. + - [QTBUG-30728] Made it possible to receive mouse move events in QVideoWidget. + - [QTBUG-60579] Added support for changing the volume on 24-bit audio samples. + - [QTBUG-53594] Fixed target rectangle coordinates while painting image + with QPainter. + - [QTBUG-51825] Fixed error reporting when QCamera::start() fails. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +PulseAudio +---------- + + - [QTBUG-49569] Emitted QAudio::StoppedState on QAudio::OpenError. + +Gstreamer +--------- + + - Fixed udpsrc timeout setting. + - [QTBUG-23761] Fixed setting vaapi sink properties. + - [QTBUG-64142] Fixed leak in prepare-window-handle message. + +DirectShow +---------- + + - Added support for manual camera exposure control. + - Added support for setting the capture destination and format. + - Added support for video probes in the camera. + - Added camera zoom support. + - [QTBUG-55354] Setting an unsupported playback rate will now fallback to the previous set rate. + - [QTBUG-65780] Fixed blank QVideoWidget when it is paused. + - Improved matching, filter and connecting pins. + +QNX +--- + + - Added support for QNX 7.0.0 audio management. + - Implemented QCustomAudioRoleControl for QNX. + +AVFoundation +------------ + + - Added support for the buffer status. diff --git a/src/multimedia/audio/qsamplecache_p.cpp b/src/multimedia/audio/qsamplecache_p.cpp index c76f51899..93010c182 100644 --- a/src/multimedia/audio/qsamplecache_p.cpp +++ b/src/multimedia/audio/qsamplecache_p.cpp @@ -132,7 +132,8 @@ QSampleCache::~QSampleCache() for (QSample* sample : copyStaleSamples) delete sample; - m_networkAccessManager->deleteLater(); + if (m_networkAccessManager) + m_networkAccessManager->deleteLater(); } void QSampleCache::loadingRelease() diff --git a/src/multimedia/audio/qsoundeffect_qaudio_p.cpp b/src/multimedia/audio/qsoundeffect_qaudio_p.cpp index 388f84d91..3f315fa28 100644 --- a/src/multimedia/audio/qsoundeffect_qaudio_p.cpp +++ b/src/multimedia/audio/qsoundeffect_qaudio_p.cpp @@ -132,6 +132,13 @@ void QSoundEffectPrivate::setSource(const QUrl &url) d->m_sample = nullptr; } + if (d->m_audioOutput) { + disconnect(d->m_audioOutput, &QAudioOutput::stateChanged, d, &PrivateSoundSource::stateChanged); + d->m_audioOutput->stop(); + d->m_audioOutput->deleteLater(); + d->m_audioOutput = nullptr; + } + setStatus(QSoundEffect::Loading); d->m_sample = sampleCache()->requestSample(url); connect(d->m_sample, &QSample::error, d, &PrivateSoundSource::decoderError); diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index 3bb6ebffb..d7a96d333 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -363,9 +363,9 @@ void CameraBinSession::setupCaptureResolution() Both = 0x4 }; quint8 found = Nothing; - - for (int i = 0; i < m_supportedViewfinderSettings.count() && !(found & Both); ++i) { - const QCameraViewfinderSettings &s = m_supportedViewfinderSettings.at(i); + auto viewfinderSettings = supportedViewfinderSettings(); + for (int i = 0; i < viewfinderSettings.count() && !(found & Both); ++i) { + const QCameraViewfinderSettings &s = viewfinderSettings.at(i); if (s.resolution() == viewfinderResolution) { if ((qFuzzyIsNull(viewfinderFrameRate) || s.maximumFrameRate() == viewfinderFrameRate) && (viewfinderPixelFormat == QVideoFrame::Format_Invalid || s.pixelFormat() == viewfinderPixelFormat)) @@ -676,8 +676,46 @@ void CameraBinSession::setViewfinder(QObject *viewfinder) } } +static QList<QCameraViewfinderSettings> capsToViewfinderSettings(GstCaps *supportedCaps) +{ + QList<QCameraViewfinderSettings> settings; + + if (!supportedCaps) + return settings; + + supportedCaps = qt_gst_caps_normalize(supportedCaps); + + // Convert caps to QCameraViewfinderSettings + for (uint i = 0; i < gst_caps_get_size(supportedCaps); ++i) { + const GstStructure *structure = gst_caps_get_structure(supportedCaps, i); + + QCameraViewfinderSettings s; + s.setResolution(QGstUtils::structureResolution(structure)); + s.setPixelFormat(QGstUtils::structurePixelFormat(structure)); + s.setPixelAspectRatio(QGstUtils::structurePixelAspectRatio(structure)); + + QPair<qreal, qreal> frameRateRange = QGstUtils::structureFrameRateRange(structure); + s.setMinimumFrameRate(frameRateRange.first); + s.setMaximumFrameRate(frameRateRange.second); + + if (!s.resolution().isEmpty() + && s.pixelFormat() != QVideoFrame::Format_Invalid + && !settings.contains(s)) { + settings.append(s); + } + } + + gst_caps_unref(supportedCaps); + return settings; +} + QList<QCameraViewfinderSettings> CameraBinSession::supportedViewfinderSettings() const { + if (m_status == QCamera::LoadedStatus && m_supportedViewfinderSettings.isEmpty()) { + m_supportedViewfinderSettings = + capsToViewfinderSettings(supportedCaps(QCamera::CaptureViewfinder)); + } + return m_supportedViewfinderSettings; } @@ -1075,7 +1113,7 @@ bool CameraBinSession::processBusMessage(const QGstreamerMessage &message) break; case GST_STATE_READY: if (oldState == GST_STATE_NULL) - updateSupportedViewfinderSettings(); + m_supportedViewfinderSettings.clear(); setMetaData(m_metaData); setStatus(QCamera::LoadedStatus); @@ -1453,40 +1491,6 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate, return res; } -void CameraBinSession::updateSupportedViewfinderSettings() -{ - m_supportedViewfinderSettings.clear(); - - GstCaps *supportedCaps = this->supportedCaps(QCamera::CaptureViewfinder); - - // Convert caps to QCameraViewfinderSettings - if (supportedCaps) { - supportedCaps = qt_gst_caps_normalize(supportedCaps); - - for (uint i = 0; i < gst_caps_get_size(supportedCaps); i++) { - const GstStructure *structure = gst_caps_get_structure(supportedCaps, i); - - QCameraViewfinderSettings s; - s.setResolution(QGstUtils::structureResolution(structure)); - s.setPixelFormat(QGstUtils::structurePixelFormat(structure)); - s.setPixelAspectRatio(QGstUtils::structurePixelAspectRatio(structure)); - - QPair<qreal, qreal> frameRateRange = QGstUtils::structureFrameRateRange(structure); - s.setMinimumFrameRate(frameRateRange.first); - s.setMaximumFrameRate(frameRateRange.second); - - if (!s.resolution().isEmpty() - && s.pixelFormat() != QVideoFrame::Format_Invalid - && !m_supportedViewfinderSettings.contains(s)) { - - m_supportedViewfinderSettings.append(s); - } - } - - gst_caps_unref(supportedCaps); - } -} - void CameraBinSession::elementAdded(GstBin *, GstElement *element, CameraBinSession *session) { GstElementFactory *factory = gst_element_get_factory(element); diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.h b/src/plugins/gstreamer/camerabin/camerabinsession.h index d5c2d7822..999398fa4 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.h +++ b/src/plugins/gstreamer/camerabin/camerabinsession.h @@ -203,7 +203,6 @@ private: bool setupCameraBin(); void setAudioCaptureCaps(); GstCaps *supportedCaps(QCamera::CaptureModes mode) const; - void updateSupportedViewfinderSettings(); static void updateBusyStatus(GObject *o, GParamSpec *p, gpointer d); QString currentContainerFormat() const; @@ -229,7 +228,7 @@ private: QGstreamerElementFactory *m_videoInputFactory; QObject *m_viewfinder; QGstreamerVideoRendererInterface *m_viewfinderInterface; - QList<QCameraViewfinderSettings> m_supportedViewfinderSettings; + mutable QList<QCameraViewfinderSettings> m_supportedViewfinderSettings; QCameraViewfinderSettings m_viewfinderSettings; QCameraViewfinderSettings m_actualViewfinderSettings; diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp index 609670b81..b268592c6 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp @@ -103,6 +103,9 @@ QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::Cap m_videoEncodeControl = new QGstreamerVideoEncode(this); m_imageEncodeControl = new QGstreamerImageEncode(this); m_recorderControl = new QGstreamerRecorderControl(this); + connect(m_recorderControl, &QGstreamerRecorderControl::error, [](int e, const QString &str) { + qWarning() << QMediaRecorder::Error(e) << ":" << str.toLatin1().constData(); + }); m_mediaContainerControl = new QGstreamerMediaContainerControl(this); setState(StoppedState); diff --git a/src/plugins/qnx/common/windowgrabber.cpp b/src/plugins/qnx/common/windowgrabber.cpp index ca7224a4f..9a65ad3a0 100644 --- a/src/plugins/qnx/common/windowgrabber.cpp +++ b/src/plugins/qnx/common/windowgrabber.cpp @@ -58,6 +58,7 @@ static PFNEGLDESTROYIMAGEKHRPROC s_eglDestroyImageKHR; WindowGrabber::WindowGrabber(QObject *parent) : QObject(parent), + m_windowParent(nullptr), m_screenContext(0), m_active(false), m_currentFrame(0), @@ -81,10 +82,26 @@ WindowGrabber::WindowGrabber(QObject *parent) s_eglCreateImageKHR = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR")); s_eglDestroyImageKHR = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR")); } + + QPlatformNativeInterface *const nativeInterface = QGuiApplication::platformNativeInterface(); + if (nativeInterface) { + m_screenContext = static_cast<screen_context_t>( + nativeInterface->nativeResourceForIntegration("screenContext")); + } + + // Create a parent window for the window whose content will be grabbed. Since the + // window is only a buffer conduit, the characteristics of the parent window are + // irrelevant. The contents of the window can be grabbed so long as the window + // joins the parent window's group and the parent window is in this process. + // Using the window that displays this content isn't possible because there's no + // way to reliably retrieve it from this code or any calling code. + screen_create_window(&m_windowParent, m_screenContext); + screen_create_window_group(m_windowParent, nullptr); } WindowGrabber::~WindowGrabber() { + screen_destroy_window(m_windowParent); QCoreApplication::eventDispatcher()->removeNativeEventFilter(this); cleanup(); } @@ -184,24 +201,13 @@ bool WindowGrabber::nativeEventFilter(const QByteArray &eventType, void *message QByteArray WindowGrabber::windowGroupId() const { - QWindow *window = QGuiApplication::allWindows().isEmpty() ? 0 : QGuiApplication::allWindows().first(); - if (!window) - return QByteArray(); - - QPlatformNativeInterface * const nativeInterface = QGuiApplication::platformNativeInterface(); - if (!nativeInterface) { - qWarning() << "WindowGrabber: Unable to get platform native interface"; - return QByteArray(); - } - - const char * const groupIdData = static_cast<const char *>( - nativeInterface->nativeResourceForWindow("windowGroup", window)); - if (!groupIdData) { - qWarning() << "WindowGrabber: Unable to find window group for window" << window; - return QByteArray(); - } - - return QByteArray(groupIdData); + char groupName[256]; + memset(groupName, 0, sizeof(groupName)); + screen_get_window_property_cv(m_windowParent, + SCREEN_PROPERTY_GROUP, + sizeof(groupName) - 1, + groupName); + return QByteArray(groupName); } bool WindowGrabber::eglImageSupported() diff --git a/src/plugins/qnx/common/windowgrabber.h b/src/plugins/qnx/common/windowgrabber.h index 4b2217f74..3ebd0e8a6 100644 --- a/src/plugins/qnx/common/windowgrabber.h +++ b/src/plugins/qnx/common/windowgrabber.h @@ -126,6 +126,7 @@ private: QByteArray m_windowId; + screen_window_t m_windowParent; screen_window_t m_window; screen_context_t m_screenContext; diff --git a/src/plugins/windowsaudio/qwindowsaudioinput.cpp b/src/plugins/windowsaudio/qwindowsaudioinput.cpp index 4771fe1cc..00b36cfe4 100644 --- a/src/plugins/windowsaudio/qwindowsaudioinput.cpp +++ b/src/plugins/windowsaudio/qwindowsaudioinput.cpp @@ -74,14 +74,13 @@ QWindowsAudioInput::QWindowsAudioInput(const QByteArray &device) waveBlockOffset = 0; mixerID = 0; + cachedVolume = 1.0f; memset(&mixerLineControls, 0, sizeof(mixerLineControls)); - initMixer(); } QWindowsAudioInput::~QWindowsAudioInput() { stop(); - closeMixer(); } void QT_WIN_CALLBACK QWindowsAudioInput::waveInProc( HWAVEIN hWaveIn, UINT uMsg, @@ -183,6 +182,7 @@ QAudio::State QWindowsAudioInput::state() const void QWindowsAudioInput::setVolume(qreal volume) { + cachedVolume = volume; for (DWORD i = 0; i < mixerLineControls.cControls; i++) { MIXERCONTROLDETAILS controlDetails; @@ -204,7 +204,6 @@ void QWindowsAudioInput::setVolume(qreal volume) qreal QWindowsAudioInput::volume() const { - DWORD volume = 0; for (DWORD i = 0; i < mixerLineControls.cControls; i++) { if ((mixerLineControls.pamxctrl[i].dwControlType != MIXERCONTROL_CONTROLTYPE_FADER) && (mixerLineControls.pamxctrl[i].dwControlType != MIXERCONTROL_CONTROLTYPE_VOLUME)) { @@ -226,11 +225,10 @@ qreal QWindowsAudioInput::volume() const continue; if (controlDetails.cbDetails < sizeof(MIXERCONTROLDETAILS_UNSIGNED)) continue; - volume = detailsUnsigned.dwValue; - break; + return detailsUnsigned.dwValue / 65535.0; } - return volume / 65535.0; + return cachedVolume; } void QWindowsAudioInput::setFormat(const QAudioFormat& fmt) @@ -378,6 +376,7 @@ bool QWindowsAudioInput::open() elapsedTimeOffset = 0; totalTimeValue = 0; errorState = QAudio::NoError; + initMixer(); return true; } @@ -396,6 +395,7 @@ void QWindowsAudioInput::close() mutex.unlock(); waveInClose(hWaveIn); + closeMixer(); int count = 0; while(!finished && count < 500) { @@ -406,17 +406,10 @@ void QWindowsAudioInput::close() void QWindowsAudioInput::initMixer() { - QDataStream ds(&m_device, QIODevice::ReadOnly); - quint32 inputDevice; - ds >> inputDevice; - - if (int(inputDevice) < 0) - return; - // Get the Mixer ID from the Sound Device ID UINT mixerIntID = 0; - if (mixerGetID(reinterpret_cast<HMIXEROBJ>(quintptr(inputDevice)), - &mixerIntID, MIXER_OBJECTF_WAVEIN) != MMSYSERR_NOERROR) + if (mixerGetID(reinterpret_cast<HMIXEROBJ>(hWaveIn), + &mixerIntID, MIXER_OBJECTF_HWAVEIN) != MMSYSERR_NOERROR) return; mixerID = reinterpret_cast<HMIXEROBJ>(quintptr(mixerIntID)); @@ -436,6 +429,8 @@ void QWindowsAudioInput::initMixer() mixerLineControls.pamxctrl = new MIXERCONTROL[mixerLineControls.cControls]; if (mixerGetLineControls(mixerID, &mixerLineControls, MIXER_GETLINECONTROLSF_ALL) != MMSYSERR_NOERROR) closeMixer(); + else + setVolume(cachedVolume); } } diff --git a/src/plugins/windowsaudio/qwindowsaudioinput.h b/src/plugins/windowsaudio/qwindowsaudioinput.h index e61a50a89..a0feae257 100644 --- a/src/plugins/windowsaudio/qwindowsaudioinput.h +++ b/src/plugins/windowsaudio/qwindowsaudioinput.h @@ -147,6 +147,7 @@ private: void closeMixer(); HMIXEROBJ mixerID; MIXERLINECONTROLS mixerLineControls; + qreal cachedVolume; private slots: void feedback(); diff --git a/src/plugins/windowsaudio/qwindowsaudiooutput.cpp b/src/plugins/windowsaudio/qwindowsaudiooutput.cpp index 104055f30..26eecb768 100644 --- a/src/plugins/windowsaudio/qwindowsaudiooutput.cpp +++ b/src/plugins/windowsaudio/qwindowsaudiooutput.cpp @@ -241,6 +241,10 @@ bool QWindowsAudioOutput::open() period_size = buffer_size / 5; } + // Make even size of wave block to prevent crackling + // due to waveOutWrite() does not like odd buffer length + period_size &= ~1; + if (period_size == 0) { errorState = QAudio::OpenError; deviceState = QAudio::StoppedState; diff --git a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp index 4fc768438..3c6a6f9c5 100644 --- a/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp +++ b/src/qtmultimediaquicktools/qdeclarativevideooutput.cpp @@ -263,17 +263,16 @@ bool QDeclarativeVideoOutput::createBackend(QMediaService *service) backendAvailable = true; } - if (!backendAvailable) { - qWarning() << Q_FUNC_INFO << "Media service has neither renderer nor window control available."; - m_backend.reset(); - } else if (!m_geometryDirty) { - m_backend->updateGeometry(); - } + if (backendAvailable) { + // Since new backend has been created needs to update its geometry. + m_geometryDirty = true; - if (m_backend) { m_backend->clearFilters(); for (int i = 0; i < m_filters.count(); ++i) m_backend->appendFilter(m_filters[i]); + } else { + qWarning() << Q_FUNC_INFO << "Media service has neither renderer nor window control available."; + m_backend.reset(); } return backendAvailable; diff --git a/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp b/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp index 14023f229..64e872f27 100644 --- a/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp +++ b/tests/auto/integration/qaudioinput/tst_qaudioinput.cpp @@ -887,6 +887,12 @@ void tst_QAudioInput::volume() QTest::qWait(500); QTRY_VERIFY(qRound(audioInput.volume()*10.0f) == 10); + audioInput.setVolume(half); + audioInput.start(); + QTRY_VERIFY(qRound(audioInput.volume()*10.0f) == 5); + audioInput.setVolume(one); + QTRY_VERIFY(qRound(audioInput.volume()*10.0f) == 10); + audioInput.setVolume(volume); } |