From 265bfb22e7f0f5333e584f6dd91926b8516e394e Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Thu, 23 Jan 2020 13:29:37 +0100 Subject: AVF: Always lock the capture device when start the camera If the viewfinder settings are valid, need to lock the capture device to avoid reseting settings to default values. See also a8123e737140719549252806e0e6a1c121359f79 Fixes: QTBUG-81048 Change-Id: I834815ef6c5ef28d8017d04bdb9d5256c02d1de7 Reviewed-by: Paul Wicking --- src/plugins/avfoundation/camera/avfcamerasession.mm | 3 ++- src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm index a3263badc..3c5f8f09a 100644 --- a/src/plugins/avfoundation/camera/avfcamerasession.mm +++ b/src/plugins/avfoundation/camera/avfcamerasession.mm @@ -408,7 +408,8 @@ bool AVFCameraSession::applyViewfinderSettings() vfSettings.setResolution(imageResolution); } - return vfControl->applySettings(vfSettings); + vfControl->applySettings(vfSettings); + return !vfSettings.isNull(); } return false; diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm index 91f3cb7dc..a77d7de03 100644 --- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm +++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm @@ -185,6 +185,7 @@ void AVFCameraViewfinderSettingsControl2::setViewfinderSettings(const QCameraVie return; m_settings = settings; + applySettings(m_settings); } QVideoFrame::PixelFormat AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(unsigned avPixelFormat) -- cgit v1.2.3 From 545d4aedc2af40182cd9141d014a02f919592cd9 Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Wed, 5 Feb 2020 11:30:05 +0100 Subject: AVF: Don't use deprecated AVPlayerItem::seekToTime::CMTime AVPlayerItem::seekToTime::CMTime is deprecated since 10.13 Also fixed to use accurate seeking by passing a time value of kCMTimeZero for both toleranceBefore and toleranceAfter. Fixes: QTBUG-81804 Change-Id: Ifafeb1fb5ca66ecba14d77abf315ebe6ffd45eab Reviewed-by: Timur Pocheptsov --- src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index 3e3736183..ff38b4104 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -686,7 +686,7 @@ void AVFMediaPlayerSession::setPosition(qint64 pos) CMTime newTime = [playerItem currentTime]; newTime.value = (pos / 1000.0f) * newTime.timescale; - [playerItem seekToTime:newTime]; + [playerItem seekToTime:newTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:nil]; Q_EMIT positionChanged(pos); -- cgit v1.2.3 From e47ed7b88223c42dd20ef86b829061fcc4f1fc30 Mon Sep 17 00:00:00 2001 From: Dominik Holland Date: Thu, 6 Feb 2020 09:41:48 +0100 Subject: AVF: Only resume playback after a stalled buffer if really needed When AVFoundation reports that the media is now buffered, we only should resume the playback if the QMediaPlayer is in the according state. Fixes: QTBUG-81912 Change-Id: Idba30ecf6c9c7b87a1c67896d89faa9a1bceae10 Reviewed-by: VaL Doroshchuk --- src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index ff38b4104..1f13fc9bb 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -928,7 +928,8 @@ void AVFMediaPlayerSession::processBufferStateChange(int bufferStatus) } else if (status == QMediaPlayer::StalledMedia) { status = QMediaPlayer::BufferedMedia; // Resume playback. - [[static_cast(m_observer) player] setRate:m_rate]; + if (m_state == QMediaPlayer::PlayingState) + [[static_cast(m_observer) player] setRate:m_rate]; } if (m_mediaStatus != status) -- cgit v1.2.3 From aec140743b1a4110c327c46bdfbf15fcddb2dd17 Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Mon, 17 Feb 2020 15:32:25 +0100 Subject: AVF: Fix applying viewfinder settings for iOS 1. If a resolution of the viewfinder is requested to be changed, it is not needed to check available formats for highResolutionStillImageDimensions (since it is viewfinder resolution and not still images). format.highResolutionStillImageDimensions returns the highest resolution still image that can be produced by the format. Using this format will cause wrong resolution in the viewfinder. 2. Seems iOS requires to call beginConfiguration/commitConfiguration to apply any changes. commitConfiguration is currently called when the camera gets active. In case if settings are changed after starting the camera, they will not be applied. To fix that, added beginConfiguration/commitConfiguration. Fixes: QTBUG-79935 Change-Id: I60b6e08887a82e4337a2a302b8e5513c65b26e61 Reviewed-by: Timur Pocheptsov --- src/plugins/avfoundation/camera/avfcamerautility.h | 2 +- src/plugins/avfoundation/camera/avfcamerautility.mm | 7 ++++--- .../avfoundation/camera/avfcameraviewfindersettingscontrol.mm | 11 ++++++++++- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/camera/avfcamerautility.h b/src/plugins/avfoundation/camera/avfcamerautility.h index 370302b1c..33956fc8a 100644 --- a/src/plugins/avfoundation/camera/avfcamerautility.h +++ b/src/plugins/avfoundation/camera/avfcamerautility.h @@ -161,7 +161,7 @@ QSize qt_device_format_high_resolution(AVCaptureDeviceFormat *format); QSize qt_device_format_pixel_aspect_ratio(AVCaptureDeviceFormat *format); QVector qt_device_format_framerates(AVCaptureDeviceFormat *format); AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDevice, const QSize &res, - FourCharCode preferredFormat); + FourCharCode preferredFormat, bool stillImage = true); AVCaptureDeviceFormat *qt_find_best_framerate_match(AVCaptureDevice *captureDevice, FourCharCode preferredFormat, Float64 fps); diff --git a/src/plugins/avfoundation/camera/avfcamerautility.mm b/src/plugins/avfoundation/camera/avfcamerautility.mm index 8c743dcbc..25ccc4b01 100644 --- a/src/plugins/avfoundation/camera/avfcamerautility.mm +++ b/src/plugins/avfoundation/camera/avfcamerautility.mm @@ -239,7 +239,8 @@ QSize qt_device_format_pixel_aspect_ratio(AVCaptureDeviceFormat *format) AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDevice, const QSize &request, - FourCharCode filter) + FourCharCode filter, + bool stillImage) { Q_ASSERT(captureDevice); Q_ASSERT(!request.isNull() && request.isValid()); @@ -254,7 +255,7 @@ AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDev if (qt_device_format_resolution(format) == request) return format; // iOS only (still images). - if (qt_device_format_high_resolution(format) == request) + if (stillImage && qt_device_format_high_resolution(format) == request) return format; } @@ -272,7 +273,7 @@ AVCaptureDeviceFormat *qt_find_best_resolution_match(AVCaptureDevice *captureDev if (!res.isNull() && res.isValid() && qt_area_sane(res)) pairs << FormatPair(res, format); const QSize highRes(qt_device_format_high_resolution(format)); - if (!highRes.isNull() && highRes.isValid() && qt_area_sane(highRes)) + if (stillImage && !highRes.isNull() && highRes.isValid() && qt_area_sane(highRes)) pairs << FormatPair(highRes, format); } diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm index a77d7de03..0f7a0560b 100644 --- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm +++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm @@ -185,7 +185,16 @@ void AVFCameraViewfinderSettingsControl2::setViewfinderSettings(const QCameraVie return; m_settings = settings; +#if defined(Q_OS_IOS) + bool active = m_service->session()->state() == QCamera::ActiveState; + if (active) + [m_service->session()->captureSession() beginConfiguration]; applySettings(m_settings); + if (active) + [m_service->session()->captureSession() commitConfiguration]; +#else + applySettings(m_settings); +#endif } QVideoFrame::PixelFormat AVFCameraViewfinderSettingsControl2::QtPixelFormatFromCVFormat(unsigned avPixelFormat) @@ -264,7 +273,7 @@ AVCaptureDeviceFormat *AVFCameraViewfinderSettingsControl2::findBestFormatMatch( // Either the exact match (including high resolution for images on iOS) // or a format with a resolution close to the requested one. return qt_find_best_resolution_match(captureDevice, resolution, - m_service->session()->defaultCodec()); + m_service->session()->defaultCodec(), false); } // No resolution requested, what about framerates? -- cgit v1.2.3 From ad3d2afae99506a779ad758f4e7385c9f0b163ba Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Tue, 18 Feb 2020 18:23:31 +0100 Subject: AVF: Don't override AVPlayerLayer's bounds if already set AVPlayerLayer's bounds can be changed while resizing, and should not be overridden by default/native size. Fixes: QTBUG-65536 Change-Id: I771b13e58606663ded80df3665454007d28836b7 Reviewed-by: Timur Pocheptsov --- src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index 1f13fc9bb..ba902a53c 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -875,9 +875,11 @@ void AVFMediaPlayerSession::processLoadStateChange(QMediaPlayer::State newState) // Get the native size of the video, and reset the bounds of the player layer AVPlayerLayer *playerLayer = [static_cast(m_observer) playerLayer]; if (videoTrack && playerLayer) { - playerLayer.bounds = CGRectMake(0.0f, 0.0f, - videoTrack.naturalSize.width, - videoTrack.naturalSize.height); + if (!playerLayer.bounds.size.width || !playerLayer.bounds.size.height) { + playerLayer.bounds = CGRectMake(0.0f, 0.0f, + videoTrack.naturalSize.width, + videoTrack.naturalSize.height); + } if (m_videoOutput && newState != QMediaPlayer::StoppedState) { m_videoOutput->setLayer(playerLayer); -- cgit v1.2.3 From ccde3b75e4ff53e711439e82e1c5640fac225d8e Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Tue, 11 Feb 2020 17:34:32 +0100 Subject: AVF: Introduce adoption of AVAssetResourceLoaderDelegate protocol AVAssetResourceLoaderDelegate allows to load custom resources. Implemented resourceLoader:shouldWaitForLoadingOfRequestedResource to read data from QIODevice. The device should be seekable, and already should have all data available. Since there is a need to know total size of the stream. So the media player will wait for QIODevice::readyRead before loading the resource. Also it requires to have url together with the stream: QMediaPlayer->setMedia(QUrl("does_not_matter.mp3"), buffer); Since the backend uses extension to determine type of the stream. Fixes: QTBUG-69101 Change-Id: I8ab0b69f668ccd67c42a8e5d5c1ad518d3306cce Reviewed-by: Timur Pocheptsov --- .../mediaplayer/avfmediaplayersession.h | 6 +- .../mediaplayer/avfmediaplayersession.mm | 112 +++++++++++++++++++-- 2 files changed, 106 insertions(+), 12 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h index 7a268a3d9..db29e88aa 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.h @@ -67,7 +67,7 @@ public: QMediaPlayer::MediaStatus mediaStatus() const; QMediaContent media() const; - const QIODevice *mediaStream() const; + QIODevice *mediaStream() const; void setMedia(const QMediaContent &content, QIODevice *stream); qint64 position() const; @@ -110,6 +110,9 @@ public Q_SLOTS: void processDurationChange(qint64 duration); + void streamReady(); + void streamDestroyed(); + Q_SIGNALS: void positionChanged(qint64 position); void durationChanged(qint64 duration); @@ -128,6 +131,7 @@ private: void setAudioAvailable(bool available); void setVideoAvailable(bool available); void setSeekable(bool seekable); + void resetStream(QIODevice *stream = nullptr); AVFMediaPlayerService *m_service; AVFVideoOutput *m_videoOutput; diff --git a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm index 1f13fc9bb..6a2dba6a0 100644 --- a/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm +++ b/src/plugins/avfoundation/mediaplayer/avfmediaplayersession.mm @@ -42,6 +42,7 @@ #include "avfvideooutput.h" #include +#include #import @@ -66,7 +67,7 @@ static void *AVFMediaPlayerSessionObserverBufferLikelyToKeepUpContext = &AVFMedi static void *AVFMediaPlayerSessionObserverCurrentItemObservationContext = &AVFMediaPlayerSessionObserverCurrentItemObservationContext; static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext = &AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext; -@interface AVFMediaPlayerSessionObserver : NSObject +@interface AVFMediaPlayerSessionObserver : NSObject @property (readonly, getter=player) AVPlayer* m_player; @property (readonly, getter=playerItem) AVPlayerItem* m_playerItem; @@ -74,7 +75,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext @property (readonly, getter=session) AVFMediaPlayerSession* m_session; - (AVFMediaPlayerSessionObserver *) initWithMediaPlayerSession:(AVFMediaPlayerSession *)session; -- (void) setURL:(NSURL *)url; +- (void) setURL:(NSURL *)url mimeType:(NSString *)mimeType; - (void) unloadMedia; - (void) prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys; - (void) assetFailedToPrepareForPlayback:(NSError *)error; @@ -84,6 +85,7 @@ static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext change:(NSDictionary *)change context:(void *)context; - (void) detatchSession; - (void) dealloc; +- (BOOL) resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest; @end @implementation AVFMediaPlayerSessionObserver @@ -95,6 +97,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext AVPlayerLayer *m_playerLayer; NSURL *m_URL; BOOL m_bufferIsLikelyToKeepUp; + NSData *m_data; + NSString *m_mimeType; } @synthesize m_player, m_playerItem, m_playerLayer, m_session; @@ -109,8 +113,11 @@ static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext return self; } -- (void) setURL:(NSURL *)url +- (void) setURL:(NSURL *)url mimeType:(NSString *)mimeType { + [m_mimeType release]; + m_mimeType = [mimeType retain]; + if (m_URL != url) { [m_URL release]; @@ -122,6 +129,8 @@ static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext // use __block to avoid maintaining strong references on variables captured by the // following block callback __block AVURLAsset *asset = [[AVURLAsset URLAssetWithURL:m_URL options:nil] retain]; + [asset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()]; + __block NSArray *requestedKeys = [[NSArray arrayWithObjects:AVF_TRACKS_KEY, AVF_PLAYABLE_KEY, nil] retain]; __block AVFMediaPlayerSessionObserver *blockSelf = self; @@ -403,9 +412,48 @@ static void *AVFMediaPlayerSessionObserverCurrentItemDurationObservationContext [m_URL release]; } + [m_mimeType release]; [super dealloc]; } +- (BOOL) resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest +{ + Q_UNUSED(resourceLoader); + + if (![loadingRequest.request.URL.scheme isEqualToString:@"iodevice"]) + return NO; + + QIODevice *device = m_session->mediaStream(); + if (!device) + return NO; + + device->seek(loadingRequest.dataRequest.requestedOffset); + if (loadingRequest.contentInformationRequest) { + loadingRequest.contentInformationRequest.contentType = m_mimeType; + loadingRequest.contentInformationRequest.contentLength = device->size(); + loadingRequest.contentInformationRequest.byteRangeAccessSupported = YES; + } + + if (loadingRequest.dataRequest) { + NSInteger requestedLength = loadingRequest.dataRequest.requestedLength; + int maxBytes = qMin(32 * 1064, int(requestedLength)); + char buffer[maxBytes]; + NSInteger submitted = 0; + while (submitted < requestedLength) { + qint64 len = device->read(buffer, maxBytes); + if (len < 1) + break; + + [loadingRequest.dataRequest respondWithData:[NSData dataWithBytes:buffer length:len]]; + submitted += len; + } + + // Finish loading even if not all bytes submitted. + [loadingRequest finishLoading]; + } + + return YES; +} @end AVFMediaPlayerSession::AVFMediaPlayerSession(AVFMediaPlayerService *service, QObject *parent) @@ -483,11 +531,23 @@ QMediaContent AVFMediaPlayerSession::media() const return m_resources; } -const QIODevice *AVFMediaPlayerSession::mediaStream() const +QIODevice *AVFMediaPlayerSession::mediaStream() const { return m_mediaStream; } +static void setURL(void *observer, const QString &url, const QString &mimeType = QString()) +{ + NSString *urlString = [NSString stringWithUTF8String:url.toUtf8().constData()]; + NSURL *nsurl = [NSURL URLWithString:urlString]; + [static_cast(observer) setURL:nsurl mimeType:[NSString stringWithUTF8String:mimeType.toLatin1().constData()]]; +} + +static void setStreamURL(void *observer, const QString &url) +{ + setURL(observer, QLatin1String("iodevice://") + url, QFileInfo(url).suffix()); +} + void AVFMediaPlayerSession::setMedia(const QMediaContent &content, QIODevice *stream) { #ifdef QT_DEBUG_AVF @@ -497,7 +557,7 @@ void AVFMediaPlayerSession::setMedia(const QMediaContent &content, QIODevice *st [static_cast(m_observer) unloadMedia]; m_resources = content; - m_mediaStream = stream; + resetStream(stream); setAudioAvailable(false); setVideoAvailable(false); @@ -508,7 +568,7 @@ void AVFMediaPlayerSession::setMedia(const QMediaContent &content, QIODevice *st const QMediaPlayer::MediaStatus oldMediaStatus = m_mediaStatus; const QMediaPlayer::State oldState = m_state; - if (content.isNull() || content.request().url().isEmpty()) { + if (!m_mediaStream && (content.isNull() || content.request().url().isEmpty())) { m_mediaStatus = QMediaPlayer::NoMedia; if (m_mediaStatus != oldMediaStatus) Q_EMIT mediaStatusChanged(m_mediaStatus); @@ -524,11 +584,16 @@ void AVFMediaPlayerSession::setMedia(const QMediaContent &content, QIODevice *st if (m_mediaStatus != oldMediaStatus) Q_EMIT mediaStatusChanged(m_mediaStatus); - //Load AVURLAsset - //initialize asset using content's URL - NSString *urlString = [NSString stringWithUTF8String:content.request().url().toEncoded().constData()]; - NSURL *url = [NSURL URLWithString:urlString]; - [static_cast(m_observer) setURL:url]; + if (m_mediaStream) { + // If there is a data, try to load it, + // otherwise wait for readyRead. + if (m_mediaStream->size()) + setStreamURL(m_observer, m_resources.request().url().toString()); + } else { + //Load AVURLAsset + //initialize asset using content's URL + setURL(m_observer, m_resources.request().url().toString()); + } m_state = QMediaPlayer::StoppedState; if (m_state != oldState) @@ -967,3 +1032,28 @@ void AVFMediaPlayerSession::processMediaLoadError() Q_EMIT error(QMediaPlayer::FormatError, tr("Failed to load media")); } + +void AVFMediaPlayerSession::streamReady() +{ + setStreamURL(m_observer, m_resources.request().url().toString()); +} + +void AVFMediaPlayerSession::streamDestroyed() +{ + resetStream(nullptr); +} + +void AVFMediaPlayerSession::resetStream(QIODevice *stream) +{ + if (m_mediaStream) { + disconnect(m_mediaStream, &QIODevice::readyRead, this, &AVFMediaPlayerSession::streamReady); + disconnect(m_mediaStream, &QIODevice::destroyed, this, &AVFMediaPlayerSession::streamDestroyed); + } + + m_mediaStream = stream; + + if (m_mediaStream) { + connect(m_mediaStream, &QIODevice::readyRead, this, &AVFMediaPlayerSession::streamReady); + connect(m_mediaStream, &QIODevice::destroyed, this, &AVFMediaPlayerSession::streamDestroyed); + } +} -- cgit v1.2.3 From 12460a14bde44d1ff7bedd75bc87c7f22d096588 Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Wed, 5 Feb 2020 16:52:56 +0100 Subject: WMF: Fix memory leak in MFPlayerSession::getStreamType Receives a pointer to the IMFMediaTypeHandler interface. The caller must release the interface. Fixes: QTBUG-80037 Change-Id: Id0222c9f8ee0f88db8cd53c9492dce053d0bfb35 Reviewed-by: Andy Shaw --- src/plugins/wmf/player/mfplayersession.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/wmf/player/mfplayersession.cpp b/src/plugins/wmf/player/mfplayersession.cpp index 10ba25998..24bfda833 100644 --- a/src/plugins/wmf/player/mfplayersession.cpp +++ b/src/plugins/wmf/player/mfplayersession.cpp @@ -288,6 +288,9 @@ MFPlayerSession::MediaType MFPlayerSession::getStreamType(IMFStreamDescriptor *s } } + if (typeHandler) + typeHandler->Release(); + return Unknown; } -- cgit v1.2.3 From 824acc4bd635aeb4cc2c399a87d78df5f6977fce Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 25 Feb 2020 15:33:34 +0100 Subject: Use Qt::SplitBehavior in preference to QString::SplitBehavior The Qt version was added in 5.14 "for use as eventual replacement for QString::SplitBehavior." Move another step closer to that goal. Change-Id: I72aa0ccae06030043ba40f0f908826e5ca4a31ab Reviewed-by: Simon Hausmann --- .../android/src/mediaplayer/qandroidmetadatareadercontrol.cpp | 8 ++++---- src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp index ef86af896..66eafc765 100644 --- a/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp +++ b/src/plugins/android/src/mediaplayer/qandroidmetadatareadercontrol.cpp @@ -176,12 +176,12 @@ void QAndroidMetaDataReaderControl::extractMetadata(QAndroidMetaDataReaderContro if (!string.isNull()) { metadata.insert(isVideo ? QMediaMetaData::LeadPerformer : QMediaMetaData::ContributingArtist, - string.split('/', QString::SkipEmptyParts)); + string.split('/', Qt::SkipEmptyParts)); } string = retriever.extractMetadata(AndroidMediaMetadataRetriever::Author); if (!string.isNull()) - metadata.insert(QMediaMetaData::Author, string.split('/', QString::SkipEmptyParts)); + metadata.insert(QMediaMetaData::Author, string.split('/', Qt::SkipEmptyParts)); string = retriever.extractMetadata(AndroidMediaMetadataRetriever::Bitrate); if (!string.isNull()) { @@ -196,7 +196,7 @@ void QAndroidMetaDataReaderControl::extractMetadata(QAndroidMetaDataReaderContro string = retriever.extractMetadata(AndroidMediaMetadataRetriever::Composer); if (!string.isNull()) - metadata.insert(QMediaMetaData::Composer, string.split('/', QString::SkipEmptyParts)); + metadata.insert(QMediaMetaData::Composer, string.split('/', Qt::SkipEmptyParts)); string = retriever.extractMetadata(AndroidMediaMetadataRetriever::Date); if (!string.isNull()) @@ -231,7 +231,7 @@ void QAndroidMetaDataReaderControl::extractMetadata(QAndroidMetaDataReaderContro string = retriever.extractMetadata(AndroidMediaMetadataRetriever::Writer); if (!string.isNull()) - metadata.insert(QMediaMetaData::Writer, string.split('/', QString::SkipEmptyParts)); + metadata.insert(QMediaMetaData::Writer, string.split('/', Qt::SkipEmptyParts)); string = retriever.extractMetadata(AndroidMediaMetadataRetriever::Year); if (!string.isNull()) diff --git a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp index f899481f0..de8422b86 100644 --- a/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp +++ b/src/plugins/android/src/wrappers/jni/androidmediaplayer.cpp @@ -271,7 +271,7 @@ void AndroidMediaPlayer::setAudioRole(QAudio::Role role) void AndroidMediaPlayer::setCustomAudioRole(const QString &role) { - QStringList roles = role.split(",", QString::SkipEmptyParts); + QStringList roles = role.split(",", Qt::SkipEmptyParts); int type = 0; // CONTENT_TYPE_UNKNOWN int usage = 0; // USAGE_UNKNOWN -- cgit v1.2.3 From b1430b9e60c51b326fd6eaf1b001916b3b8471f5 Mon Sep 17 00:00:00 2001 From: Ihor Dutchak Date: Thu, 27 Feb 2020 02:55:09 +0200 Subject: Fix AVFVideoWindowControl/AVFVideoWidget content flick on resize When AVPlayerLayer as a backend for AVFVideoWindowControl being resized, macOS adds animation that interferes with Qt resize routines. Disabling animation fixes visual flicks. Task-number: QTBUG-82542 Change-Id: I20a5699431369bcc2da8719b8c4a0151273f9973 Reviewed-by: VaL Doroshchuk --- src/plugins/avfoundation/mediaplayer/avfvideowidget.mm | 17 +++++++++++------ .../avfoundation/mediaplayer/avfvideowindowcontrol.mm | 9 +++++---- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm index be349710c..0987342b4 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowidget.mm @@ -38,12 +38,9 @@ ****************************************************************************/ #include "avfvideowidget.h" -#include -#include -#include -#include -#include +#import +#import #if defined(Q_OS_MACOS) #import @@ -51,6 +48,11 @@ #import #endif +#include +#include +#include +#include + QT_USE_NAMESPACE AVFVideoWidget::AVFVideoWidget(QWidget *parent) @@ -178,5 +180,8 @@ void AVFVideoWidget::updateAspectRatio() void AVFVideoWidget::updatePlayerLayerBounds(const QSize &size) { - m_playerLayer.bounds = CGRectMake(0.0f, 0.0f, (float)size.width(), (float)size.height()); + [CATransaction begin]; + [CATransaction setDisableActions: YES]; // disable animation/flicks + m_playerLayer.bounds = QRect(QPoint(0, 0), size).toCGRect(); + [CATransaction commit]; } diff --git a/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm b/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm index 7fa41fdc2..d61129ec9 100644 --- a/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm +++ b/src/plugins/avfoundation/mediaplayer/avfvideowindowcontrol.mm @@ -40,6 +40,7 @@ #include "avfvideowindowcontrol.h" #include +#import #if QT_HAS_INCLUDE() #include @@ -244,10 +245,10 @@ void AVFVideoWindowControl::updateAspectRatio() void AVFVideoWindowControl::updatePlayerLayerBounds() { if (m_playerLayer) { - CGRect newBounds = CGRectMake(0, 0, - m_displayRect.width(), m_displayRect.height()); - m_playerLayer.bounds = newBounds; - m_playerLayer.position = CGPointMake(m_displayRect.x(), m_displayRect.y()); + [CATransaction begin]; + [CATransaction setDisableActions: YES]; // disable animation/flicks + m_playerLayer.frame = m_displayRect.toCGRect(); + [CATransaction commit]; } } -- cgit v1.2.3 From cdb568606b9eab946c2cacff374a911dc4cfd2f0 Mon Sep 17 00:00:00 2001 From: Val Doroshchuk Date: Wed, 19 Feb 2020 14:38:17 +0100 Subject: AVF: Use supported pixel formats from video surface in Camera QAbstractVideoSurface is waiting for the video frames in supported pixel formats. See QAbstractVideoSurface::supportedPixelFormats(). If the surface does not support device's pixel format, don't show the camera's viewfinder and don't return video frames in unsupported formats. Task-number: QTBUG-82264 Change-Id: I084674f4b093a751bc4f4941047b979766880963 Reviewed-by: Andy Shaw --- .../camera/avfcamerarenderercontrol.mm | 4 +- .../camera/avfcameraviewfindersettingscontrol.mm | 43 ++++++++++++---------- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm index 0359f5d0a..9e1bf3f84 100644 --- a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm +++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm @@ -297,11 +297,9 @@ void AVFCameraRendererControl::setSurface(QAbstractVideoSurface *surface) { if (m_surface != surface) { m_surface = surface; -#ifdef Q_OS_IOS m_supportsTextures = m_surface - ? m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).contains(QVideoFrame::Format_BGRA32) + ? !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty() : false; -#endif Q_EMIT surfaceChanged(surface); } } diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm index 0f7a0560b..dd0393f96 100644 --- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm +++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm @@ -341,7 +341,10 @@ bool AVFCameraViewfinderSettingsControl2::convertPixelFormatIfSupported(QVideoFr if (m_service->videoOutput()->surface()) { const QAbstractVideoSurface *surface = m_service->videoOutput()->surface(); - if (!surface->supportedPixelFormats().contains(qtFormat)) + QAbstractVideoBuffer::HandleType h = m_service->videoOutput()->supportsTextures() + ? QAbstractVideoBuffer::GLTextureHandle + : QAbstractVideoBuffer::NoHandle; + if (!surface->supportedPixelFormats(h).contains(qtFormat)) return false; } @@ -389,21 +392,19 @@ bool AVFCameraViewfinderSettingsControl2::applySettings(const QCameraViewfinderS // format, or if no surface is set, the preferred capture device format const QVector deviceFormats = viewfinderPixelFormats(); - QVideoFrame::PixelFormat pickedFormat = deviceFormats.first(); - QAbstractVideoSurface *surface = m_service->videoOutput()->surface(); + QVideoFrame::PixelFormat pickedFormat = deviceFormats.first(); if (surface) { - if (m_service->videoOutput()->supportsTextures()) { - pickedFormat = QVideoFrame::Format_ARGB32; - } else { - QList surfaceFormats = surface->supportedPixelFormats(); - - for (int i = 0; i < surfaceFormats.count(); ++i) { - const QVideoFrame::PixelFormat surfaceFormat = surfaceFormats.at(i); - if (deviceFormats.contains(surfaceFormat)) { - pickedFormat = surfaceFormat; - break; - } + pickedFormat = QVideoFrame::Format_Invalid; + QAbstractVideoBuffer::HandleType h = m_service->videoOutput()->supportsTextures() + ? QAbstractVideoBuffer::GLTextureHandle + : QAbstractVideoBuffer::NoHandle; + QList surfaceFormats = surface->supportedPixelFormats(h); + for (int i = 0; i < surfaceFormats.count(); ++i) { + const QVideoFrame::PixelFormat surfaceFormat = surfaceFormats.at(i); + if (deviceFormats.contains(surfaceFormat)) { + pickedFormat = surfaceFormat; + break; } } } @@ -411,13 +412,15 @@ bool AVFCameraViewfinderSettingsControl2::applySettings(const QCameraViewfinderS CVPixelFormatFromQtFormat(pickedFormat, avfPixelFormat); } - if (avfPixelFormat != 0) { - NSMutableDictionary *videoSettings = [NSMutableDictionary dictionaryWithCapacity:1]; - [videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat] - forKey:(id)kCVPixelBufferPixelFormatTypeKey]; + NSMutableDictionary *videoSettings = [NSMutableDictionary dictionaryWithCapacity:1]; + [videoSettings setObject:[NSNumber numberWithUnsignedInt:avfPixelFormat] + forKey:(id)kCVPixelBufferPixelFormatTypeKey]; - videoOutput.videoSettings = videoSettings; - } + const AVFConfigurationLock lock(captureDevice); + if (!lock) + qWarning("Failed to set active format (lock failed)"); + + videoOutput.videoSettings = videoSettings; } qt_set_framerate_limits(captureDevice, videoConnection(), settings.minimumFrameRate(), settings.maximumFrameRate()); -- cgit v1.2.3 From 89dc35385037339072159d1e5fc8e325010b2dc0 Mon Sep 17 00:00:00 2001 From: VaL Doroshchuk Date: Fri, 31 Jan 2020 16:20:10 +0100 Subject: GStreamer: Allow using different resolution for capture and viewfinder Currently viewfinder resolution is overridden by image resolution. Fixed to keep it separate. Note, it might be not fully supported by gst camera implementation. Change-Id: Ia04c7819da1410f41aee458d347408f94053170b Reviewed-by: Andy Shaw --- src/plugins/gstreamer/camerabin/camerabinsession.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index 3e505a413..9445bd9d0 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -347,10 +347,12 @@ void CameraBinSession::setupCaptureResolution() // If capture resolution is specified, use it also for the viewfinder to avoid caps negotiation // to fail. if (m_usingWrapperCameraBinSrc) { - if (m_captureMode == QCamera::CaptureStillImage && !imageResolution.isEmpty()) - viewfinderResolution = imageResolution; - else if (m_captureMode == QCamera::CaptureVideo && !videoResolution.isEmpty()) - viewfinderResolution = videoResolution; + if (viewfinderResolution.isEmpty()) { + if (m_captureMode == QCamera::CaptureStillImage && !imageResolution.isEmpty()) + viewfinderResolution = imageResolution; + else if (m_captureMode == QCamera::CaptureVideo && !videoResolution.isEmpty()) + viewfinderResolution = videoResolution; + } // Make sure we don't use incompatible frame rate and pixel format with the new resolution if (viewfinderResolution != m_viewfinderSettings.resolution() && -- cgit v1.2.3 From bc42a549a309603ab4afe28b87406a663702aa24 Mon Sep 17 00:00:00 2001 From: Cheng Sun Date: Wed, 20 Nov 2019 11:23:09 +0000 Subject: QAlsaAudioOutput: leave IdleState as soon as there is data in the source This fixes two bugs: - Once IdleState is entered (due to underflow), one would have to bring the state to ActiveState manually before the backend would start sending new data to ALSA. This behavior is unlike that of QPulseAudioOutput, for example, which will automatically transition out of IdleState once there is data present in the source device. - Whilst in IdleState the audio output would would mark bytes as being consumed from the source device, even though they were not actually being sent to ALSA. Change-Id: If5b4835df0f58b7b15f1800d3a0a1041f1ab845a Reviewed-by: VaL Doroshchuk --- src/plugins/alsa/qalsaaudiooutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/alsa/qalsaaudiooutput.cpp b/src/plugins/alsa/qalsaaudiooutput.cpp index 5c8ae171c..ee5aee989 100644 --- a/src/plugins/alsa/qalsaaudiooutput.cpp +++ b/src/plugins/alsa/qalsaaudiooutput.cpp @@ -707,7 +707,7 @@ bool QAlsaAudioOutput::deviceReady() if(l > 0) { // Got some data to output - if(deviceState != QAudio::ActiveState) + if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return true; qint64 bytesWritten = write(audioBuffer,l); if (bytesWritten != l) -- cgit v1.2.3