gecko-dev/dom/media/gtest/TestAudioTrackEncoder.cpp
Mihai Alexandru Michis e0b0dfa5eb Backed out 15 changesets (bug 1014393) for causing bustages in TestMuxer.cpp and gmock-internal-utils.h CLOSED TREE
Backed out changeset 0ddbdbfa87f6 (bug 1014393)
Backed out changeset 37399c83d3bf (bug 1014393)
Backed out changeset fe652475a785 (bug 1014393)
Backed out changeset 2812ca77d87d (bug 1014393)
Backed out changeset 6755ef7b361c (bug 1014393)
Backed out changeset 72e545bdcce3 (bug 1014393)
Backed out changeset 2f030ee55722 (bug 1014393)
Backed out changeset e9416b502170 (bug 1014393)
Backed out changeset 5a01d6d44634 (bug 1014393)
Backed out changeset 3457a5065dc4 (bug 1014393)
Backed out changeset 2a4999e0475b (bug 1014393)
Backed out changeset 0be3804dc04e (bug 1014393)
Backed out changeset 234994d8f136 (bug 1014393)
Backed out changeset d17f91ff2014 (bug 1014393)
Backed out changeset 25f58baa8159 (bug 1014393)

--HG--
rename : dom/media/encoder/EncodedFrame.h => dom/media/encoder/EncodedFrameContainer.h
2019-07-12 17:18:23 +03:00

238 lines
7.7 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 "OpusTrackEncoder.h"
#include "SineWaveGenerator.h"
using namespace mozilla;
class AudioGenerator {
public:
AudioGenerator(int32_t aChannels, int32_t aSampleRate)
: mGenerator(aSampleRate, 1000), mChannels(aChannels) {}
void Generate(AudioSegment& aSegment, const int32_t& aSamples) {
RefPtr<SharedBuffer> buffer =
SharedBuffer::Create(aSamples * sizeof(int16_t));
int16_t* dest = static_cast<int16_t*>(buffer->Data());
mGenerator.generate(dest, aSamples);
AutoTArray<const int16_t*, 1> channels;
for (int32_t i = 0; i < mChannels; i++) {
channels.AppendElement(dest);
}
aSegment.AppendFrames(buffer.forget(), channels, aSamples,
PRINCIPAL_HANDLE_NONE);
}
private:
SineWaveGenerator mGenerator;
const int32_t mChannels;
};
class TestOpusTrackEncoder : public OpusTrackEncoder {
public:
TestOpusTrackEncoder() : OpusTrackEncoder(90000) {}
// Return true if it has successfully initialized the Opus encoder.
bool TestOpusRawCreation(int aChannels, int aSamplingRate) {
if (Init(aChannels, aSamplingRate) == NS_OK) {
if (IsInitialized()) {
return true;
}
}
return false;
}
// Return the sample rate of data to be fed to the Opus encoder, could be
// re-sampled if it was not one of the Opus supported sampling rates.
// Init() is expected to be called first.
int TestGetOutputSampleRate() {
return mInitialized ? GetOutputSampleRate() : 0;
}
};
static bool TestOpusInit(int aChannels, int aSamplingRate) {
TestOpusTrackEncoder encoder;
return encoder.TestOpusRawCreation(aChannels, aSamplingRate);
}
TEST(OpusAudioTrackEncoder, InitRaw)
{
// Expect false with 0 or negative channels of input signal.
EXPECT_FALSE(TestOpusInit(0, 16000));
EXPECT_FALSE(TestOpusInit(-1, 16000));
// The Opus format supports up to 8 channels, and supports multitrack audio up
// to 255 channels, but the current implementation supports only mono and
// stereo, and downmixes any more than that.
// Expect false with channels of input signal exceed the max supported number.
EXPECT_FALSE(TestOpusInit(8 + 1, 16000));
// Should accept channels within valid range.
for (int i = 1; i <= 8; i++) {
EXPECT_TRUE(TestOpusInit(i, 16000));
}
// Expect false with 0 or negative sampling rate of input signal.
EXPECT_FALSE(TestOpusInit(1, 0));
EXPECT_FALSE(TestOpusInit(1, -1));
// Verify sample rate bounds checking.
EXPECT_FALSE(TestOpusInit(2, 2000));
EXPECT_FALSE(TestOpusInit(2, 4000));
EXPECT_FALSE(TestOpusInit(2, 7999));
EXPECT_TRUE(TestOpusInit(2, 8000));
EXPECT_TRUE(TestOpusInit(2, 192000));
EXPECT_FALSE(TestOpusInit(2, 192001));
EXPECT_FALSE(TestOpusInit(2, 200000));
}
TEST(OpusAudioTrackEncoder, Init)
{
{
// The encoder does not normally recieve enough info from null data to
// init. However, multiple attempts to do so, with sufficiently long
// duration segments, should result in a best effort attempt. The first
// attempt should never do this though, even if the duration is long:
OpusTrackEncoder encoder(48000);
AudioSegment segment;
segment.AppendNullData(48000 * 100);
encoder.TryInit(segment, segment.GetDuration());
EXPECT_FALSE(encoder.IsInitialized());
// Multiple init attempts should result in best effort init:
encoder.TryInit(segment, segment.GetDuration());
EXPECT_TRUE(encoder.IsInitialized());
}
{
// If the duration of the segments given to the encoder is not long then
// we shouldn't try a best effort init:
OpusTrackEncoder encoder(48000);
AudioSegment segment;
segment.AppendNullData(1);
encoder.TryInit(segment, segment.GetDuration());
EXPECT_FALSE(encoder.IsInitialized());
encoder.TryInit(segment, segment.GetDuration());
EXPECT_FALSE(encoder.IsInitialized());
}
{
// For non-null segments we should init immediately
OpusTrackEncoder encoder(48000);
AudioSegment segment;
AudioGenerator generator(2, 48000);
generator.Generate(segment, 1);
encoder.TryInit(segment, segment.GetDuration());
EXPECT_TRUE(encoder.IsInitialized());
}
{
// Test low sample rate bound
OpusTrackEncoder encoder(7999);
AudioSegment segment;
AudioGenerator generator(2, 7999);
generator.Generate(segment, 1);
encoder.TryInit(segment, segment.GetDuration());
EXPECT_FALSE(encoder.IsInitialized());
}
{
// Test low sample rate bound
OpusTrackEncoder encoder(8000);
AudioSegment segment;
AudioGenerator generator(2, 8000);
generator.Generate(segment, 1);
encoder.TryInit(segment, segment.GetDuration());
EXPECT_TRUE(encoder.IsInitialized());
}
{
// Test high sample rate bound
OpusTrackEncoder encoder(192001);
AudioSegment segment;
AudioGenerator generator(2, 192001);
generator.Generate(segment, 1);
encoder.TryInit(segment, segment.GetDuration());
EXPECT_FALSE(encoder.IsInitialized());
}
{
// Test high sample rate bound
OpusTrackEncoder encoder(192000);
AudioSegment segment;
AudioGenerator generator(2, 192000);
generator.Generate(segment, 1);
encoder.TryInit(segment, segment.GetDuration());
EXPECT_TRUE(encoder.IsInitialized());
}
}
static int TestOpusResampler(int aChannels, int aSamplingRate) {
TestOpusTrackEncoder encoder;
EXPECT_TRUE(encoder.TestOpusRawCreation(aChannels, aSamplingRate));
return encoder.TestGetOutputSampleRate();
}
TEST(OpusAudioTrackEncoder, Resample)
{
// Sampling rates of data to be fed to Opus encoder, should remain unchanged
// if it is one of Opus supported rates (8000, 12000, 16000, 24000 and 48000
// (kHz)) at initialization.
EXPECT_TRUE(TestOpusResampler(1, 8000) == 8000);
EXPECT_TRUE(TestOpusResampler(1, 12000) == 12000);
EXPECT_TRUE(TestOpusResampler(1, 16000) == 16000);
EXPECT_TRUE(TestOpusResampler(1, 24000) == 24000);
EXPECT_TRUE(TestOpusResampler(1, 48000) == 48000);
// Otherwise, it should be resampled to 48kHz by resampler.
EXPECT_TRUE(TestOpusResampler(1, 9600) == 48000);
EXPECT_TRUE(TestOpusResampler(1, 44100) == 48000);
}
TEST(OpusAudioTrackEncoder, FetchMetadata)
{
const int32_t channels = 1;
const int32_t sampleRate = 44100;
TestOpusTrackEncoder encoder;
EXPECT_TRUE(encoder.TestOpusRawCreation(channels, sampleRate));
RefPtr<TrackMetadataBase> metadata = encoder.GetMetadata();
ASSERT_EQ(TrackMetadataBase::METADATA_OPUS, metadata->GetKind());
RefPtr<OpusMetadata> opusMeta = static_cast<OpusMetadata*>(metadata.get());
EXPECT_EQ(channels, opusMeta->mChannels);
EXPECT_EQ(sampleRate, opusMeta->mSamplingFrequency);
}
TEST(OpusAudioTrackEncoder, FrameEncode)
{
const int32_t channels = 1;
const int32_t sampleRate = 44100;
TestOpusTrackEncoder encoder;
EXPECT_TRUE(encoder.TestOpusRawCreation(channels, sampleRate));
// Generate five seconds of raw audio data.
AudioGenerator generator(channels, sampleRate);
AudioSegment segment;
const int32_t samples = sampleRate * 5;
generator.Generate(segment, samples);
encoder.AppendAudioSegment(std::move(segment));
EncodedFrameContainer container;
EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
// Verify that encoded data is 5 seconds long.
uint64_t totalDuration = 0;
for (auto& frame : container.GetEncodedFrames()) {
totalDuration += frame->GetDuration();
}
// 44100 as used above gets resampled to 48000 for opus.
const uint64_t five = 48000 * 5;
EXPECT_EQ(five, totalDuration);
}