diff options
Diffstat (limited to 'dom/media/webcodecs/AudioData.cpp')
-rw-r--r-- | dom/media/webcodecs/AudioData.cpp | 84 |
1 files changed, 36 insertions, 48 deletions
diff --git a/dom/media/webcodecs/AudioData.cpp b/dom/media/webcodecs/AudioData.cpp index 0b21798be8..aae58fb32c 100644 --- a/dom/media/webcodecs/AudioData.cpp +++ b/dom/media/webcodecs/AudioData.cpp @@ -151,25 +151,6 @@ JSObject* AudioData::WrapObject(JSContext* aCx, return AudioData_Binding::Wrap(aCx, this, aGivenProto); } -uint32_t BytesPerSamples(const mozilla::dom::AudioSampleFormat& aFormat) { - switch (aFormat) { - case AudioSampleFormat::U8: - case AudioSampleFormat::U8_planar: - return sizeof(uint8_t); - case AudioSampleFormat::S16: - case AudioSampleFormat::S16_planar: - return sizeof(int16_t); - case AudioSampleFormat::S32: - case AudioSampleFormat::F32: - case AudioSampleFormat::S32_planar: - case AudioSampleFormat::F32_planar: - return sizeof(float); - default: - MOZ_ASSERT_UNREACHABLE("wrong enum value"); - } - return 0; -} - Result<Ok, nsCString> IsValidAudioDataInit(const AudioDataInit& aInit) { if (aInit.mSampleRate <= 0.0) { auto msg = nsLiteralCString("sampleRate must be positive"); @@ -205,37 +186,13 @@ Result<Ok, nsCString> IsValidAudioDataInit(const AudioDataInit& aInit) { return Ok(); } -const char* FormatToString(AudioSampleFormat aFormat) { - switch (aFormat) { - case AudioSampleFormat::U8: - return "u8"; - case AudioSampleFormat::S16: - return "s16"; - case AudioSampleFormat::S32: - return "s32"; - case AudioSampleFormat::F32: - return "f32"; - case AudioSampleFormat::U8_planar: - return "u8-planar"; - case AudioSampleFormat::S16_planar: - return "s16-planar"; - case AudioSampleFormat::S32_planar: - return "s32-planar"; - case AudioSampleFormat::F32_planar: - return "f32-planar"; - default: - MOZ_ASSERT_UNREACHABLE("wrong enum value"); - } - return "unsupported"; -} - /* static */ already_AddRefed<AudioData> AudioData::Constructor(const GlobalObject& aGlobal, const AudioDataInit& aInit, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); LOGD("[%p] AudioData(fmt: %s, rate: %f, ch: %" PRIu32 ", ts: %" PRId64 ")", - global.get(), FormatToString(aInit.mFormat), aInit.mSampleRate, + global.get(), GetEnumString(aInit.mFormat).get(), aInit.mSampleRate, aInit.mNumberOfChannels, aInit.mTimestamp); if (!global) { LOGE("Global unavailable"); @@ -311,6 +268,9 @@ struct CopyToSpec { const uint32_t mFrameOffset; const uint32_t mPlaneIndex; const AudioSampleFormat mFormat; + // False if this is used internally, and this copy call doesn't come from + // script. + DebugOnly<bool> mFromScript = true; }; bool IsInterleaved(const AudioSampleFormat& aFormat) { @@ -463,7 +423,7 @@ void CopySamples(Span<S> aSource, Span<D> aDest, uint32_t aSourceChannelCount, } if (!IsInterleaved(aSourceFormat) && IsInterleaved(aCopyToSpec.mFormat)) { - MOZ_CRASH("This should never be hit -- current spec doesn't support it"); + MOZ_ASSERT(!aCopyToSpec.mFromScript); // Planar to interleaved -- copy of all channels of the source into the // destination buffer. MOZ_ASSERT(aCopyToSpec.mPlaneIndex == 0); @@ -505,7 +465,7 @@ nsCString AudioData::ToString() const { return nsPrintfCString("AudioData[%zu bytes %s %fHz %" PRIu32 "x%" PRIu32 "ch]", mResource->Data().LengthBytes(), - FormatToString(mAudioSampleFormat.value()), + GetEnumString(mAudioSampleFormat.value()).get(), mSampleRate, mNumberOfFrames, mNumberOfChannels); } @@ -515,8 +475,9 @@ nsCString CopyToToString(size_t aDestBufSize, "AudioDataCopyToOptions[data: %zu bytes %s frame count:%" PRIu32 " frame offset: %" PRIu32 " plane: %" PRIu32 "]", aDestBufSize, - aOptions.mFormat.WasPassed() ? FormatToString(aOptions.mFormat.Value()) - : "null", + aOptions.mFormat.WasPassed() + ? GetEnumString(aOptions.mFormat.Value()).get() + : "null", aOptions.mFrameCount.WasPassed() ? aOptions.mFrameCount.Value() : 0, aOptions.mFrameOffset, aOptions.mPlaneIndex); } @@ -650,6 +611,8 @@ void AudioData::Close() { mAudioSampleFormat = Nothing(); } +bool AudioData::IsClosed() const { return !mResource; } + // https://w3c.github.io/webcodecs/#ref-for-deserialization-steps%E2%91%A1 /* static */ JSObject* AudioData::ReadStructuredClone(JSContext* aCx, @@ -724,6 +687,31 @@ void AudioData::CloseIfNeeded() { } } +RefPtr<mozilla::AudioData> AudioData::ToAudioData() const { + // Always convert to f32 interleaved for now, as this Gecko's prefered + // internal audio representation for encoding and decoding. + Span<uint8_t> data = mResource->Data(); + DebugOnly<uint32_t> frames = mNumberOfFrames; + uint32_t bytesPerSample = BytesPerSamples(mAudioSampleFormat.value()); + uint32_t samples = data.Length() / bytesPerSample; + DebugOnly<uint32_t> computedFrames = samples / mNumberOfChannels; + MOZ_ASSERT(frames == computedFrames); + AlignedAudioBuffer buf(samples); + Span<uint8_t> storage(reinterpret_cast<uint8_t*>(buf.Data()), + samples * sizeof(float)); + + CopyToSpec spec(mNumberOfFrames, 0, 0, AudioSampleFormat::F32); +#ifdef DEBUG + spec.mFromScript = false; +#endif + + DoCopy(data, storage, mNumberOfChannels, mAudioSampleFormat.value(), spec); + + return MakeRefPtr<mozilla::AudioData>( + 0, media::TimeUnit::FromMicroseconds(mTimestamp), std::move(buf), + mNumberOfChannels, mSampleRate); +} + #undef LOGD #undef LOGE #undef LOG_INTERNAL |