content/media/AudioCompactor.h

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:52e5a5cfa363
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
8
9 #include "MediaQueue.h"
10 #include "MediaData.h"
11 #include "VideoUtils.h"
12
13 namespace mozilla {
14
15 class AudioCompactor
16 {
17 public:
18 AudioCompactor(MediaQueue<AudioData>& aQueue)
19 : mQueue(aQueue)
20 { }
21
22 // Push audio data into the underlying queue with minimal heap allocation
23 // slop. This method is responsible for allocating AudioDataValue[] buffers.
24 // The caller must provide a functor to copy the data into the buffers. The
25 // functor must provide the following signature:
26 //
27 // uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples);
28 //
29 // The functor must copy as many complete frames as possible to the provided
30 // buffer given its length (in AudioDataValue elements). The number of frames
31 // copied must be returned. This copy functor must support being called
32 // multiple times in order to copy the audio data fully. The copy functor
33 // must copy full frames as partial frames will be ignored.
34 template<typename CopyFunc>
35 bool Push(int64_t aOffset, int64_t aTime, int32_t aSampleRate,
36 uint32_t aFrames, uint32_t aChannels, CopyFunc aCopyFunc)
37 {
38 // If we are losing more than a reasonable amount to padding, try to chunk
39 // the data.
40 size_t maxSlop = AudioDataSize(aFrames, aChannels) / MAX_SLOP_DIVISOR;
41
42 while (aFrames > 0) {
43 uint32_t samples = GetChunkSamples(aFrames, aChannels, maxSlop);
44 nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[samples]);
45
46 // Copy audio data to buffer using caller-provided functor.
47 uint32_t framesCopied = aCopyFunc(buffer, samples);
48
49 NS_ASSERTION(framesCopied <= aFrames, "functor copied too many frames");
50
51 CheckedInt64 duration = FramesToUsecs(framesCopied, aSampleRate);
52 if (!duration.isValid()) {
53 return false;
54 }
55
56 mQueue.Push(new AudioData(aOffset,
57 aTime,
58 duration.value(),
59 framesCopied,
60 buffer.forget(),
61 aChannels));
62
63 // Remove the frames we just pushed into the queue and loop if there is
64 // more to be done.
65 aTime += duration.value();
66 aFrames -= framesCopied;
67
68 // NOTE: No need to update aOffset as its only an approximation anyway.
69 }
70
71 return true;
72 }
73
74 // Copy functor suitable for copying audio samples already in the
75 // AudioDataValue format/layout expected by AudioStream on this platform.
76 class NativeCopy
77 {
78 public:
79 NativeCopy(const uint8_t* aSource, size_t aSourceBytes,
80 uint32_t aChannels)
81 : mSource(aSource)
82 , mSourceBytes(aSourceBytes)
83 , mChannels(aChannels)
84 , mNextByte(0)
85 { }
86
87 uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples);
88
89 private:
90 const uint8_t* const mSource;
91 const size_t mSourceBytes;
92 const uint32_t mChannels;
93 size_t mNextByte;
94 };
95
96 // Allow 12.5% slop before chunking kicks in. Public so that the gtest can
97 // access it.
98 static const size_t MAX_SLOP_DIVISOR = 8;
99
100 private:
101 // Compute the number of AudioDataValue samples that will be fit the most
102 // frames while keeping heap allocation slop less than the given threshold.
103 static uint32_t
104 GetChunkSamples(uint32_t aFrames, uint32_t aChannels, size_t aMaxSlop);
105
106 static size_t BytesPerFrame(uint32_t aChannels)
107 {
108 return sizeof(AudioDataValue) * aChannels;
109 }
110
111 static size_t AudioDataSize(uint32_t aFrames, uint32_t aChannels)
112 {
113 return aFrames * BytesPerFrame(aChannels);
114 }
115
116 MediaQueue<AudioData> &mQueue;
117 };
118
119 } // namespace mozilla
120
121 #endif // AudioCompactor_h

mercurial