diff options
author | Piotr Srebrny <piotr.srebrny@qt.io> | 2021-06-28 12:00:42 +0200 |
---|---|---|
committer | Piotr Srebrny <piotr.srebrny@qt.io> | 2021-08-06 13:44:38 +0200 |
commit | d663c31172e93cb6a54e2704310c5f2da3cd1863 (patch) | |
tree | 5f2dd683ada63205244b9373d2a40c43bd750cb9 | |
parent | df73d1ebb3ab5a7aed3521add0e7fcfefa2a151d (diff) | |
download | qtmultimedia-d663c31172e93cb6a54e2704310c5f2da3cd1863.tar.gz |
Resolve media format and provide encoder settings with record()
Media format and other settings is implicitly resolved at the platform
backend and the API user cannot get information about what codecs
bitrates and other settings are selected for recording.
With this patch the resolved media is provided to the backend with
the record() function and the backend updates the remaining encoding
parameters.
Change-Id: I4876397ada2c257e59ebe8fccdd7587b2a628232
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
21 files changed, 115 insertions, 212 deletions
diff --git a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp index 9b3ee40af..83928ca6a 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidcapturesession.cpp @@ -109,7 +109,7 @@ QMediaRecorder::RecorderState QAndroidCaptureSession::state() const return m_state; } -void QAndroidCaptureSession::start(const QMediaEncoderSettings &, const QUrl &outputLocation) +void QAndroidCaptureSession::start(QMediaEncoderSettings &settings, const QUrl &outputLocation) { if (m_state == QMediaRecorder::RecordingState) return; @@ -133,13 +133,16 @@ void QAndroidCaptureSession::start(const QMediaEncoderSettings &, const QUrl &ou return; } + applySettings(settings); + m_mediaRecorder = new AndroidMediaRecorder; connect(m_mediaRecorder, SIGNAL(error(int,int)), this, SLOT(onError(int,int))); connect(m_mediaRecorder, SIGNAL(info(int,int)), this, SLOT(onInfo(int,int))); // Set audio/video sources if (m_cameraSession) { - updateResolution(); + m_cameraSession->camera()->stopPreviewSynchronous(); + m_cameraSession->applyResolution(settings.videoResolution(), false); m_cameraSession->camera()->unlock(); m_mediaRecorder->setCamera(m_cameraSession->camera()); m_mediaRecorder->setAudioSource(AndroidMediaRecorder::Camcorder); @@ -155,22 +158,22 @@ void QAndroidCaptureSession::start(const QMediaEncoderSettings &, const QUrl &ou m_mediaRecorder->setOutputFormat(m_outputFormat); // Set audio encoder settings - m_mediaRecorder->setAudioChannels(m_encoderSettings.audioChannelCount()); - m_mediaRecorder->setAudioEncodingBitRate(m_encoderSettings.audioBitRate()); - m_mediaRecorder->setAudioSamplingRate(m_encoderSettings.audioSampleRate()); + m_mediaRecorder->setAudioChannels(settings.audioChannelCount()); + m_mediaRecorder->setAudioEncodingBitRate(settings.audioBitRate()); + m_mediaRecorder->setAudioSamplingRate(settings.audioSampleRate()); m_mediaRecorder->setAudioEncoder(m_audioEncoder); // Set video encoder settings if (m_cameraSession) { - m_mediaRecorder->setVideoSize(m_encoderSettings.videoResolution()); - m_mediaRecorder->setVideoFrameRate(qRound(m_encoderSettings.videoFrameRate())); - m_mediaRecorder->setVideoEncodingBitRate(m_encoderSettings.videoBitRate()); + m_mediaRecorder->setVideoSize(settings.videoResolution()); + m_mediaRecorder->setVideoFrameRate(qRound(settings.videoFrameRate())); + m_mediaRecorder->setVideoEncodingBitRate(settings.videoBitRate()); m_mediaRecorder->setVideoEncoder(m_videoEncoder); m_mediaRecorder->setOrientationHint(m_cameraSession->currentCameraRotation()); } - QString extension = m_encoderSettings.mimeType().preferredSuffix(); + QString extension = settings.mimeType().preferredSuffix(); // Set output file QString filePath = m_mediaStorageLocation.generateFileName( @@ -270,15 +273,10 @@ qint64 QAndroidCaptureSession::duration() const return m_duration; } -void QAndroidCaptureSession::applySettings(const QMediaEncoderSettings &settings) +void QAndroidCaptureSession::applySettings(QMediaEncoderSettings &settings) { - const auto flag = m_cameraSession ? QMediaFormat::RequiresVideo - : QMediaFormat::NoFlags; - m_encoderSettings = settings; - m_encoderSettings.resolveFormat(flag); - // container settings - auto fileFormat = m_encoderSettings.mediaFormat().fileFormat(); + auto fileFormat = settings.mediaFormat().fileFormat(); if (!m_cameraSession && fileFormat == QMediaFormat::AAC) { m_outputFormat = AndroidMediaRecorder::AAC_ADTS; } else if (fileFormat == QMediaFormat::Ogg) { @@ -293,18 +291,18 @@ void QAndroidCaptureSession::applySettings(const QMediaEncoderSettings &settings } // audio settings - if (m_encoderSettings.audioChannelCount() <= 0) - m_encoderSettings.setAudioChannelCount(m_defaultSettings.audioChannels); - if (m_encoderSettings.audioBitRate() <= 0) - m_encoderSettings.setAudioBitRate(m_defaultSettings.audioBitRate); - if (m_encoderSettings.audioSampleRate() <= 0) - m_encoderSettings.setAudioSampleRate(m_defaultSettings.audioSampleRate); - - if (m_encoderSettings.audioCodec() == QMediaFormat::AudioCodec::AAC) + if (settings.audioChannelCount() <= 0) + settings.setAudioChannelCount(m_defaultSettings.audioChannels); + if (settings.audioBitRate() <= 0) + settings.setAudioBitRate(m_defaultSettings.audioBitRate); + if (settings.audioSampleRate() <= 0) + settings.setAudioSampleRate(m_defaultSettings.audioSampleRate); + + if (settings.audioCodec() == QMediaFormat::AudioCodec::AAC) m_audioEncoder = AndroidMediaRecorder::AAC; - else if (m_encoderSettings.audioCodec() == QMediaFormat::AudioCodec::Opus) + else if (settings.audioCodec() == QMediaFormat::AudioCodec::Opus) m_audioEncoder = AndroidMediaRecorder::OPUS; - else if (m_encoderSettings.audioCodec() == QMediaFormat::AudioCodec::Vorbis) + else if (settings.audioCodec() == QMediaFormat::AudioCodec::Vorbis) m_audioEncoder = AndroidMediaRecorder::VORBIS; else m_audioEncoder = m_defaultSettings.audioEncoder; @@ -312,11 +310,11 @@ void QAndroidCaptureSession::applySettings(const QMediaEncoderSettings &settings // video settings if (m_cameraSession && m_cameraSession->camera()) { - if (m_encoderSettings.videoResolution().isEmpty()) { - m_encoderSettings.setVideoResolution(m_defaultSettings.videoResolution); - } else if (!m_supportedResolutions.contains(m_encoderSettings.videoResolution())) { + if (settings.videoResolution().isEmpty()) { + settings.setVideoResolution(m_defaultSettings.videoResolution); + } else if (!m_supportedResolutions.contains(settings.videoResolution())) { // if the requested resolution is not supported, find the closest one - QSize reqSize = m_encoderSettings.videoResolution(); + QSize reqSize = settings.videoResolution(); int reqPixelCount = reqSize.width() * reqSize.height(); QList<int> supportedPixelCounts; for (int i = 0; i < m_supportedResolutions.size(); ++i) { @@ -324,19 +322,19 @@ void QAndroidCaptureSession::applySettings(const QMediaEncoderSettings &settings supportedPixelCounts.append(s.width() * s.height()); } int closestIndex = qt_findClosestValue(supportedPixelCounts, reqPixelCount); - m_encoderSettings.setVideoResolution(m_supportedResolutions.at(closestIndex)); + settings.setVideoResolution(m_supportedResolutions.at(closestIndex)); } - if (m_encoderSettings.videoFrameRate() <= 0) - m_encoderSettings.setVideoFrameRate(m_defaultSettings.videoFrameRate); - if (m_encoderSettings.videoBitRate() <= 0) - m_encoderSettings.setVideoBitRate(m_defaultSettings.videoBitRate); + if (settings.videoFrameRate() <= 0) + settings.setVideoFrameRate(m_defaultSettings.videoFrameRate); + if (settings.videoBitRate() <= 0) + settings.setVideoBitRate(m_defaultSettings.videoBitRate); - if (m_encoderSettings.videoCodec() == QMediaFormat::VideoCodec::H264) + if (settings.videoCodec() == QMediaFormat::VideoCodec::H264) m_videoEncoder = AndroidMediaRecorder::H264; - else if (m_encoderSettings.videoCodec() == QMediaFormat::VideoCodec::H265) + else if (settings.videoCodec() == QMediaFormat::VideoCodec::H265) m_videoEncoder = AndroidMediaRecorder::HEVC; - else if (m_encoderSettings.videoCodec() == QMediaFormat::VideoCodec::MPEG4) + else if (settings.videoCodec() == QMediaFormat::VideoCodec::MPEG4) m_videoEncoder = AndroidMediaRecorder::MPEG_4_SP; else m_videoEncoder = m_defaultSettings.videoEncoder; @@ -344,12 +342,6 @@ void QAndroidCaptureSession::applySettings(const QMediaEncoderSettings &settings } } -void QAndroidCaptureSession::updateResolution() -{ - m_cameraSession->camera()->stopPreviewSynchronous(); - m_cameraSession->applyResolution(m_encoderSettings.videoResolution(), false); -} - void QAndroidCaptureSession::restartViewfinder() { if (!m_cameraSession) @@ -399,8 +391,6 @@ void QAndroidCaptureSession::onCameraOpened() std::sort(m_supportedResolutions.begin(), m_supportedResolutions.end(), qt_sizeLessThan); std::sort(m_supportedFramerates.begin(), m_supportedFramerates.end()); - - applySettings(m_encoderSettings); } QAndroidCaptureSession::CaptureProfile QAndroidCaptureSession::getProfile(int id) diff --git a/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h b/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h index 23c96d867..1673710a6 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h +++ b/src/multimedia/platform/android/mediacapture/qandroidcapturesession_p.h @@ -80,7 +80,7 @@ public: QMediaRecorder::RecorderState state() const; - void start(const QMediaEncoderSettings &settings, const QUrl &outputLocation); + void start(QMediaEncoderSettings &settings, const QUrl &outputLocation); void stop(bool error = false); qint64 duration() const; @@ -89,8 +89,6 @@ public: void setMediaEncoder(QAndroidMediaEncoder *encoder) { m_mediaEncoder = encoder; } - void applySettings(const QMediaEncoderSettings &settings); - void stateChanged(QMediaRecorder::RecorderState state) { if (m_mediaEncoder) m_mediaEncoder->stateChanged(state); @@ -119,6 +117,8 @@ private Q_SLOTS: void onInfo(int what, int extra); private: + void applySettings(QMediaEncoderSettings &settings); + struct CaptureProfile { AndroidMediaRecorder::OutputFormat outputFormat; QString outputFileExtension; @@ -152,7 +152,6 @@ private: CaptureProfile getProfile(int id); - void updateResolution(); void restartViewfinder(); QAndroidMediaEncoder *m_mediaEncoder = nullptr; diff --git a/src/multimedia/platform/android/mediacapture/qandroidmediaencoder.cpp b/src/multimedia/platform/android/mediacapture/qandroidmediaencoder.cpp index 7daa89262..5e7ae990d 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidmediaencoder.cpp +++ b/src/multimedia/platform/android/mediacapture/qandroidmediaencoder.cpp @@ -66,13 +66,7 @@ qint64 QAndroidMediaEncoder::duration() const } -void QAndroidMediaEncoder::applySettings(const QMediaEncoderSettings &settings) -{ - if (m_session) - m_session->applySettings(settings); -} - -void QAndroidMediaEncoder::record(const QMediaEncoderSettings &settings) +void QAndroidMediaEncoder::record(QMediaEncoderSettings &settings) { if (m_session) m_session->start(settings, outputLocation()); diff --git a/src/multimedia/platform/android/mediacapture/qandroidmediaencoder_p.h b/src/multimedia/platform/android/mediacapture/qandroidmediaencoder_p.h index 21525e23b..6c6160ca9 100644 --- a/src/multimedia/platform/android/mediacapture/qandroidmediaencoder_p.h +++ b/src/multimedia/platform/android/mediacapture/qandroidmediaencoder_p.h @@ -67,12 +67,11 @@ public: bool isLocationWritable(const QUrl &location) const override; QMediaRecorder::RecorderState state() const override; qint64 duration() const override; - void applySettings(const QMediaEncoderSettings &settings) override; void setCaptureSession(QPlatformMediaCaptureSession *session); void setOutputLocation(const QUrl &location) override; - void record(const QMediaEncoderSettings &settings) override; + void record(QMediaEncoderSettings &settings) override; void stop() override; private: diff --git a/src/multimedia/platform/darwin/camera/avfmediaencoder.mm b/src/multimedia/platform/darwin/camera/avfmediaencoder.mm index c6ad84712..9399ed2a1 100644 --- a/src/multimedia/platform/darwin/camera/avfmediaencoder.mm +++ b/src/multimedia/platform/darwin/camera/avfmediaencoder.mm @@ -409,25 +409,12 @@ NSDictionary *avfVideoSettings(QMediaEncoderSettings &encoderSettings, AVCapture return videoSettings; } -void AVFMediaEncoder::applySettings(const QMediaEncoderSettings &settings) +void AVFMediaEncoder::applySettings(QMediaEncoderSettings &settings) { - m_settings = settings; - - if (!m_service || !m_service->session()) - return; AVFCameraSession *session = m_service->session(); - if (m_state != QMediaRecorder::StoppedState) - return; - - const auto flag = (session->activecameraDevice().isNull()) - ? QMediaFormat::NoFlags - : QMediaFormat::RequiresVideo; - - m_settings.resolveFormat(flag); - // audio settings - m_audioSettings = avfAudioSettings(m_settings); + m_audioSettings = avfAudioSettings(settings); if (m_audioSettings) [m_audioSettings retain]; @@ -437,7 +424,7 @@ void AVFMediaEncoder::applySettings(const QMediaEncoderSettings &settings) return; const AVFConfigurationLock lock(device); // prevents activeFormat from being overridden AVCaptureConnection *conn = [session->videoOutput()->videoDataOutput() connectionWithMediaType:AVMediaTypeVideo]; - m_videoSettings = avfVideoSettings(m_settings, device, conn); + m_videoSettings = avfVideoSettings(settings, device, conn); if (m_videoSettings) [m_videoSettings retain]; } @@ -481,7 +468,7 @@ void AVFMediaEncoder::setCaptureSession(QPlatformMediaCaptureSession *session) onCameraChanged(); } -void AVFMediaEncoder::record(const QMediaEncoderSettings &) +void AVFMediaEncoder::record(QMediaEncoderSettings &settings) { if (!m_service || !m_service->session()) { qWarning() << Q_FUNC_INFO << "Encoder is not set to a capture session"; @@ -497,7 +484,7 @@ void AVFMediaEncoder::record(const QMediaEncoderSettings &) return; m_service->session()->setActive(true); - const bool audioOnly = m_settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified; + const bool audioOnly = settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified; AVCaptureSession *session = m_service->session()->captureSession(); float rotation = 0; @@ -528,7 +515,7 @@ void AVFMediaEncoder::record(const QMediaEncoderSettings &) const QUrl fileURL(QUrl::fromLocalFile(m_storageLocation.generateFileName(path, audioOnly ? AVFStorageLocation::Audio : AVFStorageLocation::Video, QLatin1String("clip_"), - m_settings.mimeType().preferredSuffix()))); + settings.mimeType().preferredSuffix()))); NSURL *nsFileURL = fileURL.toNSURL(); if (!nsFileURL) { @@ -551,7 +538,7 @@ void AVFMediaEncoder::record(const QMediaEncoderSettings &) return; } - applySettings(m_settings); + applySettings(settings); // We stop session now so that no more frames for renderer's queue // generated, will restart in assetWriterStarted. @@ -561,7 +548,7 @@ void AVFMediaEncoder::record(const QMediaEncoderSettings &) cameraService:m_service audioSettings:m_audioSettings videoSettings:m_videoSettings - fileFormat:m_settings.fileFormat() + fileFormat:settings.fileFormat() transform:CGAffineTransformMakeRotation(qDegreesToRadians(rotation))]) { m_state = QMediaRecorder::RecordingState; diff --git a/src/multimedia/platform/darwin/camera/avfmediaencoder_p.h b/src/multimedia/platform/darwin/camera/avfmediaencoder_p.h index d7ba2cf01..33c438ace 100644 --- a/src/multimedia/platform/darwin/camera/avfmediaencoder_p.h +++ b/src/multimedia/platform/darwin/camera/avfmediaencoder_p.h @@ -84,10 +84,7 @@ public: qint64 duration() const override; - void applySettings(const QMediaEncoderSettings &settings) override; - void unapplySettings(); - - void record(const QMediaEncoderSettings &settings) override; + void record(QMediaEncoderSettings &settings) override; void stop() override; void setMetaData(const QMediaMetaData &) override; @@ -100,6 +97,8 @@ public: void updateDuration(qint64 duration); private: + void applySettings(QMediaEncoderSettings &settings); + void unapplySettings(); Q_INVOKABLE void assetWriterStarted(); Q_INVOKABLE void assetWriterFinished(); @@ -117,7 +116,6 @@ private: AVFStorageLocation m_storageLocation; QMediaRecorder::RecorderState m_state; - QMediaEncoderSettings m_settings; QMediaMetaData m_metaData; diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder.cpp b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder.cpp index 71c9d3a39..158e47075 100644 --- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder.cpp +++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder.cpp @@ -68,7 +68,6 @@ QGstreamerMediaEncoder::~QGstreamerMediaEncoder() { gstPipeline.removeMessageFilter(this); gstPipeline.setStateSync(GST_STATE_NULL); - QObject::disconnect(cameraChanged); } bool QGstreamerMediaEncoder::isLocationWritable(const QUrl &) const @@ -234,16 +233,22 @@ static GstEncodingContainerProfile *createEncodingProfile(const QMediaEncoderSet return containerProfile; } -void QGstreamerMediaEncoder::record(const QMediaEncoderSettings &) +void QGstreamerMediaEncoder::record(QMediaEncoderSettings &settings) { if (!m_session || state() != QMediaRecorder::StoppedState) return; + auto *encodingProfile = createEncodingProfile(settings); + g_object_set (gstEncoder.object(), "profile", encodingProfile, nullptr); + gst_encoding_profile_unref(encodingProfile); + + const auto audioOnly = settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified; + // create new encoder QString location = outputLocation().toLocalFile(); if (outputLocation().isEmpty()) { - QString container = m_resolvedSettings.mimeType().preferredSuffix(); - location = generateFileName(defaultDir(), container); + QString container = settings.mimeType().preferredSuffix(); + location = generateFileName(defaultDir(audioOnly), container); } QUrl actualSink = QUrl::fromLocalFile(QDir::currentPath()).resolved(location); qCDebug(qLcMediaEncoder) << "recording new video to" << actualSink; @@ -262,7 +267,7 @@ void QGstreamerMediaEncoder::record(const QMediaEncoderSettings &) audioSrcPad.link(audioPad); } - if (m_resolvedSettings.videoCodec() != QMediaFormat::VideoCodec::Unspecified) { + if (settings.videoCodec() != QMediaFormat::VideoCodec::Unspecified) { videoSrcPad = m_session->getVideoPad(); if (!videoSrcPad.isNull()) { QGstPad videoPad = gstEncoder.getRequestPad("video_%u"); @@ -347,21 +352,6 @@ void QGstreamerMediaEncoder::finalize() gstPipeline.endConfig(); } -void QGstreamerMediaEncoder::applySettings(const QMediaEncoderSettings &settings) -{ - if (!m_session) - return; - - const auto flag = m_session->camera() ? QMediaFormat::RequiresVideo - : QMediaFormat::NoFlags; - m_resolvedSettings = settings; - m_resolvedSettings.resolveFormat(flag); - - auto *encodingProfile = createEncodingProfile(m_resolvedSettings); - g_object_set (gstEncoder.object(), "profile", encodingProfile, nullptr); - gst_encoding_profile_unref(encodingProfile); -} - void QGstreamerMediaEncoder::setMetaData(const QMediaMetaData &metaData) { if (!m_session) @@ -388,7 +378,6 @@ void QGstreamerMediaEncoder::setCaptureSession(QPlatformMediaCaptureSession *ses gstPipeline.remove(gstEncoder); gstPipeline.remove(gstFileSink); heartbeat.disconnect(); - QObject::disconnect(cameraChanged); gstPipeline.removeMessageFilter(this); } @@ -408,17 +397,13 @@ void QGstreamerMediaEncoder::setCaptureSession(QPlatformMediaCaptureSession *ses gstEncoder.link(gstFileSink); gstEncoder.lockState(true); gstFileSink.lockState(true); // ### enough with the encoder? - - // ensure we have a usable format - applySettings(QMediaEncoderSettings()); - cameraChanged = QObject::connect(m_session, &QGstreamerMediaCapture::cameraChanged, [this]() { applySettings(m_resolvedSettings); }); } -QDir QGstreamerMediaEncoder::defaultDir() const +QDir QGstreamerMediaEncoder::defaultDir(bool audioOnly) const { QStringList dirCandidates; - if (m_resolvedSettings.videoCodec() != QMediaFormat::VideoCodec::Unspecified) + if (!audioOnly) dirCandidates << QStandardPaths::writableLocation(QStandardPaths::MoviesLocation); else dirCandidates << QStandardPaths::writableLocation(QStandardPaths::MusicLocation); diff --git a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder_p.h b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder_p.h index a6dc30067..6c9cdc92b 100644 --- a/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder_p.h +++ b/src/multimedia/platform/gstreamer/mediacapture/qgstreamermediaencoder_p.h @@ -76,8 +76,7 @@ public: qint64 duration() const override; - void applySettings(const QMediaEncoderSettings &settings) override; - void record(const QMediaEncoderSettings &settings) override; + void record(QMediaEncoderSettings &settings) override; void pause() override; void resume() override; void stop() override; @@ -95,10 +94,9 @@ public: private: void handleSessionError(QMediaRecorder::Error code, const QString &description); void finalize(); - QDir defaultDir() const; + QDir defaultDir(bool audioOnly) const; QString generateFileName(const QDir &dir, const QString &ext) const; - QMediaEncoderSettings m_resolvedSettings; QGstreamerMediaCapture *m_session = nullptr; QGstreamerMetaData m_metaData; QElapsedTimer m_duration; @@ -110,8 +108,6 @@ private: QGstPad audioSrcPad; QGstPad videoSrcPad; - - QMetaObject::Connection cameraChanged; }; QT_END_NAMESPACE diff --git a/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol.cpp b/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol.cpp index d79a09358..a90ae33be 100644 --- a/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol.cpp +++ b/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol.cpp @@ -112,16 +112,12 @@ qreal BbCameraMediaRecorderControl::volume() const return (level / 100); } -void BbCameraMediaRecorderControl::applySettings(const QMediaEncoderSettings &) +void BbCameraMediaRecorderControl::record(QMediaEncoderSettings &) { - if (m_session) + if (m_session) { m_session->applyVideoSettings(); -} - -void BbCameraMediaRecorderControl::record(const QMediaEncoderSettings &) -{ - if (m_session) m_session->startVideoRecording(outputLocation()); + } } void BbCameraMediaRecorderControl::stop() diff --git a/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol_p.h b/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol_p.h index ea9712acf..5ea453a0b 100644 --- a/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol_p.h +++ b/src/multimedia/platform/qnx/camera/bbcameramediarecordercontrol_p.h @@ -67,8 +67,7 @@ public: qint64 duration() const override; bool isMuted() const override; qreal volume() const override; - void applySettings(const QMediaEncoderSettings &settings) override; - void record(const QMediaEncoderSettings &settings) override; + void record(QMediaEncoderSettings &settings) override; void stop() override; diff --git a/src/multimedia/platform/qplatformmediaencoder.cpp b/src/multimedia/platform/qplatformmediaencoder.cpp index 2a15db708..8f08fab4e 100644 --- a/src/multimedia/platform/qplatformmediaencoder.cpp +++ b/src/multimedia/platform/qplatformmediaencoder.cpp @@ -103,7 +103,7 @@ QPlatformMediaEncoder::QPlatformMediaEncoder(QMediaRecorder *parent) */ /*! - \fn void QPlatformMediaEncoder::record(const QMediaEncoderSettings &settings) + \fn void QPlatformMediaEncoder::record(QMediaEncoderSettings &settings) Start media recording. */ @@ -132,14 +132,6 @@ void QPlatformMediaEncoder::resume() { Stop media recording */ - -/*! - \fn QPlatformMediaEncoder::applySettings(const QMediaEncoderSettings &) - - Commits the encoder settings and performs pre-initialization to reduce delays when recording - is started. -*/ - /*! \fn void QPlatformMediaEncoder::stateChanged(QMediaRecorder::RecorderState state) diff --git a/src/multimedia/platform/qplatformmediaencoder_p.h b/src/multimedia/platform/qplatformmediaencoder_p.h index d2ae73bf7..354998b5c 100644 --- a/src/multimedia/platform/qplatformmediaencoder_p.h +++ b/src/multimedia/platform/qplatformmediaencoder_p.h @@ -140,15 +140,13 @@ public: virtual bool isLocationWritable(const QUrl &location) const = 0; virtual QMediaRecorder::RecorderState state() const { return m_state; } - virtual void record(const QMediaEncoderSettings &settings) = 0; + virtual void record(QMediaEncoderSettings &settings) = 0; virtual void pause(); virtual void resume(); virtual void stop() = 0; virtual qint64 duration() const = 0; - virtual void applySettings(const QMediaEncoderSettings &) {}; - virtual void setMetaData(const QMediaMetaData &) {} virtual QMediaMetaData metaData() const { return {}; } diff --git a/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession.cpp b/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession.cpp index 2b213df2c..701579fa9 100644 --- a/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession.cpp +++ b/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession.cpp @@ -230,7 +230,7 @@ void QWindowsMediaDeviceSession::setAudioOutput(QAudioOutput *output) connect(m_audioOutput, &QAudioOutput::deviceChanged, this, &QWindowsMediaDeviceSession::audioOutputDeviceChanged); } -bool QWindowsMediaDeviceSession::startRecording(const QMediaEncoderSettings &settings, const QString &fileName, bool audioOnly) +bool QWindowsMediaDeviceSession::startRecording(QMediaEncoderSettings &settings, const QString &fileName, bool audioOnly) { GUID container = QWindowsMultimediaUtils::containerForVideoFileFormat(settings.mediaFormat().fileFormat()); GUID videoFormat = QWindowsMultimediaUtils::videoFormatForCodec(settings.videoCodec()); @@ -244,20 +244,32 @@ bool QWindowsMediaDeviceSession::startRecording(const QMediaEncoderSettings &set } else { width = m_mediaDeviceReader->frameWidth(); height = m_mediaDeviceReader->frameHeight(); + settings.setVideoResolution(QSize(int(width), int(height))); } - qreal fps = settings.videoFrameRate(); - qreal frameRate = (fps > 0) ? fps : m_mediaDeviceReader->frameRate(); + qreal frameRate = settings.videoFrameRate(); + if (frameRate <= 0) { + frameRate = m_mediaDeviceReader->frameRate(); + settings.setVideoFrameRate(frameRate); + } auto quality = settings.quality(); - int vbrate = settings.videoBitRate(); - int abrate = settings.audioBitRate(); - UINT32 videoBitRate = (vbrate > 0) ? UINT32(vbrate) - : estimateVideoBitRate(videoFormat, width, height, frameRate, quality); + UINT32 videoBitRate = 0; + if (settings.videoBitRate() > 0) { + videoBitRate = UINT32(settings.videoBitRate()); + } else { + videoBitRate = estimateVideoBitRate(videoFormat, width, height, frameRate, quality); + settings.setVideoBitRate(int(videoBitRate)); + } - UINT32 audioBitRate = (abrate > 0) ? UINT32(abrate) - : estimateAudioBitRate(audioFormat, quality); + UINT32 audioBitRate = 0; + if (settings.audioBitRate() > 0) { + audioBitRate = UINT32(settings.audioBitRate()); + } else { + audioBitRate = estimateAudioBitRate(audioFormat, quality); + settings.setAudioBitRate(int(audioBitRate)); + } return m_mediaDeviceReader->startRecording(fileName, container, audioOnly ? GUID_NULL : videoFormat, videoBitRate, width, height, frameRate, diff --git a/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession_p.h b/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession_p.h index 8f55ec8b7..93642d676 100644 --- a/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession_p.h +++ b/src/multimedia/platform/windows/mediacapture/qwindowsmediadevicesession_p.h @@ -95,7 +95,7 @@ public: void setAudioInput(QAudioInput *input); void setAudioOutput(QAudioOutput *output); - bool startRecording(const QMediaEncoderSettings &settings, const QString &fileName, bool audioOnly); + bool startRecording(QMediaEncoderSettings &settings, const QString &fileName, bool audioOnly); void stopRecording(); bool pauseRecording(); bool resumeRecording(); diff --git a/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder.cpp b/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder.cpp index 303af31bb..84c520444 100644 --- a/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder.cpp +++ b/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder.cpp @@ -71,7 +71,7 @@ qint64 QWindowsMediaEncoder::duration() const return m_duration; } -void QWindowsMediaEncoder::record(const QMediaEncoderSettings &settings) +void QWindowsMediaEncoder::record(QMediaEncoderSettings &settings) { if (!m_captureService || !m_mediaDeviceSession) { qWarning() << Q_FUNC_INFO << "Encoder is not set to a capture session"; @@ -88,11 +88,7 @@ void QWindowsMediaEncoder::record(const QMediaEncoderSettings &settings) return; } - const auto audioOnly = m_mediaDeviceSession->activeCamera().isNull(); - - auto resolvedSettings = settings; - resolvedSettings.resolveFormat(audioOnly ? QMediaFormat::NoFlags - : QMediaFormat::RequiresVideo); + const auto audioOnly = settings.videoCodec() == QMediaFormat::VideoCodec::Unspecified; const QString path = (outputLocation().scheme() == QLatin1String("file") ? outputLocation().path() : outputLocation().toString()); @@ -101,9 +97,9 @@ void QWindowsMediaEncoder::record(const QMediaEncoderSettings &settings) ? QWindowsStorageLocation::Audio : QWindowsStorageLocation::Video, QLatin1String("clip_"), - resolvedSettings.mimeType().preferredSuffix()); + settings.mimeType().preferredSuffix()); - if (m_mediaDeviceSession->startRecording(resolvedSettings, m_fileName, audioOnly)) { + if (m_mediaDeviceSession->startRecording(settings, m_fileName, audioOnly)) { m_state = QMediaRecorder::RecordingState; diff --git a/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder_p.h b/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder_p.h index c71412e9c..199561b86 100644 --- a/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder_p.h +++ b/src/multimedia/platform/windows/mediacapture/qwindowsmediaencoder_p.h @@ -79,7 +79,7 @@ public: void setCaptureSession(QPlatformMediaCaptureSession *session); - void record(const QMediaEncoderSettings &settings) override; + void record(QMediaEncoderSettings &settings) override; void pause() override; void resume() override; void stop() override; diff --git a/src/multimedia/recording/qmediarecorder.cpp b/src/multimedia/recording/qmediarecorder.cpp index c4bc032bd..fed88fb1d 100644 --- a/src/multimedia/recording/qmediarecorder.cpp +++ b/src/multimedia/recording/qmediarecorder.cpp @@ -78,22 +78,6 @@ QMediaRecorderPrivate::QMediaRecorderPrivate() encoderSettings.mimeType(); } -void QMediaRecorderPrivate::applySettingsLater() -{ - if (control && !settingsChanged) { - settingsChanged = true; - QMetaObject::invokeMethod(q_func(), "_q_applySettings", Qt::QueuedConnection); - } -} - -void QMediaRecorderPrivate::_q_applySettings() -{ - if (control && settingsChanged) { - settingsChanged = false; - control->applySettings(encoderSettings); - } -} - QString QMediaRecorderPrivate::msgFailedStartRecording() { return QMediaRecorder::tr("Failed to start recording"); @@ -146,8 +130,6 @@ void QMediaRecorder::setCaptureSession(QMediaCaptureSession *session) return; platformSession->setMediaEncoder(d->control); - d->applySettingsLater(); - } /*! @@ -271,10 +253,22 @@ void QMediaRecorder::record() if (d->control->state() == QMediaRecorder::PausedState) { d->control->resume(); } else { - d->control->applySettings(d->encoderSettings); + auto oldMediaFormat = d->encoderSettings.mediaFormat(); + auto camera = d->captureSession->camera(); + auto flags = camera && camera->isActive() ? QMediaFormat::RequiresVideo + : QMediaFormat::NoFlags; + d->encoderSettings.resolveFormat(flags); d->control->clearActualLocation(); d->control->clearError(); + + auto settings = d->encoderSettings; d->control->record(d->encoderSettings); + + if (settings != d->encoderSettings) + emit encoderSettingsChanged(); + + if (oldMediaFormat != d->encoderSettings.mediaFormat()) + emit mediaFormatChanged(); } } @@ -450,7 +444,6 @@ void QMediaRecorder::setMediaFormat(const QMediaFormat &format) if (d->encoderSettings.mediaFormat() == format) return; d->encoderSettings.setMediaFormat(format); - d->applySettingsLater(); emit mediaFormatChanged(); } @@ -480,7 +473,6 @@ void QMediaRecorder::setEncodingMode(EncodingMode mode) if (d->encoderSettings.encodingMode() == mode) return; d->encoderSettings.setEncodingMode(mode); - d->applySettingsLater(); emit encodingModeChanged(); } @@ -496,7 +488,6 @@ void QMediaRecorder::setQuality(Quality quality) if (d->encoderSettings.quality() == quality) return; d->encoderSettings.setQuality(quality); - d->applySettingsLater(); emit qualityChanged(); } @@ -522,7 +513,6 @@ void QMediaRecorder::setVideoResolution(const QSize &size) if (d->encoderSettings.videoResolution() == size) return; d->encoderSettings.setVideoResolution(size); - d->applySettingsLater(); emit videoResolutionChanged(); } @@ -554,7 +544,6 @@ void QMediaRecorder::setVideoFrameRate(qreal frameRate) if (d->encoderSettings.videoFrameRate() == frameRate) return; d->encoderSettings.setVideoFrameRate(frameRate); - d->applySettingsLater(); emit videoFrameRateChanged(); } @@ -576,7 +565,6 @@ void QMediaRecorder::setVideoBitRate(int bitRate) if (d->encoderSettings.videoBitRate() == bitRate) return; d->encoderSettings.setVideoBitRate(bitRate); - d->applySettingsLater(); emit videoBitRateChanged(); } @@ -598,7 +586,6 @@ void QMediaRecorder::setAudioBitRate(int bitRate) if (d->encoderSettings.audioBitRate() == bitRate) return; d->encoderSettings.setAudioBitRate(bitRate); - d->applySettingsLater(); emit audioBitRateChanged(); } @@ -623,7 +610,6 @@ void QMediaRecorder::setAudioChannelCount(int channels) if (d->encoderSettings.audioChannelCount() == channels) return; d->encoderSettings.setAudioChannelCount(channels); - d->applySettingsLater(); emit audioChannelCountChanged(); } @@ -648,7 +634,6 @@ void QMediaRecorder::setAudioSampleRate(int sampleRate) if (d->encoderSettings.audioSampleRate() == sampleRate) return; d->encoderSettings.setAudioSampleRate(sampleRate); - d->applySettingsLater(); emit audioSampleRateChanged(); } diff --git a/src/multimedia/recording/qmediarecorder.h b/src/multimedia/recording/qmediarecorder.h index 48f86a32a..85ce5365e 100644 --- a/src/multimedia/recording/qmediarecorder.h +++ b/src/multimedia/recording/qmediarecorder.h @@ -193,7 +193,6 @@ private: void setCaptureSession(QMediaCaptureSession *session); Q_DISABLE_COPY(QMediaRecorder) Q_DECLARE_PRIVATE(QMediaRecorder) - Q_PRIVATE_SLOT(d_func(), void _q_applySettings()) }; QT_END_NAMESPACE diff --git a/src/multimedia/recording/qmediarecorder_p.h b/src/multimedia/recording/qmediarecorder_p.h index 5039d3d4c..e0b61ace0 100644 --- a/src/multimedia/recording/qmediarecorder_p.h +++ b/src/multimedia/recording/qmediarecorder_p.h @@ -69,8 +69,6 @@ class QMediaRecorderPrivate public: QMediaRecorderPrivate(); - void applySettingsLater(); - static QString msgFailedStartRecording(); QMediaCaptureSession *captureSession = nullptr; @@ -80,8 +78,6 @@ public: QMediaEncoderSettings encoderSettings; - void _q_applySettings(); - QMediaRecorder *q_ptr = nullptr; }; diff --git a/tests/auto/unit/mockbackend/qmockmediaencoder.h b/tests/auto/unit/mockbackend/qmockmediaencoder.h index 988ce8f10..ca6c3ef7c 100644 --- a/tests/auto/unit/mockbackend/qmockmediaencoder.h +++ b/tests/auto/unit/mockbackend/qmockmediaencoder.h @@ -40,8 +40,7 @@ public: QMockMediaEncoder(QMediaRecorder *parent): QPlatformMediaEncoder(parent), m_state(QMediaRecorder::StoppedState), - m_position(0), - m_settingAppliedCount(0) + m_position(0) { } @@ -60,12 +59,6 @@ public: return m_position; } - void applySettings(const QMediaEncoderSettings &settings) override - { - m_settings = settings; - m_settingAppliedCount++; - } - virtual void setMetaData(const QMediaMetaData &m) override { m_metaData = m; @@ -76,9 +69,10 @@ public: using QPlatformMediaEncoder::error; public: - void record(const QMediaEncoderSettings &) override + void record(QMediaEncoderSettings &settings) override { m_state = QMediaRecorder::RecordingState; + m_settings = settings; m_position=1; emit stateChanged(m_state); emit durationChanged(m_position); @@ -111,7 +105,6 @@ public: QMediaRecorder::RecorderState m_state; QMediaEncoderSettings m_settings; qint64 m_position; - int m_settingAppliedCount; }; #endif // MOCKRECORDERCONTROL_H diff --git a/tests/auto/unit/multimedia/qmediarecorder/tst_qmediarecorder.cpp b/tests/auto/unit/multimedia/qmediarecorder/tst_qmediarecorder.cpp index 36fd0a16d..ceed4eeff 100644 --- a/tests/auto/unit/multimedia/qmediarecorder/tst_qmediarecorder.cpp +++ b/tests/auto/unit/multimedia/qmediarecorder/tst_qmediarecorder.cpp @@ -361,22 +361,11 @@ void tst_QMediaRecorder::testSettingsApplied() session.setRecorder(&encoder); auto *mock = mockIntegration->lastCaptureService()->mockControl; - //if the media recorder is not configured after construction - //the settings are applied in the next event loop - QCOMPARE(mock->m_settingAppliedCount, 0); - QTRY_COMPARE(mock->m_settingAppliedCount, 1); - encoder.setVideoResolution(640,480); - QCOMPARE(mock->m_settingAppliedCount, 1); - QTRY_COMPARE(mock->m_settingAppliedCount, 2); - //encoder settings are applied before recording if changed encoder.setQuality(QMediaRecorder::VeryHighQuality); - - QCOMPARE(mock->m_settingAppliedCount, 2); encoder.record(); - QCOMPARE(mock->m_settingAppliedCount, 3); encoder.stop(); } |