Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3e90d88

Browse files
committedDec 10, 2024
Amend AudioSampleBufferConverter to support various encoder options
https://bugs.webkit.org/show_bug.cgi?id=284355 rdar://141204354 Reviewed by NOBODY (OOPS!). Add support for passing various encoder options to the AudioSampleBufferConverter's AudioConverter. The size of the compressed packet is determined by setting the AudioStreamBasicDescription's mFramesPerPacket. Tests to follow as part of the WebCodec's WPT. No change of behaviours at this stage. * Source/WebCore/platform/audio/cocoa/AudioSampleBufferConverter.h: (WebCore::AudioSampleBufferConverter::preSkip const): Add method to retrieve the preSkip value after creating the AudioConverter. Will be used to create the Opus's codec description. * Source/WebCore/platform/audio/cocoa/AudioSampleBufferConverter.mm: (WebCore::AudioSampleBufferConverter::initAudioConverterForSourceFormatDescription):
1 parent a48336b commit 3e90d88

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed
 

‎Source/WebCore/platform/audio/cocoa/AudioSampleBufferConverter.h

+19
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#if USE(AVFOUNDATION)
2828

29+
#include "BitrateMode.h"
2930
#include <CoreMedia/CoreMedia.h>
3031
#include <wtf/Forward.h>
3132
#include <wtf/ThreadSafeWeakPtr.h>
@@ -41,12 +42,28 @@ class WebAudioBufferList;
4142

4243
class AudioSampleBufferConverter : public ThreadSafeRefCountedAndCanMakeThreadSafeWeakPtr<AudioSampleBufferConverter> {
4344
public:
45+
46+
#if ENABLE(WEB_CODECS)
47+
using BitrateMode = BitrateMode;
48+
#else
49+
enum class BitrateMode {
50+
Constant,
51+
Variable
52+
};
53+
#endif
54+
4455
struct Options {
4556
AudioFormatID format { kAudioFormatMPEG4AAC };
4657
std::optional<AudioStreamBasicDescription> description { };
4758
std::optional<unsigned> outputBitRate { };
4859
bool generateTimestamp { true };
4960
std::optional<unsigned> preSkip { 0 };
61+
std::optional<BitrateMode> bitrateMode { };
62+
std::optional<unsigned> packetSize { };
63+
std::optional<unsigned> complexity { };
64+
std::optional<unsigned> packetlossperc { };
65+
std::optional<bool> useinbandfec { };
66+
std::optional<bool> usedtx { };
5067
};
5168
static RefPtr<AudioSampleBufferConverter> create(CMBufferQueueTriggerCallback, void* callbackObject, const Options&);
5269
~AudioSampleBufferConverter();
@@ -60,6 +77,7 @@ class AudioSampleBufferConverter : public ThreadSafeRefCountedAndCanMakeThreadSa
6077
RetainPtr<CMSampleBufferRef> takeOutputSampleBuffer();
6178

6279
unsigned bitRate() const;
80+
unsigned preSkip() const { return m_preSkip; }
6381

6482
private:
6583
AudioSampleBufferConverter(const Options&);
@@ -109,6 +127,7 @@ class AudioSampleBufferConverter : public ThreadSafeRefCountedAndCanMakeThreadSa
109127
const AudioFormatID m_outputCodecType;
110128
const Options m_options;
111129
std::atomic<unsigned> m_defaultBitRate { 0 };
130+
std::atomic<unsigned> m_preSkip { 0 };
112131
};
113132

114133
}

‎Source/WebCore/platform/audio/cocoa/AudioSampleBufferConverter.mm

+38-7
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,21 @@
172172
m_destinationFormat.mChannelsPerFrame = m_sourceFormat.mChannelsPerFrame;
173173
m_destinationFormat.mSampleRate = m_sourceFormat.mSampleRate;
174174
}
175-
if (outputFormatID == kAudioFormatOpus)
176-
m_destinationFormat.mSampleRate = 48000;
177175

178-
UInt32 size = sizeof(m_destinationFormat);
179-
if (auto error = PAL::AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &m_destinationFormat)) {
176+
if (auto error = [&](auto& destinationFormat) {
177+
auto originalDestinationFormat = destinationFormat;
178+
UInt32 size = sizeof(destinationFormat);
179+
auto result = PAL::AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat);
180+
if (result == kAudioCodecUnsupportedFormatError) {
181+
destinationFormat.mSampleRate = 48000;
182+
result = PAL::AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat);
183+
if (originalDestinationFormat.mFramesPerPacket) {
184+
// Adjust mFramesPerPacket to match new sampling rate
185+
destinationFormat.mFramesPerPacket = originalDestinationFormat.mFramesPerPacket / originalDestinationFormat.mSampleRate * destinationFormat.mSampleRate;
186+
}
187+
}
188+
return result;
189+
}(m_destinationFormat)) {
180190
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter AudioFormatGetProperty failed with %d", static_cast<int>(error));
181191
return error;
182192
}
@@ -209,7 +219,7 @@
209219
}
210220
}
211221

212-
size = sizeof(m_sourceFormat);
222+
UInt32 size = sizeof(m_sourceFormat);
213223
if (auto error = PAL::AudioConverterGetProperty(m_converter, kAudioConverterCurrentInputStreamDescription, &size, &m_sourceFormat)) {
214224
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter getting kAudioConverterCurrentInputStreamDescription failed with %d", static_cast<int>(error));
215225
return error;
@@ -231,8 +241,7 @@
231241
}
232242
if (shouldSetDefaultOutputBitRate) {
233243
auto outputBitRate = defaultOutputBitRate(m_destinationFormat);
234-
size = sizeof(outputBitRate);
235-
if (auto error = PAL::AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, size, &outputBitRate))
244+
if (auto error = PAL::AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, sizeof(outputBitRate), &outputBitRate))
236245
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter setting default kAudioConverterEncodeBitRate failed with %d", static_cast<int>(error));
237246
else
238247
m_defaultBitRate = outputBitRate;
@@ -250,7 +259,29 @@
250259
UInt32 size = sizeof(primeInfo);
251260
if (auto error = PAL::AudioConverterGetProperty(m_converter, kAudioConverterPrimeInfo, &size, &primeInfo))
252261
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter getting kAudioConverterPrimeInfo failed with %d", static_cast<int>(error));
262+
else
263+
m_preSkip = primeInfo.leadingFrames;
253264
m_remainingPrimeDuration = PAL::CMTimeMake(primeInfo.leadingFrames, m_destinationFormat.mSampleRate);
265+
266+
if (m_options.bitrateMode) {
267+
UInt32 bitrateMode = *m_options.bitrateMode == BitrateMode::Variable ? kAudioCodecBitRateControlMode_Variable : kAudioCodecBitRateControlMode_Constant;
268+
if (auto error = PAL::AudioConverterSetProperty(m_converter, kAudioCodecPropertyBitRateControlMode, sizeof(bitrateMode), &bitrateMode))
269+
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter setting kAudioCodecPropertyBitRateControlMode failed with %d", static_cast<int>(error));
270+
}
271+
if (m_options.complexity) {
272+
if (auto error = PAL::AudioConverterSetProperty(m_converter, kAudioCodecPropertyQualitySetting, sizeof(*m_options.complexity), &m_options.complexity.value()))
273+
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter setting kAudioCodecPropertyQualitySetting failed with %d", static_cast<int>(error));
274+
}
275+
276+
// Only operational with Opus encoder.
277+
if (m_options.packetlossperc) {
278+
if (auto error = PAL::AudioConverterSetProperty(m_converter, 'plsp', sizeof(*m_options.packetlossperc), &m_options.packetlossperc.value()))
279+
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter setting packetlossperc failed with %d", static_cast<int>(error));
280+
}
281+
if (m_options.useinbandfec) {
282+
if (auto error = PAL::AudioConverterSetProperty(m_converter, 'pfec', sizeof(*m_options.useinbandfec), &m_options.useinbandfec.value()))
283+
RELEASE_LOG_ERROR(MediaStream, "AudioSampleBufferConverter setting useinbandfec failed with %d", static_cast<int>(error));
284+
}
254285
}
255286

256287
if (!m_destinationFormat.mBytesPerPacket) {

0 commit comments

Comments
 (0)
Please sign in to comment.