diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/multimedia/audio/qsoundeffectwithplayer.cpp | 21 | ||||
| -rw-r--r-- | src/multimedia/audio/qsoundeffectwithplayer_p.h | 2 | ||||
| -rw-r--r-- | src/multimedia/video/qvideoframe.cpp | 6 | ||||
| -rw-r--r-- | src/multimedia/video/qvideotexturehelper.cpp | 7 | ||||
| -rw-r--r-- | src/multimediaquick/qquickmediaplayer.cpp | 2 | ||||
| -rw-r--r-- | src/plugins/multimedia/ffmpeg/qffmpeghwaccel.cpp | 25 | ||||
| -rw-r--r-- | src/plugins/multimedia/ffmpeg/qffmpeghwaccel_p.h | 6 |
7 files changed, 48 insertions, 21 deletions
diff --git a/src/multimedia/audio/qsoundeffectwithplayer.cpp b/src/multimedia/audio/qsoundeffectwithplayer.cpp index 1a9ec7a4a..2c9b52374 100644 --- a/src/multimedia/audio/qsoundeffectwithplayer.cpp +++ b/src/multimedia/audio/qsoundeffectwithplayer.cpp @@ -152,7 +152,7 @@ void QSoundEffectPrivateWithPlayer::setResolvedAudioDevice(QAudioDevice device) }; m_voices.clear(); - bool hasPlayer = updatePlayer(); + bool hasPlayer = updatePlayer(m_sample); if (!hasPlayer) return; @@ -202,12 +202,18 @@ bool QSoundEffectPrivateWithPlayer::setSource(const QUrl &url, QSampleCache &sam return; } + bool hasPlayer = updatePlayer(result); + if (!hasPlayer) { + qWarning("QSoundEffect: playback of this format is not supported on the selected " + "audio device"); + setStatus(QSoundEffect::Error); + return; + } + m_sample = std::move(result); setStatus(QSoundEffect::Ready); - bool hasPlayer = updatePlayer(); if (std::exchange(m_playPending, false)) { - if (hasPlayer) - play(); + play(); } } else { qWarning("QSoundEffect: Error decoding source %ls", qUtf16Printable(m_url.toString())); @@ -363,8 +369,9 @@ void QSoundEffectPrivateWithPlayer::play(std::shared_ptr<QSoundEffectVoice> voic emit q_ptr->playingChanged(); } -bool QSoundEffectPrivateWithPlayer::updatePlayer() +bool QSoundEffectPrivateWithPlayer::updatePlayer(const SharedSamplePtr &sample) { + Q_ASSERT(sample); Q_ASSERT(m_voices.empty()); QObject::disconnect(m_voiceFinishedConnection); @@ -372,8 +379,10 @@ bool QSoundEffectPrivateWithPlayer::updatePlayer() if (m_resolvedAudioDevice.isNull()) return false; - auto player = QRtAudioEngine::getEngineFor(m_resolvedAudioDevice, m_sample->format()); + auto player = QRtAudioEngine::getEngineFor(m_resolvedAudioDevice, sample->format()); m_player = player; + if (!m_player) + return false; m_voiceFinishedConnection = QObject::connect(m_player.get(), &QRtAudioEngine::voiceFinished, this, [this](VoiceId voiceId) { diff --git a/src/multimedia/audio/qsoundeffectwithplayer_p.h b/src/multimedia/audio/qsoundeffectwithplayer_p.h index 577df8e52..4215265ed 100644 --- a/src/multimedia/audio/qsoundeffectwithplayer_p.h +++ b/src/multimedia/audio/qsoundeffectwithplayer_p.h @@ -88,7 +88,7 @@ public: private: void play(std::shared_ptr<QSoundEffectVoice>); void setStatus(QSoundEffect::Status status); - [[nodiscard]] bool updatePlayer(); + [[nodiscard]] bool updatePlayer(const SharedSamplePtr &sample); std::optional<VoiceId> activeVoice() const; static bool formatIsSupported(const QAudioFormat &); void setResolvedAudioDevice(QAudioDevice device); diff --git a/src/multimedia/video/qvideoframe.cpp b/src/multimedia/video/qvideoframe.cpp index aff78617d..0cac7ffdc 100644 --- a/src/multimedia/video/qvideoframe.cpp +++ b/src/multimedia/video/qvideoframe.cpp @@ -511,14 +511,14 @@ bool QVideoFrame::map(QVideoFrame::MapMode mode) const int height = this->height(); const int yStride = d->mapData.bytesPerLine[0]; const int uvHeight = pixelFmt == QVideoFrameFormat::Format_YUV422P ? height : height / 2; - const int uvStride = (d->mapData.dataSize[0] - (yStride * height)) / uvHeight / 2; + const int uvSize = d->mapData.dataSize[0] - yStride * height; + const int uvStride = uvSize / 2 / uvHeight; // Three planes, the second and third vertically (and horizontally for other than Format_YUV422P formats) subsampled. d->mapData.planeCount = 3; d->mapData.bytesPerLine[2] = d->mapData.bytesPerLine[1] = uvStride; d->mapData.dataSize[0] = yStride * height; - d->mapData.dataSize[1] = uvStride * uvHeight; - d->mapData.dataSize[2] = uvStride * uvHeight; + d->mapData.dataSize[2] = d->mapData.dataSize[1] = uvStride * uvHeight; d->mapData.data[1] = d->mapData.data[0] + d->mapData.dataSize[0]; d->mapData.data[2] = d->mapData.data[1] + d->mapData.dataSize[1]; break; diff --git a/src/multimedia/video/qvideotexturehelper.cpp b/src/multimedia/video/qvideotexturehelper.cpp index 72d33678a..628f7850b 100644 --- a/src/multimedia/video/qvideotexturehelper.cpp +++ b/src/multimedia/video/qvideotexturehelper.cpp @@ -8,6 +8,7 @@ #include "qvideoframe_p.h" #include "qvideoframetexturefromsource_p.h" #include "private/qmultimediautils_p.h" +#include "private/qaudio_alignment_support_p.h" #include <QtCore/qfile.h> #include <qpainter.h> @@ -107,7 +108,7 @@ static const TextureDescription descriptions[QVideoFrameFormat::NPixelFormats] = }, // Format_YUV420P { 3, 1, - [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); }, + [](int stride, int height) { return stride * (height + QtMultimediaPrivate::alignUp(height, 2) / 2); }, { TextureDescription::Red_8, TextureDescription::Red_8, TextureDescription::Red_8 }, { { 1, 1 }, { 2, 2 }, { 2, 2 } } }, @@ -119,7 +120,7 @@ static const TextureDescription descriptions[QVideoFrameFormat::NPixelFormats] = }, // Format_YV12 { 3, 1, - [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); }, + [](int stride, int height) { return stride * (height + QtMultimediaPrivate::alignUp(height, 2) / 2); }, {TextureDescription::Red_8, TextureDescription::Red_8, TextureDescription::Red_8 }, { { 1, 1 }, { 2, 2 }, { 2, 2 } } }, @@ -227,7 +228,7 @@ static const TextureDescription descriptions[QVideoFrameFormat::NPixelFormats] = }, // Format_YUV420P10 { 3, 2, - [](int stride, int height) { return stride * ((height * 3 / 2 + 1) & ~1); }, + [](int stride, int height) { return stride * (height + QtMultimediaPrivate::alignUp(height, 2) / 2); }, { TextureDescription::Red_16, TextureDescription::Red_16, TextureDescription::Red_16 }, { { 1, 1 }, { 2, 2 }, { 2, 2 } } }, diff --git a/src/multimediaquick/qquickmediaplayer.cpp b/src/multimediaquick/qquickmediaplayer.cpp index 6b49c827e..00efcaaa0 100644 --- a/src/multimediaquick/qquickmediaplayer.cpp +++ b/src/multimediaquick/qquickmediaplayer.cpp @@ -19,9 +19,9 @@ void QQuickMediaPlayer::qmlSetSource(const QUrl &source) if (m_source == source) return; m_source = source; - m_wasMediaLoaded = false; const QQmlContext *context = qmlContext(this); setSource(context ? context->resolvedUrl(source) : source); + m_wasMediaLoaded = false; emit qmlSourceChanged(source); } diff --git a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel.cpp b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel.cpp index cb6c1696b..6e78f8eb6 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel.cpp +++ b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel.cpp @@ -405,7 +405,16 @@ AVHWFramesContext *HWAccel::hwFramesContext() const static void deleteHwFrameContextData(AVHWFramesContext *context) { - delete reinterpret_cast<HwFrameContextData *>(context->user_opaque); + std::unique_ptr<HwFrameContextData> contextData( + static_cast<HwFrameContextData *>(context->user_opaque)); + Q_ASSERT(contextData); + + if (contextData->avDeleter) { + context->user_opaque = contextData->avUserOpaque; + context->free = contextData->avDeleter; + + context->free(context); + } } HwFrameContextData &HwFrameContextData::ensure(AVFrame &hwFrame) @@ -413,15 +422,19 @@ HwFrameContextData &HwFrameContextData::ensure(AVFrame &hwFrame) Q_ASSERT(hwFrame.hw_frames_ctx && hwFrame.hw_frames_ctx->data); auto context = reinterpret_cast<AVHWFramesContext *>(hwFrame.hw_frames_ctx->data); - if (!context->user_opaque) { - context->user_opaque = new HwFrameContextData; - Q_ASSERT(!context->free); + + if (context->free != deleteHwFrameContextData) { + // In most cases, we expect null context->free and context->user_opaque. + // However, FFmpeg decoding implementations for specific graphic card backends + // may set a custom deleter. Let's save the deleter and its data (user_opaque) + // to invoke it in deleteHwFrameContextData. + context->user_opaque = new HwFrameContextData{ context->free, context->user_opaque }; context->free = deleteHwFrameContextData; } else { - Q_ASSERT(context->free == deleteHwFrameContextData); + Q_ASSERT(context->user_opaque); } - return *reinterpret_cast<HwFrameContextData *>(context->user_opaque); + return *static_cast<HwFrameContextData *>(context->user_opaque); } AVFrameUPtr copyFromHwPool(AVFrameUPtr frame) diff --git a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_p.h b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_p.h index 64aeb098c..d2f9ed0b3 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_p.h +++ b/src/plugins/multimedia/ffmpeg/qffmpeghwaccel_p.h @@ -47,7 +47,11 @@ using HWAccelUPtr = std::unique_ptr<HWAccel>; */ struct HwFrameContextData { - QRhiValueMapper<TextureConverter> textureConverterMapper; + using AVHWFramesContextDeleter = void (*)(struct AVHWFramesContext *ctx); + AVHWFramesContextDeleter avDeleter = nullptr; + void *avUserOpaque = nullptr; + + QRhiValueMapper<TextureConverter> textureConverterMapper = {}; /** * @brief gets or creates an instance of the class, associated with |
