michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: #include "gtest/gtest.h" michael@0: #include "AudioCompactor.h" michael@0: #include "MediaDecoderReader.h" michael@0: michael@0: using mozilla::AudioCompactor; michael@0: using mozilla::AudioData; michael@0: using mozilla::AudioDataValue; michael@0: using mozilla::MediaDecoderReader; michael@0: using mozilla::MediaQueue; michael@0: michael@0: class MemoryFunctor : public nsDequeFunctor { michael@0: public: michael@0: MemoryFunctor() : mSize(0) {} michael@0: MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf); michael@0: michael@0: virtual void* operator()(void* anObject) { michael@0: const AudioData* audioData = static_cast(anObject); michael@0: mSize += audioData->SizeOfIncludingThis(MallocSizeOf); michael@0: return nullptr; michael@0: } michael@0: michael@0: size_t mSize; michael@0: }; michael@0: michael@0: class TestCopy michael@0: { michael@0: public: michael@0: TestCopy(uint32_t aFrames, uint32_t aChannels, michael@0: uint32_t &aCallCount, uint32_t &aFrameCount) michael@0: : mFrames(aFrames) michael@0: , mChannels(aChannels) michael@0: , mCallCount(aCallCount) michael@0: , mFrameCount(aFrameCount) michael@0: { } michael@0: michael@0: uint32_t operator()(AudioDataValue *aBuffer, uint32_t aSamples) michael@0: { michael@0: mCallCount += 1; michael@0: uint32_t frames = std::min(mFrames - mFrameCount, aSamples / mChannels); michael@0: mFrameCount += frames; michael@0: return frames; michael@0: } michael@0: michael@0: private: michael@0: const uint32_t mFrames; michael@0: const uint32_t mChannels; michael@0: uint32_t &mCallCount; michael@0: uint32_t &mFrameCount; michael@0: }; michael@0: michael@0: static void TestAudioCompactor(size_t aBytes) michael@0: { michael@0: MediaQueue queue; michael@0: AudioCompactor compactor(queue); michael@0: michael@0: uint64_t offset = 0; michael@0: uint64_t time = 0; michael@0: uint32_t sampleRate = 44000; michael@0: uint32_t channels = 2; michael@0: uint32_t frames = aBytes / (channels * sizeof(AudioDataValue)); michael@0: size_t maxSlop = aBytes / AudioCompactor::MAX_SLOP_DIVISOR; michael@0: michael@0: uint32_t callCount = 0; michael@0: uint32_t frameCount = 0; michael@0: michael@0: compactor.Push(offset, time, sampleRate, frames, channels, michael@0: TestCopy(frames, channels, callCount, frameCount)); michael@0: michael@0: EXPECT_GT(callCount, 0U) << "copy functor never called"; michael@0: EXPECT_EQ(frames, frameCount) << "incorrect number of frames copied"; michael@0: michael@0: MemoryFunctor memoryFunc; michael@0: queue.LockedForEach(memoryFunc); michael@0: size_t allocSize = memoryFunc.mSize - (callCount * sizeof(AudioData)); michael@0: size_t slop = allocSize - aBytes; michael@0: EXPECT_LE(slop, maxSlop) << "allowed too much allocation slop"; michael@0: } michael@0: michael@0: TEST(Media, AudioCompactor_4000) michael@0: { michael@0: TestAudioCompactor(4000); michael@0: } michael@0: michael@0: TEST(Media, AudioCompactor_4096) michael@0: { michael@0: TestAudioCompactor(4096); michael@0: } michael@0: michael@0: TEST(Media, AudioCompactor_5000) michael@0: { michael@0: TestAudioCompactor(5000); michael@0: } michael@0: michael@0: TEST(Media, AudioCompactor_5256) michael@0: { michael@0: TestAudioCompactor(5256); michael@0: } michael@0: michael@0: TEST(Media, AudioCompactor_NativeCopy) michael@0: { michael@0: const uint32_t channels = 2; michael@0: const size_t srcBytes = 32; michael@0: const uint32_t srcSamples = srcBytes / sizeof(AudioDataValue); michael@0: const uint32_t srcFrames = srcSamples / channels; michael@0: uint8_t src[srcBytes]; michael@0: michael@0: for (uint32_t i = 0; i < srcBytes; ++i) { michael@0: src[i] = i; michael@0: } michael@0: michael@0: AudioCompactor::NativeCopy copy(src, srcBytes, channels); michael@0: michael@0: const uint32_t dstSamples = srcSamples * 2; michael@0: AudioDataValue dst[dstSamples]; michael@0: michael@0: const AudioDataValue notCopied = 0xffff; michael@0: for (uint32_t i = 0; i < dstSamples; ++i) { michael@0: dst[i] = notCopied; michael@0: } michael@0: michael@0: const uint32_t copyCount = 8; michael@0: uint32_t copiedFrames = 0; michael@0: uint32_t nextSample = 0; michael@0: for (uint32_t i = 0; i < copyCount; ++i) { michael@0: uint32_t copySamples = dstSamples / copyCount; michael@0: copiedFrames += copy(dst + nextSample, copySamples); michael@0: nextSample += copySamples; michael@0: } michael@0: michael@0: EXPECT_EQ(srcFrames, copiedFrames) << "copy exact number of source frames"; michael@0: michael@0: // Verify that the only the correct bytes were copied. michael@0: for (uint32_t i = 0; i < dstSamples; ++i) { michael@0: if (i < srcSamples) { michael@0: EXPECT_NE(notCopied, dst[i]) << "should have copied over these bytes"; michael@0: } else { michael@0: EXPECT_EQ(notCopied, dst[i]) << "should not have copied over these bytes"; michael@0: } michael@0: } michael@0: }