summaryrefslogtreecommitdiff
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:17:40 +0200
commit934c9b6dee03b8b71bd71f06d03185c56f94bd76 (patch)
tree4b2a8cac9d378761372e579207dec69cd07bb839
parent315d0f848a67c33390e787c094c16d496601a042 (diff)
downloadqtmultimedia-934c9b6dee03b8b71bd71f06d03185c56f94bd76.tar.gz
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;
}