summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/multimedia/audio/qsoundeffectwithplayer.cpp21
-rw-r--r--src/multimedia/audio/qsoundeffectwithplayer_p.h2
-rw-r--r--src/multimedia/video/qvideoframe.cpp6
-rw-r--r--src/multimedia/video/qvideotexturehelper.cpp7
-rw-r--r--src/multimediaquick/qquickmediaplayer.cpp2
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpeghwaccel.cpp25
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpeghwaccel_p.h6
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