summaryrefslogtreecommitdiff
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
commitb0332afbf2862d30bc5d13613dd53437cb1abe11 (patch)
treec8cf22eaf20fe66f8f27124970a7f72bdb2a299d
parentc3bf94afce42dbef71107df8068e21e6833705da (diff)
downloadqtmultimedia-b0332afbf2862d30bc5d13613dd53437cb1abe11.tar.gz
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];