Bug 1526591 - Remove devtools.inspector.shapesHighlighter.enabled pref. r=rcaliman
[gecko.git] / dom / media / AudioCompactor.h
blob526f1dae3e5c3580e327e281897bc75421c06d81
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 = FramesToTimeUnit(framesCopied, aSampleRate);
65 if (!duration.IsValid()) {
66 return false;
69 mQueue.Push(new AudioData(aOffset, time, duration, framesCopied,
70 std::move(buffer), aChannels, aSampleRate));
72 // Remove the frames we just pushed into the queue and loop if there is
73 // more to be done.
74 time += duration;
75 aFrames -= framesCopied;
77 // NOTE: No need to update aOffset as its only an approximation anyway.
80 return true;
83 // Copy functor suitable for copying audio samples already in the
84 // AudioDataValue format/layout expected by AudioStream on this platform.
85 class NativeCopy {
86 public:
87 NativeCopy(const uint8_t* aSource, size_t aSourceBytes, uint32_t aChannels)
88 : mSource(aSource),
89 mSourceBytes(aSourceBytes),
90 mChannels(aChannels),
91 mNextByte(0) {}
93 uint32_t operator()(AudioDataValue* aBuffer, uint32_t aSamples);
95 private:
96 const uint8_t* const mSource;
97 const size_t mSourceBytes;
98 const uint32_t mChannels;
99 size_t mNextByte;
102 // Allow 12.5% slop before chunking kicks in. Public so that the gtest can
103 // access it.
104 static const size_t MAX_SLOP_DIVISOR = 8;
106 private:
107 // Compute the number of AudioDataValue samples that will be fit the most
108 // frames while keeping heap allocation slop less than the given threshold.
109 static uint32_t GetChunkSamples(uint32_t aFrames, uint32_t aChannels,
110 size_t aMaxSlop);
112 static size_t BytesPerFrame(uint32_t aChannels) {
113 return sizeof(AudioDataValue) * aChannels;
116 static size_t AudioDataSize(uint32_t aFrames, uint32_t aChannels) {
117 return aFrames * BytesPerFrame(aChannels);
120 MediaQueue<AudioData>& mQueue;
121 size_t mSamplesPadding;
124 } // namespace mozilla
126 #endif // AudioCompactor_h