mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-26 11:45:37 +00:00
Bug 951043 - [MediaEncoder::GTest] Implement unit test of Vorbis encoding. r=rillian
This commit is contained in:
parent
249ed48c5d
commit
eb0de7a40a
213
content/media/gtest/TestVorbisTrackEncoder.cpp
Normal file
213
content/media/gtest/TestVorbisTrackEncoder.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/* -*- 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 "VorbisTrackEncoder.h"
|
||||
#include "WebMWriter.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
class TestVorbisTrackEncoder : public VorbisTrackEncoder
|
||||
{
|
||||
public:
|
||||
// Return true if it has successfully initialized the vorbis encoder.
|
||||
bool TestVorbisCreation(int aChannels, int aSamplingRate)
|
||||
{
|
||||
if (Init(aChannels, aSamplingRate) == NS_OK) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static bool
|
||||
TestVorbisInit(int aChannels, int aSamplingRate)
|
||||
{
|
||||
TestVorbisTrackEncoder encoder;
|
||||
return encoder.TestVorbisCreation(aChannels, aSamplingRate);
|
||||
}
|
||||
|
||||
static int
|
||||
ReadLacing(const uint8_t* aInput, uint32_t aInputLength, uint32_t& aReadBytes)
|
||||
{
|
||||
aReadBytes = 0;
|
||||
|
||||
int packetSize = 0;
|
||||
while (aReadBytes < aInputLength) {
|
||||
if (aInput[aReadBytes] == 255) {
|
||||
packetSize += 255;
|
||||
aReadBytes++;
|
||||
} else { // the last byte
|
||||
packetSize += aInput[aReadBytes];
|
||||
aReadBytes++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return packetSize;
|
||||
}
|
||||
|
||||
static bool
|
||||
parseVorbisMetadata(nsTArray<uint8_t>& aData, int aChannels, int aRate)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
// the first byte should be 2.
|
||||
if (aData.ElementAt(0) != 2) {
|
||||
return false;
|
||||
}
|
||||
offset = 1;
|
||||
|
||||
// Read the length of header and header_comm
|
||||
uint32_t readbytes;
|
||||
ogg_packet header;
|
||||
ogg_packet header_comm;
|
||||
ogg_packet header_code;
|
||||
int header_length;
|
||||
int header_comm_length;
|
||||
int header_code_length;
|
||||
EXPECT_TRUE(offset < aData.Length());
|
||||
header_length = ReadLacing(aData.Elements()+offset, aData.Length()-offset,
|
||||
readbytes);
|
||||
offset += readbytes;
|
||||
EXPECT_TRUE(offset < aData.Length());
|
||||
header_comm_length = ReadLacing(aData.Elements()+offset,
|
||||
aData.Length()-offset, readbytes);
|
||||
offset += readbytes;
|
||||
EXPECT_TRUE(offset < aData.Length());
|
||||
// The rest length is header_code.
|
||||
header_code_length = aData.Length() - offset - header_length
|
||||
- header_comm_length;
|
||||
EXPECT_TRUE(header_code_length >= 32);
|
||||
|
||||
// Verify the three header packets by vorbis_synthesis_headerin.
|
||||
header.packet = aData.Elements() + offset;
|
||||
header.bytes = header_length;
|
||||
offset += header_length;
|
||||
header_comm.packet = aData.Elements() + offset;
|
||||
header_comm.bytes = header_comm_length;
|
||||
offset += header_comm_length;
|
||||
header_code.packet = aData.Elements() + offset;
|
||||
header_code.bytes = header_code_length;
|
||||
|
||||
vorbis_info vi;
|
||||
vorbis_comment vc;
|
||||
vorbis_info_init(&vi);
|
||||
vorbis_comment_init(&vc);
|
||||
EXPECT_TRUE(0 == vorbis_synthesis_headerin(&vi,&vc,&header));
|
||||
|
||||
EXPECT_TRUE(0 == vorbis_synthesis_headerin(&vi,&vc,&header_comm));
|
||||
|
||||
EXPECT_TRUE(0 == vorbis_synthesis_headerin(&vi,&vc,&header_code));
|
||||
|
||||
EXPECT_TRUE(vi.channels == aChannels);
|
||||
EXPECT_TRUE(vi.rate == aRate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test init function
|
||||
TEST(VorbisTrackEncoder, Init)
|
||||
{
|
||||
// Channel number range test
|
||||
// Expect false with 0 or negative channels of input signal.
|
||||
EXPECT_FALSE(TestVorbisInit(0, 16000));
|
||||
EXPECT_FALSE(TestVorbisInit(-1, 16000));
|
||||
EXPECT_FALSE(TestVorbisInit(8 + 1, 16000));
|
||||
|
||||
// Sample rate and channel range test.
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
EXPECT_FALSE(TestVorbisInit(i, -1));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 8000));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 11000));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 16000));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 22050));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 32000));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 44100));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 48000));
|
||||
EXPECT_TRUE(TestVorbisInit(i, 96000));
|
||||
EXPECT_FALSE(TestVorbisInit(i, 200000 + 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Test metadata
|
||||
TEST(VorbisTrackEncoder, Metadata)
|
||||
{
|
||||
// Initiate vorbis encoder.
|
||||
TestVorbisTrackEncoder encoder;
|
||||
int channels = 1;
|
||||
int rate = 44100;
|
||||
encoder.TestVorbisCreation(channels, rate);
|
||||
|
||||
nsRefPtr<TrackMetadataBase> meta = encoder.GetMetadata();
|
||||
nsRefPtr<VorbisMetadata> vorbisMetadata(static_cast<VorbisMetadata*>(meta.get()));
|
||||
|
||||
// According to initialization parameters, verify the correctness
|
||||
// of vorbisMetadata.
|
||||
EXPECT_TRUE(vorbisMetadata->mChannels == channels);
|
||||
EXPECT_TRUE(vorbisMetadata->mSamplingFrequency == rate);
|
||||
EXPECT_TRUE(parseVorbisMetadata(vorbisMetadata->mData, channels, rate));
|
||||
}
|
||||
|
||||
// Test encode function
|
||||
TEST(VorbisTrackEncoder, EncodedFrame)
|
||||
{
|
||||
// Initiate vorbis encoder
|
||||
TestVorbisTrackEncoder encoder;
|
||||
int channels = 1;
|
||||
int rate = 44100;
|
||||
encoder.TestVorbisCreation(channels, rate);
|
||||
|
||||
// Generate 1 second samples.
|
||||
// Reference PeerConnectionMedia.h::Fake_AudioGenerator
|
||||
nsRefPtr<mozilla::SharedBuffer> samples =
|
||||
mozilla::SharedBuffer::Create(rate * sizeof(AudioDataValue));
|
||||
AudioDataValue* data = static_cast<AudioDataValue*>(samples->Data());
|
||||
for (int i = 0; i < rate; i++) {
|
||||
data[i] = ((i%8)*4000) - (7*4000)/2;
|
||||
}
|
||||
nsAutoTArray<const AudioDataValue*,1> channelData;
|
||||
channelData.AppendElement(data);
|
||||
AudioSegment segment;
|
||||
segment.AppendFrames(samples.forget(), channelData, 44100);
|
||||
|
||||
// Track change notification.
|
||||
encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, 0, 0, segment);
|
||||
|
||||
// Pull Encoded data back from encoder and verify encoded samples.
|
||||
EncodedFrameContainer container;
|
||||
EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
|
||||
// Should have some encoded data.
|
||||
EXPECT_TRUE(container.GetEncodedFrames().Length() > 0);
|
||||
EXPECT_TRUE(container.GetEncodedFrames().ElementAt(0)->GetFrameData().Length()
|
||||
> 0);
|
||||
EXPECT_TRUE(container.GetEncodedFrames().ElementAt(0)->GetFrameType() ==
|
||||
EncodedFrame::FrameType::VORBIS_AUDIO_FRAME);
|
||||
// Encoded data doesn't have duration and timestamp.
|
||||
EXPECT_TRUE(container.GetEncodedFrames().ElementAt(0)->GetDuration() == 0);
|
||||
EXPECT_TRUE(container.GetEncodedFrames().ElementAt(0)->GetTimeStamp() == 0);
|
||||
}
|
||||
|
||||
// EOS test
|
||||
TEST(VorbisTrackEncoder, EncodeComplete)
|
||||
{
|
||||
// Initiate vorbis encoder
|
||||
TestVorbisTrackEncoder encoder;
|
||||
int channels = 1;
|
||||
int rate = 44100;
|
||||
encoder.TestVorbisCreation(channels, rate);
|
||||
|
||||
// Track end notification.
|
||||
AudioSegment segment;
|
||||
encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, 0,
|
||||
MediaStreamListener::TRACK_EVENT_ENDED,
|
||||
segment);
|
||||
|
||||
// Pull Encoded Data back from encoder. Since we had send out
|
||||
// EOS to encoder, encoder.GetEncodedTrack should return
|
||||
// NS_OK immidiately.
|
||||
EncodedFrameContainer container;
|
||||
EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
|
||||
}
|
@ -13,6 +13,7 @@ UNIFIED_SOURCES += [
|
||||
|
||||
if CONFIG['MOZ_WEBM_ENCODER']:
|
||||
UNIFIED_SOURCES += ['TestVideoTrackEncoder.cpp',
|
||||
'TestVorbisTrackEncoder.cpp',
|
||||
]
|
||||
|
||||
EXPORT_LIBRARY = True
|
||||
|
Loading…
Reference in New Issue
Block a user