diff options
author | Doris Verria <doris.verria@qt.io> | 2023-02-14 16:37:41 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-02-15 15:08:53 +0000 |
commit | b442e71593c16a3ea9ccda44458542c2347a465c (patch) | |
tree | 7bb91c117a6eac9c7d1727aee779333fab3205d6 | |
parent | 5663b1201d9f1b0d7beb3f3a0b3c19c8bb8ebdf4 (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.h | 2 | ||||
-rw-r--r-- | src/plugins/multimedia/darwin/camera/avfmediaencoder.mm | 45 |
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]; |