1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/AudioCompactor.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,121 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 +#if !defined(AudioCompactor_h) 1.10 +#define AudioCompactor_h 1.11 + 1.12 +#include "MediaQueue.h" 1.13 +#include "MediaData.h" 1.14 +#include "VideoUtils.h" 1.15 + 1.16 +namespace mozilla { 1.17 + 1.18 +class AudioCompactor 1.19 +{ 1.20 +public: 1.21 + AudioCompactor(MediaQueue<AudioData>& aQueue) 1.22 + : mQueue(aQueue) 1.23 + { } 1.24 + 1.25 + // Push audio data into the underlying queue with minimal heap allocation 1.26 + // slop. This method is responsible for allocating AudioDataValue[] buffers. 1.27 + // The caller must provide a functor to copy the data into the buffers. The 1.28 + // functor must provide the following signature: 1.29 + // 1.30 + // uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples); 1.31 + // 1.32 + // The functor must copy as many complete frames as possible to the provided 1.33 + // buffer given its length (in AudioDataValue elements). The number of frames 1.34 + // copied must be returned. This copy functor must support being called 1.35 + // multiple times in order to copy the audio data fully. The copy functor 1.36 + // must copy full frames as partial frames will be ignored. 1.37 + template<typename CopyFunc> 1.38 + bool Push(int64_t aOffset, int64_t aTime, int32_t aSampleRate, 1.39 + uint32_t aFrames, uint32_t aChannels, CopyFunc aCopyFunc) 1.40 + { 1.41 + // If we are losing more than a reasonable amount to padding, try to chunk 1.42 + // the data. 1.43 + size_t maxSlop = AudioDataSize(aFrames, aChannels) / MAX_SLOP_DIVISOR; 1.44 + 1.45 + while (aFrames > 0) { 1.46 + uint32_t samples = GetChunkSamples(aFrames, aChannels, maxSlop); 1.47 + nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[samples]); 1.48 + 1.49 + // Copy audio data to buffer using caller-provided functor. 1.50 + uint32_t framesCopied = aCopyFunc(buffer, samples); 1.51 + 1.52 + NS_ASSERTION(framesCopied <= aFrames, "functor copied too many frames"); 1.53 + 1.54 + CheckedInt64 duration = FramesToUsecs(framesCopied, aSampleRate); 1.55 + if (!duration.isValid()) { 1.56 + return false; 1.57 + } 1.58 + 1.59 + mQueue.Push(new AudioData(aOffset, 1.60 + aTime, 1.61 + duration.value(), 1.62 + framesCopied, 1.63 + buffer.forget(), 1.64 + aChannels)); 1.65 + 1.66 + // Remove the frames we just pushed into the queue and loop if there is 1.67 + // more to be done. 1.68 + aTime += duration.value(); 1.69 + aFrames -= framesCopied; 1.70 + 1.71 + // NOTE: No need to update aOffset as its only an approximation anyway. 1.72 + } 1.73 + 1.74 + return true; 1.75 + } 1.76 + 1.77 + // Copy functor suitable for copying audio samples already in the 1.78 + // AudioDataValue format/layout expected by AudioStream on this platform. 1.79 + class NativeCopy 1.80 + { 1.81 + public: 1.82 + NativeCopy(const uint8_t* aSource, size_t aSourceBytes, 1.83 + uint32_t aChannels) 1.84 + : mSource(aSource) 1.85 + , mSourceBytes(aSourceBytes) 1.86 + , mChannels(aChannels) 1.87 + , mNextByte(0) 1.88 + { } 1.89 + 1.90 + uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples); 1.91 + 1.92 + private: 1.93 + const uint8_t* const mSource; 1.94 + const size_t mSourceBytes; 1.95 + const uint32_t mChannels; 1.96 + size_t mNextByte; 1.97 + }; 1.98 + 1.99 + // Allow 12.5% slop before chunking kicks in. Public so that the gtest can 1.100 + // access it. 1.101 + static const size_t MAX_SLOP_DIVISOR = 8; 1.102 + 1.103 +private: 1.104 + // Compute the number of AudioDataValue samples that will be fit the most 1.105 + // frames while keeping heap allocation slop less than the given threshold. 1.106 + static uint32_t 1.107 + GetChunkSamples(uint32_t aFrames, uint32_t aChannels, size_t aMaxSlop); 1.108 + 1.109 + static size_t BytesPerFrame(uint32_t aChannels) 1.110 + { 1.111 + return sizeof(AudioDataValue) * aChannels; 1.112 + } 1.113 + 1.114 + static size_t AudioDataSize(uint32_t aFrames, uint32_t aChannels) 1.115 + { 1.116 + return aFrames * BytesPerFrame(aChannels); 1.117 + } 1.118 + 1.119 + MediaQueue<AudioData> &mQueue; 1.120 +}; 1.121 + 1.122 +} // namespace mozilla 1.123 + 1.124 +#endif // AudioCompactor_h