summaryrefslogtreecommitdiffstats
path: root/dom/media/gtest/TestAudioCompactor.cpp
blob: 8c37a98ddf321f1358a2b5d769dc1a7b0c156f92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "AudioCompactor.h"
#include "nsDeque.h"
#include "nsIMemoryReporter.h"

using mozilla::AudioCompactor;
using mozilla::AudioData;
using mozilla::AudioDataValue;
using mozilla::MediaQueue;

class MemoryFunctor : public nsDequeFunctor<AudioData> {
 public:
  MemoryFunctor() : mSize(0) {}
  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf);

  void operator()(AudioData* aObject) override {
    mSize += aObject->SizeOfIncludingThis(MallocSizeOf);
  }

  size_t mSize;
};

class TestCopy {
 public:
  TestCopy(uint32_t aFrames, uint32_t aChannels, uint32_t& aCallCount,
           uint32_t& aFrameCount)
      : mFrames(aFrames),
        mChannels(aChannels),
        mCallCount(aCallCount),
        mFrameCount(aFrameCount) {}

  uint32_t operator()(AudioDataValue* aBuffer, uint32_t aSamples) {
    mCallCount += 1;
    uint32_t frames = std::min(mFrames - mFrameCount, aSamples / mChannels);
    mFrameCount += frames;
    return frames;
  }

 private:
  const uint32_t mFrames;
  const uint32_t mChannels;
  uint32_t& mCallCount;
  uint32_t& mFrameCount;
};

static void TestAudioCompactor(size_t aBytes) {
  MediaQueue<AudioData> queue;
  AudioCompactor compactor(queue);

  uint64_t offset = 0;
  uint64_t time = 0;
  uint32_t sampleRate = 44000;
  uint32_t channels = 2;
  uint32_t frames = aBytes / (channels * sizeof(AudioDataValue));
  size_t maxSlop = aBytes / AudioCompactor::MAX_SLOP_DIVISOR;

  uint32_t callCount = 0;
  uint32_t frameCount = 0;

  compactor.Push(offset, time, sampleRate, frames, channels,
                 TestCopy(frames, channels, callCount, frameCount));

  EXPECT_GT(callCount, 0U) << "copy functor never called";
  EXPECT_EQ(frames, frameCount) << "incorrect number of frames copied";

  MemoryFunctor memoryFunc;
  queue.LockedForEach(memoryFunc);
  size_t allocSize = memoryFunc.mSize - (callCount * sizeof(AudioData));
  size_t slop = allocSize - aBytes;
  EXPECT_LE(slop, maxSlop) << "allowed too much allocation slop";
}

TEST(Media, AudioCompactor_4000)
{ TestAudioCompactor(4000); }

TEST(Media, AudioCompactor_4096)
{ TestAudioCompactor(4096); }

TEST(Media, AudioCompactor_5000)
{ TestAudioCompactor(5000); }

TEST(Media, AudioCompactor_5256)
{ TestAudioCompactor(5256); }

TEST(Media, AudioCompactor_NativeCopy)
{
  const uint32_t channels = 2;
  const size_t srcBytes = 32;
  const uint32_t srcSamples = srcBytes / sizeof(AudioDataValue);
  const uint32_t srcFrames = srcSamples / channels;
  uint8_t src[srcBytes];

  for (uint32_t i = 0; i < srcBytes; ++i) {
    src[i] = i;
  }

  AudioCompactor::NativeCopy copy(src, srcBytes, channels);

  const uint32_t dstSamples = srcSamples * 2;
  AudioDataValue dst[dstSamples];

  const AudioDataValue notCopied = 0xffff;
  for (uint32_t i = 0; i < dstSamples; ++i) {
    dst[i] = notCopied;
  }

  const uint32_t copyCount = 8;
  uint32_t copiedFrames = 0;
  uint32_t nextSample = 0;
  for (uint32_t i = 0; i < copyCount; ++i) {
    uint32_t copySamples = dstSamples / copyCount;
    copiedFrames += copy(dst + nextSample, copySamples);
    nextSample += copySamples;
  }

  EXPECT_EQ(srcFrames, copiedFrames) << "copy exact number of source frames";

  // Verify that the only the correct bytes were copied.
  for (uint32_t i = 0; i < dstSamples; ++i) {
    if (i < srcSamples) {
      EXPECT_NE(notCopied, dst[i]) << "should have copied over these bytes";
    } else {
      EXPECT_EQ(notCopied, dst[i]) << "should not have copied over these bytes";
    }
  }
}