content/media/AudioCompactor.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     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 {
    17 public:
    18   AudioCompactor(MediaQueue<AudioData>& aQueue)
    19     : mQueue(aQueue)
    20   { }
    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;
    42     while (aFrames > 0) {
    43       uint32_t samples = GetChunkSamples(aFrames, aChannels, maxSlop);
    44       nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[samples]);
    46       // Copy audio data to buffer using caller-provided functor.
    47       uint32_t framesCopied = aCopyFunc(buffer, samples);
    49       NS_ASSERTION(framesCopied <= aFrames, "functor copied too many frames");
    51       CheckedInt64 duration = FramesToUsecs(framesCopied, aSampleRate);
    52       if (!duration.isValid()) {
    53         return false;
    54       }
    56       mQueue.Push(new AudioData(aOffset,
    57                                 aTime,
    58                                 duration.value(),
    59                                 framesCopied,
    60                                 buffer.forget(),
    61                                 aChannels));
    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;
    68       // NOTE: No need to update aOffset as its only an approximation anyway.
    69     }
    71     return true;
    72   }
    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     { }
    87     uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples);
    89   private:
    90     const uint8_t* const mSource;
    91     const size_t mSourceBytes;
    92     const uint32_t mChannels;
    93     size_t mNextByte;
    94   };
    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;
   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);
   106   static size_t BytesPerFrame(uint32_t aChannels)
   107   {
   108     return sizeof(AudioDataValue) * aChannels;
   109   }
   111   static size_t AudioDataSize(uint32_t aFrames, uint32_t aChannels)
   112   {
   113     return aFrames * BytesPerFrame(aChannels);
   114   }
   116   MediaQueue<AudioData> &mQueue;
   117 };
   119 } // namespace mozilla
   121 #endif // AudioCompactor_h

mercurial