summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoris Verria <doris.verria@qt.io>2022-03-28 02:09:24 +0200
committerDoris Verria <doris.verria@qt.io>2022-04-05 13:18:57 +0200
commita7aae08e4dee3e3773d897b478bcc15550872203 (patch)
tree8e0950bff011e1e6e233a91223851aa72ebe29d6
parent07ef223dad41958199e26c9ff98b5690a553a68c (diff)
darwin: Don't specify source format hint for audio recording
We were initializing the audio writer input with a format hint equal to the audio capture device's active format. This is wrong as we can't ensure that the captured audio buffers will be in that same format. This caused failure in recording because the captured audio buffers had the kAudioFormatFlagIsNonInterleaved set, while the format hint didn't, causing the internal calls to the AudioConverter to fail with errors. To fix, do not specify a format hint but instead setup the audio settings dictionary with the necessary keys. Force a default value for AVNumberOfChannelsKey since it is now required, and for recording with more than 2 channels, provide a supported channel layout. Fixes: QTBUG-98262 Done-with: Vladimir Belyavsky <belyavskyv@gmail.com> Change-Id: I537d82e729c91a66d85aaa61c563a1ecd1a91af3 Reviewed-by: Vladimir Belyavsky <belyavskyv@gmail.com> Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit 980c145069c589085b4dee4b4c2b69e3b1a0adc3) Reviewed-by: Doris Verria <doris.verria@qt.io>
-rw-r--r--src/multimedia/platform/darwin/camera/avfcamerautility.mm33
-rw-r--r--src/multimedia/platform/darwin/camera/avfcamerautility_p.h1
-rw-r--r--src/multimedia/platform/darwin/camera/avfmediaassetwriter.mm6
-rw-r--r--src/multimedia/platform/darwin/camera/avfmediaencoder.mm33
4 files changed, 55 insertions, 18 deletions
diff --git a/src/multimedia/platform/darwin/camera/avfcamerautility.mm b/src/multimedia/platform/darwin/camera/avfcamerautility.mm
index 444162523..f5c90bb77 100644
--- a/src/multimedia/platform/darwin/camera/avfcamerautility.mm
+++ b/src/multimedia/platform/darwin/camera/avfcamerautility.mm
@@ -711,4 +711,37 @@ std::optional<QList<UInt32>> qt_supported_channel_counts_for_format(int codecId)
return result;
}
+QList<UInt32> qt_supported_channel_layout_tags_for_format(int codecId, int noChannels)
+{
+ QList<UInt32> result;
+ AudioStreamBasicDescription sf = {};
+ sf.mFormatID = codecId;
+ sf.mChannelsPerFrame = noChannels;
+ UInt32 size;
+ OSStatus err = AudioFormatGetPropertyInfo(
+ kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
+ sizeof(sf),
+ &sf,
+ &size);
+
+ if (err != noErr)
+ return result;
+
+ UInt32 noTags = (UInt32)size / sizeof(UInt32);
+ AudioChannelLayoutTag tagsArr[noTags];
+
+ err = AudioFormatGetProperty(kAudioFormatProperty_AvailableEncodeChannelLayoutTags,
+ sizeof(sf),
+ &sf,
+ &size,
+ tagsArr);
+ if (err != noErr)
+ return result;
+
+ for (UInt32 i = 0; i < noTags; i++)
+ result << tagsArr[i];
+
+ return result;
+}
+
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/darwin/camera/avfcamerautility_p.h b/src/multimedia/platform/darwin/camera/avfcamerautility_p.h
index 26a023be9..00ff4bb29 100644
--- a/src/multimedia/platform/darwin/camera/avfcamerautility_p.h
+++ b/src/multimedia/platform/darwin/camera/avfcamerautility_p.h
@@ -195,6 +195,7 @@ void qt_set_framerate_limits(AVCaptureDevice *captureDevice, AVCaptureConnection
QList<AudioValueRange> qt_supported_sample_rates_for_format(int codecId);
QList<AudioValueRange> qt_supported_bit_rates_for_format(int codecId);
std::optional<QList<UInt32>> qt_supported_channel_counts_for_format(int codecId);
+QList<UInt32> qt_supported_channel_layout_tags_for_format(int codecId, int noChannels);
QT_END_NAMESPACE
diff --git a/src/multimedia/platform/darwin/camera/avfmediaassetwriter.mm b/src/multimedia/platform/darwin/camera/avfmediaassetwriter.mm
index 61f248c72..243f8455a 100644
--- a/src/multimedia/platform/darwin/camera/avfmediaassetwriter.mm
+++ b/src/multimedia/platform/darwin/camera/avfmediaassetwriter.mm
@@ -529,12 +529,8 @@ using AVFAtomicInt64 = QAtomicInteger<qint64>;
m_audioWriterInput.reset();
if (m_audioQueue) {
- CMFormatDescriptionRef sourceFormat = session->audioCaptureDevice()
- ? session->audioCaptureDevice().activeFormat.formatDescription
- : 0;
m_audioWriterInput.reset([[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio
- outputSettings:m_audioSettings
- sourceFormatHint:sourceFormat]);
+ outputSettings:m_audioSettings]);
if (!m_audioWriterInput) {
qWarning() << Q_FUNC_INFO << "failed to create audio writer input";
// But we still can record video.
diff --git a/src/multimedia/platform/darwin/camera/avfmediaencoder.mm b/src/multimedia/platform/darwin/camera/avfmediaencoder.mm
index 87e7a357f..b669dd960 100644
--- a/src/multimedia/platform/darwin/camera/avfmediaencoder.mm
+++ b/src/multimedia/platform/darwin/camera/avfmediaencoder.mm
@@ -139,12 +139,14 @@ static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettin
{
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
+ // Codec
int codecId = QDarwinFormatInfo::audioFormatForCodec(encoderSettings.mediaFormat().audioCodec());
[settings setObject:[NSNumber numberWithInt:codecId] forKey:AVFormatIDKey];
// Setting AVEncoderQualityKey is not allowed when format ID is alac or lpcm
if (codecId != kAudioFormatAppleLossless && codecId != kAudioFormatLinearPCM
&& encoderSettings.encodingMode() == QMediaRecorder::ConstantQualityEncoding) {
+ // AudioQuality
int quality;
switch (encoderSettings.quality()) {
case QMediaRecorder::VeryLowQuality:
@@ -166,6 +168,7 @@ static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettin
}
[settings setObject:[NSNumber numberWithInt:quality] forKey:AVEncoderAudioQualityKey];
} else {
+ // BitRate
bool isBitRateSupported = false;
int bitRate = encoderSettings.audioBitRate();
if (bitRate > 0) {
@@ -183,6 +186,7 @@ static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettin
}
}
+ // SampleRate
int sampleRate = encoderSettings.audioSampleRate();
bool isSampleRateSupported = false;
if (sampleRate >= 8000 && sampleRate <= 192000) {
@@ -194,7 +198,11 @@ static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettin
}
}
}
+ if (!isSampleRateSupported)
+ sampleRate = 44100;
+ [settings setObject:[NSNumber numberWithInt:sampleRate] forKey:AVSampleRateKey];
+ // Channels
int channelCount = encoderSettings.audioChannelCount();
bool isChannelCountSupported = false;
if (channelCount > 0) {
@@ -213,16 +221,20 @@ static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettin
}
}
-#ifdef Q_OS_IOS
- // Some keys are mandatory only on iOS
- if (!isSampleRateSupported) {
- sampleRate = 44100;
- isSampleRateSupported = true;
+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) {
+ if (!isChannelCountSupported)
channelCount = 2;
- isChannelCountSupported = true;
- }
+ [settings setObject:[NSNumber numberWithInt:channelCount] forKey:AVNumberOfChannelsKey];
if (codecId == kAudioFormatAppleLossless)
[settings setObject:[NSNumber numberWithInt:24] forKey:AVEncoderBitDepthHintKey];
@@ -233,11 +245,6 @@ static NSDictionary *avfAudioSettings(const QMediaEncoderSettings &encoderSettin
[settings setObject:[NSNumber numberWithInt:NO] forKey:AVLinearPCMIsFloatKey];
[settings setObject:[NSNumber numberWithInt:NO] forKey:AVLinearPCMIsNonInterleaved];
}
-#endif
- if (isSampleRateSupported)
- [settings setObject:[NSNumber numberWithInt:sampleRate] forKey:AVSampleRateKey];
- if (isChannelCountSupported)
- [settings setObject:[NSNumber numberWithInt:channelCount] forKey:AVNumberOfChannelsKey];
return settings;
}