Bug 1850460 - Removed file build/build-clang/revert-llvmorg-18-init-3787-gb6a1473f97d...
[gecko.git] / dom / media / AudioCompactor.h
blob8281686977f8efc3e1bd8a2f90954ca7769e9e3c
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #if !defined(AudioCompactor_h)
7 # define AudioCompactor_h
9 # include "MediaQueue.h"
10 # include "MediaData.h"
11 # include "VideoUtils.h"
13 namespace mozilla {
15 class AudioCompactor {
16 public:
17 explicit AudioCompactor(MediaQueue<AudioData>& aQueue) : mQueue(aQueue) {
18 // Determine padding size used by AlignedBuffer.
19 size_t paddedSize = AlignedAudioBuffer::AlignmentPaddingSize();
20 mSamplesPadding = paddedSize / sizeof(AudioDataValue);
21 if (mSamplesPadding * sizeof(AudioDataValue) < paddedSize) {
22 // Round up.
23 mSamplesPadding++;
27 // Push audio data into the underlying queue with minimal heap allocation
28 // slop. This method is responsible for allocating AudioDataValue[] buffers.
29 // The caller must provide a functor to copy the data into the buffers. The
30 // functor must provide the following signature:
32 // uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples);
34 // The functor must copy as many complete frames as possible to the provided
35 // buffer given its length (in AudioDataValue elements). The number of frames
36 // copied must be returned. This copy functor must support being called
37 // multiple times in order to copy the audio data fully. The copy functor
38 // must copy full frames as partial frames will be ignored.
39 template <typename CopyFunc>
40 bool Push(int64_t aOffset, int64_t aTime, int32_t aSampleRate,
41 uint32_t aFrames, uint32_t aChannels, CopyFunc aCopyFunc) {
42 auto time = media::TimeUnit::FromMicroseconds(aTime);
44 // If we are losing more than a reasonable amount to padding, try to chunk
45 // the data.
46 size_t maxSlop = AudioDataSize(aFrames, aChannels) / MAX_SLOP_DIVISOR;
48 while (aFrames > 0) {
49 uint32_t samples = GetChunkSamples(aFrames, aChannels, maxSlop);
50 if (samples / aChannels > mSamplesPadding / aChannels + 1) {
51 samples -= mSamplesPadding;
53 AlignedAudioBuffer buffer(samples);
54 if (!buffer) {
55 return false;
58 // Copy audio data to buffer using caller-provided functor.
59 uint32_t framesCopied = aCopyFunc(buffer.get(), samples);
61 NS_ASSERTION(framesCopied <= aFrames, "functor copied too many frames");
62 buffer.SetLength(size_t(framesCopied) * aChannels);
64 auto duration = media::TimeUnit(framesCopied, aSampleRate);
65 if (!duration.IsValid()) {
66 return false;
69 RefPtr<AudioData> data = new AudioData(aOffset, time, std::move(buffer),
70 aChannels, aSampleRate);
71 MOZ_DIAGNOSTIC_ASSERT(duration == data->mDuration, "must be equal");
72 mQueue.Push(data);
74 // Remove the frames we just pushed into the queue and loop if there is
75 // more to be done.
76 time += duration;
77 aFrames -= framesCopied;
79 // NOTE: No need to update aOffset as its only an approximation anyway.
82 return true;
85 // Copy functor suitable for copying audio samples already in the
86 // AudioDataValue format/layout expected by AudioStream on this platform.
87 class NativeCopy {
88 public:
89 NativeCopy(const uint8_t* aSource, size_t aSourceBytes, uint32_t aChannels)
90 : mSource(aSource),
91 mSourceBytes(aSourceBytes),
92 mChannels(aChannels),
93 mNextByte(0) {}
95 uint32_t operator()(AudioDataValue* aBuffer, uint32_t aSamples);
97 private:
98 const uint8_t* const mSource;
99 const size_t mSourceBytes;
100 const uint32_t mChannels;
101 size_t mNextByte;
104 // Allow 12.5% slop before chunking kicks in. Public so that the gtest can
105 // access it.
106 static const size_t MAX_SLOP_DIVISOR = 8;
108 private:
109 // Compute the number of AudioDataValue samples that will be fit the most
110 // frames while keeping heap allocation slop less than the given threshold.
111 static uint32_t GetChunkSamples(uint32_t aFrames, uint32_t aChannels,
112 size_t aMaxSlop);
114 static size_t BytesPerFrame(uint32_t aChannels) {
115 return sizeof(AudioDataValue) * aChannels;
118 static size_t AudioDataSize(uint32_t aFrames, uint32_t aChannels) {
119 return aFrames * BytesPerFrame(aChannels);
122 MediaQueue<AudioData>& mQueue;
123 size_t mSamplesPadding;
126 } // namespace mozilla
128 #endif // AudioCompactor_h