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 #include "gtest/gtest.h"
7 #include "AudioCompactor.h"
8 #include "nsDeque.h"
9 #include "nsIMemoryReporter.h"
10 
11 using mozilla::AudioCompactor;
12 using mozilla::AudioData;
13 using mozilla::AudioDataValue;
14 using mozilla::MediaQueue;
15 
16 class MemoryFunctor : public nsDequeFunctor<AudioData> {
17  public:
MemoryFunctor()18   MemoryFunctor() : mSize(0) {}
19   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);
20 
operator ()(AudioData * aObject)21   void operator()(AudioData* aObject) override {
22     mSize += aObject->SizeOfIncludingThis(MallocSizeOf);
23   }
24 
25   size_t mSize;
26 };
27 
28 class TestCopy {
29  public:
TestCopy(uint32_t aFrames,uint32_t aChannels,uint32_t & aCallCount,uint32_t & aFrameCount)30   TestCopy(uint32_t aFrames, uint32_t aChannels, uint32_t& aCallCount,
31            uint32_t& aFrameCount)
32       : mFrames(aFrames),
33         mChannels(aChannels),
34         mCallCount(aCallCount),
35         mFrameCount(aFrameCount) {}
36 
operator ()(AudioDataValue * aBuffer,uint32_t aSamples)37   uint32_t operator()(AudioDataValue* aBuffer, uint32_t aSamples) {
38     mCallCount += 1;
39     uint32_t frames = std::min(mFrames - mFrameCount, aSamples / mChannels);
40     mFrameCount += frames;
41     return frames;
42   }
43 
44  private:
45   const uint32_t mFrames;
46   const uint32_t mChannels;
47   uint32_t& mCallCount;
48   uint32_t& mFrameCount;
49 };
50 
TestAudioCompactor(size_t aBytes)51 static void TestAudioCompactor(size_t aBytes) {
52   MediaQueue<AudioData> queue;
53   AudioCompactor compactor(queue);
54 
55   uint64_t offset = 0;
56   uint64_t time = 0;
57   uint32_t sampleRate = 44000;
58   uint32_t channels = 2;
59   uint32_t frames = aBytes / (channels * sizeof(AudioDataValue));
60   size_t maxSlop = aBytes / AudioCompactor::MAX_SLOP_DIVISOR;
61 
62   uint32_t callCount = 0;
63   uint32_t frameCount = 0;
64 
65   compactor.Push(offset, time, sampleRate, frames, channels,
66                  TestCopy(frames, channels, callCount, frameCount));
67 
68   EXPECT_GT(callCount, 0U) << "copy functor never called";
69   EXPECT_EQ(frames, frameCount) << "incorrect number of frames copied";
70 
71   MemoryFunctor memoryFunc;
72   queue.LockedForEach(memoryFunc);
73   size_t allocSize = memoryFunc.mSize - (callCount * sizeof(AudioData));
74   size_t slop = allocSize - aBytes;
75   EXPECT_LE(slop, maxSlop) << "allowed too much allocation slop";
76 }
77 
TEST(Media,AudioCompactor_4000)78 TEST(Media, AudioCompactor_4000)
79 { TestAudioCompactor(4000); }
80 
TEST(Media,AudioCompactor_4096)81 TEST(Media, AudioCompactor_4096)
82 { TestAudioCompactor(4096); }
83 
TEST(Media,AudioCompactor_5000)84 TEST(Media, AudioCompactor_5000)
85 { TestAudioCompactor(5000); }
86 
TEST(Media,AudioCompactor_5256)87 TEST(Media, AudioCompactor_5256)
88 { TestAudioCompactor(5256); }
89 
TEST(Media,AudioCompactor_NativeCopy)90 TEST(Media, AudioCompactor_NativeCopy)
91 {
92   const uint32_t channels = 2;
93   const size_t srcBytes = 32;
94   const uint32_t srcSamples = srcBytes / sizeof(AudioDataValue);
95   const uint32_t srcFrames = srcSamples / channels;
96   uint8_t src[srcBytes];
97 
98   for (uint32_t i = 0; i < srcBytes; ++i) {
99     src[i] = i;
100   }
101 
102   AudioCompactor::NativeCopy copy(src, srcBytes, channels);
103 
104   const uint32_t dstSamples = srcSamples * 2;
105   AudioDataValue dst[dstSamples];
106 
107   const AudioDataValue notCopied = 0xffff;
108   for (uint32_t i = 0; i < dstSamples; ++i) {
109     dst[i] = notCopied;
110   }
111 
112   const uint32_t copyCount = 8;
113   uint32_t copiedFrames = 0;
114   uint32_t nextSample = 0;
115   for (uint32_t i = 0; i < copyCount; ++i) {
116     uint32_t copySamples = dstSamples / copyCount;
117     copiedFrames += copy(dst + nextSample, copySamples);
118     nextSample += copySamples;
119   }
120 
121   EXPECT_EQ(srcFrames, copiedFrames) << "copy exact number of source frames";
122 
123   // Verify that the only the correct bytes were copied.
124   for (uint32_t i = 0; i < dstSamples; ++i) {
125     if (i < srcSamples) {
126       EXPECT_NE(notCopied, dst[i]) << "should have copied over these bytes";
127     } else {
128       EXPECT_EQ(notCopied, dst[i]) << "should not have copied over these bytes";
129     }
130   }
131 }
132