summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoris Verria <doris.verria@qt.io>2023-02-14 16:37:41 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-15 15:08:53 +0000
commitb442e71593c16a3ea9ccda44458542c2347a465c (patch)
tree7bb91c117a6eac9c7d1727aee779333fab3205d6
parent5663b1201d9f1b0d7beb3f3a0b3c19c8bb8ebdf4 (diff)
AVFMediaEncoder: Set channel layout configuration when recording
When recording audio, we are setting the audio channel count to the one specified in the encoder settings. If this is not set, we were setting it to 2 channels by default. However, this was causing sometimes problems as the internal AudioConverter could not always convert from the audio capture device's actual format to one with 2 channels. To avoid this, we should default to setting the channel layout configuration settings based on the channel layout of the audio device. This is safer and avoids unnecessary format conversions. Fixes: QTBUG-110844 Change-Id: I3d78ec8b37d6780c7d96147f81ce15bd6425b448 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> Reviewed-by: Lars Knoll <lars@knoll.priv.no> (cherry picked from commit a40b9fed50ef75504cec128d4acfb1062e90df98) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/multimedia/darwin/qcoreaudioutils_p.h2
-rw-r--r--src/plugins/multimedia/darwin/camera/avfmediaencoder.mm45
2 files changed, 33 insertions, 14 deletions
diff --git a/src/multimedia/darwin/qcoreaudioutils_p.h b/src/multimedia/darwin/qcoreaudioutils_p.h
index c6a7d0315..94b6298f3 100644
--- a/src/multimedia/darwin/qcoreaudioutils_p.h
+++ b/src/multimedia/darwin/qcoreaudioutils_p.h
@@ -31,7 +31,7 @@ public:
static AudioStreamBasicDescription toAudioStreamBasicDescription(QAudioFormat const& audioFormat);
// ownership is transferred to caller, free with ::free()
- static std::unique_ptr<AudioChannelLayout> toAudioChannelLayout(const QAudioFormat &format, UInt32 *size);
+ static Q_MULTIMEDIA_EXPORT std::unique_ptr<AudioChannelLayout> toAudioChannelLayout(const QAudioFormat &format, UInt32 *size);
static QAudioFormat::ChannelConfig fromAudioChannelLayout(const AudioChannelLayout *layout);
private:
diff --git a/src/plugins/multimedia/darwin/camera/avfmediaencoder.mm b/src/plugins/multimedia/darwin/camera/avfmediaencoder.mm
index ba79a9f97..3b878d1b4 100644
--- a/src/plugins/multimedia/darwin/camera/avfmediaencoder.mm
+++ b/src/plugins/multimedia/darwin/camera/avfmediaencoder.mm
@@ -16,11 +16,14 @@
#include "private/qmediarecorder_p.h"
#include "qdarwinformatsinfo_p.h"
#include "private/qplatformaudiooutput_p.h"
+#include <private/qplatformaudioinput_p.h>
#include <QtCore/qmath.h>
#include <QtCore/qdebug.h>
#include <QtCore/qmimetype.h>
+#include <private/qcoreaudioutils_p.h>
+
QT_USE_NAMESPACE
namespace {
@@ -99,7 +102,7 @@ void AVFMediaEncoder::updateDuration(qint64 duration)
durationChanged(m_duration);
}
-static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettings)
+static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettings, const QAudioFormat &format)
{
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
@@ -183,22 +186,36 @@ static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettin
}
}
}
+
+ // if channel count is provided and it's bigger than 2
+ // provide a supported channel layout
+ if (isChannelCountSupported && channelCount > 2) {
+ AudioChannelLayout channelLayout;
+ memset(&channelLayout, 0, sizeof(AudioChannelLayout));
+ auto channelLayoutTags = qt_supported_channel_layout_tags_for_format(codecId, channelCount);
+ if (channelLayoutTags.size()) {
+ channelLayout.mChannelLayoutTag = channelLayoutTags.first();
+ [settings setObject:[NSData dataWithBytes: &channelLayout length: sizeof(channelLayout)] forKey:AVChannelLayoutKey];
+ } else {
+ isChannelCountSupported = false;
+ }
+ }
+
+ if (isChannelCountSupported)
+ [settings setObject:[NSNumber numberWithInt:channelCount] forKey:AVNumberOfChannelsKey];
}
- if (isChannelCountSupported && channelCount > 2) {
- AudioChannelLayout channelLayout;
- memset(&channelLayout, 0, sizeof(AudioChannelLayout));
- auto channelLayoutTags = qt_supported_channel_layout_tags_for_format(codecId, channelCount);
- if (channelLayoutTags.size()) {
- channelLayout.mChannelLayoutTag = channelLayoutTags.first();
- [settings setObject:[NSData dataWithBytes: &channelLayout length: sizeof(channelLayout)] forKey:AVChannelLayoutKey];
+ if (!isChannelCountSupported) {
+ // fallback to providing channel layout if channel count is not specified or supported
+ UInt32 size = 0;
+ if (format.isValid()) {
+ auto layout = CoreAudioUtils::toAudioChannelLayout(format, &size);
+ [settings setObject:[NSData dataWithBytes:layout.get() length:sizeof(AudioChannelLayout)] forKey:AVChannelLayoutKey];
} else {
- isChannelCountSupported = false;
+ // finally default to setting channel count to 1
+ [settings setObject:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey];
}
}
- if (!isChannelCountSupported)
- channelCount = 2;
- [settings setObject:[NSNumber numberWithInt:channelCount] forKey:AVNumberOfChannelsKey];
if (codecId == kAudioFormatAppleLossless)
[settings setObject:[NSNumber numberWithInt:24] forKey:AVEncoderBitDepthHintKey];
@@ -385,7 +402,9 @@ void AVFMediaEncoder::applySettings(QMediaEncoderSettings &settings)
AVFCameraSession *session = m_service->session();
// audio settings
- m_audioSettings = avfAudioSettings(settings);
+ const auto audioInput = m_service->audioInput();
+ const QAudioFormat audioFormat = audioInput ? audioInput->device.preferredFormat() : QAudioFormat();
+ m_audioSettings = avfAudioSettings(settings, audioFormat);
if (m_audioSettings)
[m_audioSettings retain];