Delete NetEq::RegisterExternalDecoder.

Bug: webrtc:10080
Change-Id: Ie36b10af6ab22f498636e38f36bef11f28fc7f7e
Reviewed-on: https://webrtc-review.googlesource.com/c/112081
Reviewed-by: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26174}
This commit is contained in:
Niels Möller
2019-01-09 09:26:50 +01:00
committed by Commit Bot
parent c12d41b747
commit 9c277dd1dd
11 changed files with 44 additions and 365 deletions

View File

@ -1577,8 +1577,6 @@ if (rtc_include_tests) {
rtc_source_set("neteq_test_support") { rtc_source_set("neteq_test_support") {
testonly = true testonly = true
sources = [ sources = [
"neteq/tools/neteq_external_decoder_test.cc",
"neteq/tools/neteq_external_decoder_test.h",
"neteq/tools/neteq_performance_test.cc", "neteq/tools/neteq_performance_test.cc",
"neteq/tools/neteq_performance_test.h", "neteq/tools/neteq_performance_test.h",
] ]
@ -1992,13 +1990,11 @@ if (rtc_include_tests) {
"neteq/mock/mock_dtmf_buffer.h", "neteq/mock/mock_dtmf_buffer.h",
"neteq/mock/mock_dtmf_tone_generator.h", "neteq/mock/mock_dtmf_tone_generator.h",
"neteq/mock/mock_expand.h", "neteq/mock/mock_expand.h",
"neteq/mock/mock_external_decoder_pcm16b.h",
"neteq/mock/mock_packet_buffer.h", "neteq/mock/mock_packet_buffer.h",
"neteq/mock/mock_red_payload_splitter.h", "neteq/mock/mock_red_payload_splitter.h",
"neteq/mock/mock_statistics_calculator.h", "neteq/mock/mock_statistics_calculator.h",
"neteq/nack_tracker_unittest.cc", "neteq/nack_tracker_unittest.cc",
"neteq/neteq_decoder_plc_unittest.cc", "neteq/neteq_decoder_plc_unittest.cc",
"neteq/neteq_external_decoder_unittest.cc",
"neteq/neteq_impl_unittest.cc", "neteq/neteq_impl_unittest.cc",
"neteq/neteq_network_stats_unittest.cc", "neteq/neteq_network_stats_unittest.cc",
"neteq/neteq_stereo_unittest.cc", "neteq/neteq_stereo_unittest.cc",

View File

@ -43,7 +43,6 @@ DecoderDatabase::DecoderInfo::DecoderInfo(
audio_format_(audio_format), audio_format_(audio_format),
codec_pair_id_(codec_pair_id), codec_pair_id_(codec_pair_id),
factory_(factory), factory_(factory),
external_decoder_(nullptr),
cng_decoder_(CngDecoder::Create(audio_format)), cng_decoder_(CngDecoder::Create(audio_format)),
subtype_(SubtypeFromFormat(audio_format)) {} subtype_(SubtypeFromFormat(audio_format)) {}
@ -59,23 +58,11 @@ DecoderDatabase::DecoderInfo::DecoderInfo(
AudioDecoderFactory* factory) AudioDecoderFactory* factory)
: DecoderInfo(*NetEqDecoderToSdpAudioFormat(ct), codec_pair_id, factory) {} : DecoderInfo(*NetEqDecoderToSdpAudioFormat(ct), codec_pair_id, factory) {}
DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
AudioDecoder* ext_dec,
const std::string& codec_name)
: name_(codec_name),
audio_format_(audio_format),
codec_pair_id_(absl::nullopt),
factory_(nullptr),
external_decoder_(ext_dec),
subtype_(Subtype::kNormal) {
RTC_CHECK(ext_dec);
}
DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default; DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
DecoderDatabase::DecoderInfo::~DecoderInfo() = default; DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
bool DecoderDatabase::DecoderInfo::CanGetDecoder() const { bool DecoderDatabase::DecoderInfo::CanGetDecoder() const {
if (subtype_ == Subtype::kNormal && !external_decoder_ && !decoder_) { if (subtype_ == Subtype::kNormal && !decoder_) {
// TODO(ossu): Keep a check here for now, since a number of tests create // TODO(ossu): Keep a check here for now, since a number of tests create
// DecoderInfos without factories. // DecoderInfos without factories.
RTC_DCHECK(factory_); RTC_DCHECK(factory_);
@ -90,11 +77,6 @@ AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
// These are handled internally, so they have no AudioDecoder objects. // These are handled internally, so they have no AudioDecoder objects.
return nullptr; return nullptr;
} }
if (external_decoder_) {
RTC_DCHECK(!decoder_);
RTC_DCHECK(!cng_decoder_);
return external_decoder_;
}
if (!decoder_) { if (!decoder_) {
// TODO(ossu): Keep a check here for now, since a number of tests create // TODO(ossu): Keep a check here for now, since a number of tests create
// DecoderInfos without factories. // DecoderInfos without factories.
@ -227,31 +209,6 @@ int DecoderDatabase::RegisterPayload(int rtp_payload_type,
return kOK; return kOK;
} }
int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
NetEqDecoder codec_type,
const std::string& codec_name,
AudioDecoder* decoder) {
if (rtp_payload_type > 0x7F) {
return kInvalidRtpPayloadType;
}
if (!decoder) {
return kInvalidPointer;
}
const auto opt_db_format = NetEqDecoderToSdpAudioFormat(codec_type);
const SdpAudioFormat format =
opt_db_format.value_or(SdpAudioFormat("arbitrary", 0, 0));
std::pair<DecoderMap::iterator, bool> ret;
DecoderInfo info(format, decoder, codec_name);
ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
if (ret.second == false) {
// Database already contains a decoder with type |rtp_payload_type|.
return kDecoderExists;
}
return kOK;
}
int DecoderDatabase::Remove(uint8_t rtp_payload_type) { int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
if (decoders_.erase(rtp_payload_type) == 0) { if (decoders_.erase(rtp_payload_type) == 0) {
// No decoder with that |rtp_payload_type|. // No decoder with that |rtp_payload_type|.

View File

@ -50,9 +50,6 @@ class DecoderDatabase {
explicit DecoderInfo(NetEqDecoder ct, explicit DecoderInfo(NetEqDecoder ct,
absl::optional<AudioCodecPairId> codec_pair_id, absl::optional<AudioCodecPairId> codec_pair_id,
AudioDecoderFactory* factory = nullptr); AudioDecoderFactory* factory = nullptr);
DecoderInfo(const SdpAudioFormat& audio_format,
AudioDecoder* ext_dec,
const std::string& codec_name);
DecoderInfo(DecoderInfo&&); DecoderInfo(DecoderInfo&&);
~DecoderInfo(); ~DecoderInfo();
@ -109,9 +106,6 @@ class DecoderDatabase {
AudioDecoderFactory* const factory_; AudioDecoderFactory* const factory_;
mutable std::unique_ptr<AudioDecoder> decoder_; mutable std::unique_ptr<AudioDecoder> decoder_;
// Set iff this is an external decoder.
AudioDecoder* const external_decoder_;
// Set iff this is a comfort noise decoder. // Set iff this is a comfort noise decoder.
struct CngDecoder { struct CngDecoder {
static absl::optional<CngDecoder> Create(const SdpAudioFormat& format); static absl::optional<CngDecoder> Create(const SdpAudioFormat& format);
@ -165,13 +159,6 @@ class DecoderDatabase {
virtual int RegisterPayload(int rtp_payload_type, virtual int RegisterPayload(int rtp_payload_type,
const SdpAudioFormat& audio_format); const SdpAudioFormat& audio_format);
// Registers an externally created AudioDecoder object, and associates it
// as a decoder of type |codec_type| with |rtp_payload_type|.
virtual int InsertExternal(uint8_t rtp_payload_type,
NetEqDecoder codec_type,
const std::string& codec_name,
AudioDecoder* decoder);
// Removes the entry for |rtp_payload_type| from the database. // Removes the entry for |rtp_payload_type| from the database.
// Returns kDecoderNotFound or kOK depending on the outcome of the operation. // Returns kDecoderNotFound or kOK depending on the outcome of the operation.
virtual int Remove(uint8_t rtp_payload_type); virtual int Remove(uint8_t rtp_payload_type);

View File

@ -165,35 +165,6 @@ TEST(DecoderDatabase, TypeTests) {
EXPECT_TRUE(db.IsRed(kPayloadTypeRed)); EXPECT_TRUE(db.IsRed(kPayloadTypeRed));
} }
TEST(DecoderDatabase, ExternalDecoder) {
DecoderDatabase db(new rtc::RefCountedObject<MockAudioDecoderFactory>,
absl::nullopt);
const uint8_t kPayloadType = 0;
const std::string kCodecName = "Robert\'); DROP TABLE Students;";
MockAudioDecoder decoder;
// Load into database.
EXPECT_EQ(DecoderDatabase::kOK,
db.InsertExternal(kPayloadType, NetEqDecoder::kDecoderPCMu,
kCodecName, &decoder));
EXPECT_EQ(1, db.Size());
// Get decoder and make sure we get the external one.
EXPECT_EQ(&decoder, db.GetDecoder(kPayloadType));
// Get the decoder info struct and check it too.
const DecoderDatabase::DecoderInfo* info;
info = db.GetDecoderInfo(kPayloadType);
ASSERT_TRUE(info != NULL);
EXPECT_TRUE(info->IsType("pcmu"));
EXPECT_EQ(info->get_name(), kCodecName);
EXPECT_EQ(kCodecName, info->get_name());
// Expect not to delete the decoder when removing it from the database, since
// it was declared externally.
EXPECT_CALL(decoder, Die()).Times(0);
EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType));
EXPECT_TRUE(db.Empty());
EXPECT_CALL(decoder, Die()).Times(1); // Will be called when |db| is deleted.
}
TEST(DecoderDatabase, CheckPayloadTypes) { TEST(DecoderDatabase, CheckPayloadTypes) {
constexpr int kNumPayloads = 10; constexpr int kNumPayloads = 10;
rtc::scoped_refptr<MockAudioDecoderFactory> factory( rtc::scoped_refptr<MockAudioDecoderFactory> factory(

View File

@ -174,17 +174,6 @@ class NetEq {
const std::string& codec_name, const std::string& codec_name,
uint8_t rtp_payload_type) = 0; uint8_t rtp_payload_type) = 0;
// Provides an externally created decoder object |decoder| to insert in the
// decoder database. The decoder implements a decoder of type |codec| and
// associates it with |rtp_payload_type| and |codec_name|. Returns kOK on
// success, kFail on failure. The name is only used to provide information
// back to the caller about the decoders. Hence, the name is arbitrary, and
// may be empty.
virtual int RegisterExternalDecoder(AudioDecoder* decoder,
NetEqDecoder codec,
const std::string& codec_name,
uint8_t rtp_payload_type) = 0;
// Associates |rtp_payload_type| with the given codec, which NetEq will // Associates |rtp_payload_type| with the given codec, which NetEq will
// instantiate when it needs it. Returns true iff successful. // instantiate when it needs it. Returns true iff successful.
virtual bool RegisterPayloadType(int rtp_payload_type, virtual bool RegisterPayloadType(int rtp_payload_type,

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
#include "api/audio_codecs/audio_decoder.h"
#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
#include "rtc_base/constructormagic.h"
#include "test/gmock.h"
namespace webrtc {
using ::testing::_;
using ::testing::Invoke;
// Implement an external version of the PCM16b decoder.
class ExternalPcm16B : public AudioDecoder {
public:
explicit ExternalPcm16B(int sample_rate_hz)
: sample_rate_hz_(sample_rate_hz) {}
void Reset() override {}
int DecodeInternal(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type) override {
EXPECT_EQ(sample_rate_hz_, sample_rate_hz);
size_t ret = WebRtcPcm16b_Decode(encoded, encoded_len, decoded);
*speech_type = ConvertSpeechType(1);
return static_cast<int>(ret);
}
int SampleRateHz() const override { return sample_rate_hz_; }
size_t Channels() const override { return 1; }
private:
const int sample_rate_hz_;
RTC_DISALLOW_COPY_AND_ASSIGN(ExternalPcm16B);
};
// Create a mock of ExternalPcm16B which delegates all calls to the real object.
// The reason is that we can then track that the correct calls are being made.
class MockExternalPcm16B : public AudioDecoder {
public:
explicit MockExternalPcm16B(int sample_rate_hz) : real_(sample_rate_hz) {
// By default, all calls are delegated to the real object.
ON_CALL(*this, DecodeInternal(_, _, _, _, _))
.WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodeInternal));
ON_CALL(*this, HasDecodePlc())
.WillByDefault(Invoke(&real_, &ExternalPcm16B::HasDecodePlc));
ON_CALL(*this, DecodePlc(_, _))
.WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodePlc));
ON_CALL(*this, Reset())
.WillByDefault(Invoke(&real_, &ExternalPcm16B::Reset));
ON_CALL(*this, IncomingPacket(_, _, _, _, _))
.WillByDefault(Invoke(&real_, &ExternalPcm16B::IncomingPacket));
ON_CALL(*this, ErrorCode())
.WillByDefault(Invoke(&real_, &ExternalPcm16B::ErrorCode));
}
virtual ~MockExternalPcm16B() { Die(); }
MOCK_METHOD0(Die, void());
MOCK_METHOD5(DecodeInternal,
int(const uint8_t* encoded,
size_t encoded_len,
int sample_rate_hz,
int16_t* decoded,
SpeechType* speech_type));
MOCK_CONST_METHOD0(HasDecodePlc, bool());
MOCK_METHOD2(DecodePlc, size_t(size_t num_frames, int16_t* decoded));
MOCK_METHOD0(Reset, void());
MOCK_METHOD5(IncomingPacket,
int(const uint8_t* payload,
size_t payload_len,
uint16_t rtp_sequence_number,
uint32_t rtp_timestamp,
uint32_t arrival_timestamp));
MOCK_METHOD0(ErrorCode, int());
int SampleRateHz() const /* override */ { return real_.SampleRateHz(); }
size_t Channels() const /* override */ { return real_.Channels(); }
private:
ExternalPcm16B real_;
};
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_

View File

@ -248,26 +248,6 @@ int NetEqImpl::RegisterPayloadType(NetEqDecoder codec,
return kOK; return kOK;
} }
int NetEqImpl::RegisterExternalDecoder(AudioDecoder* decoder,
NetEqDecoder codec,
const std::string& codec_name,
uint8_t rtp_payload_type) {
rtc::CritScope lock(&crit_sect_);
RTC_LOG(LS_VERBOSE) << "RegisterExternalDecoder "
<< static_cast<int>(rtp_payload_type) << " "
<< static_cast<int>(codec);
if (!decoder) {
RTC_LOG(LS_ERROR) << "Cannot register external decoder with NULL pointer";
assert(false);
return kFail;
}
if (decoder_database_->InsertExternal(rtp_payload_type, codec, codec_name,
decoder) != DecoderDatabase::kOK) {
return kFail;
}
return kOK;
}
bool NetEqImpl::RegisterPayloadType(int rtp_payload_type, bool NetEqImpl::RegisterPayloadType(int rtp_payload_type,
const SdpAudioFormat& audio_format) { const SdpAudioFormat& audio_format) {
RTC_LOG(LS_VERBOSE) << "NetEqImpl::RegisterPayloadType: payload type " RTC_LOG(LS_VERBOSE) << "NetEqImpl::RegisterPayloadType: payload type "

View File

@ -141,11 +141,6 @@ class NetEqImpl : public webrtc::NetEq {
const std::string& codec_name, const std::string& codec_name,
uint8_t rtp_payload_type) override; uint8_t rtp_payload_type) override;
int RegisterExternalDecoder(AudioDecoder* decoder,
NetEqDecoder codec,
const std::string& codec_name,
uint8_t rtp_payload_type) override;
bool RegisterPayloadType(int rtp_payload_type, bool RegisterPayloadType(int rtp_payload_type,
const SdpAudioFormat& audio_format) override; const SdpAudioFormat& audio_format) override;

View File

@ -10,9 +10,15 @@
#include <memory> #include <memory>
#include "absl/memory/memory.h"
#include "api/audio/audio_frame.h" #include "api/audio/audio_frame.h"
#include "modules/audio_coding/neteq/tools/neteq_external_decoder_test.h" #include "api/audio_codecs/audio_decoder.h"
#include "common_types.h" // NOLINT(build/include)
#include "modules/audio_coding/neteq/include/neteq.h"
#include "modules/audio_coding/neteq/tools/rtp_generator.h" #include "modules/audio_coding/neteq/tools/rtp_generator.h"
#include "rtc_base/refcountedobject.h"
#include "test/audio_decoder_proxy_factory.h"
#include "test/gmock.h" #include "test/gmock.h"
namespace webrtc { namespace webrtc {
@ -117,10 +123,12 @@ class MockAudioDecoder final : public AudioDecoder {
bool fec_enabled_; bool fec_enabled_;
}; };
class NetEqNetworkStatsTest : public NetEqExternalDecoderTest { class NetEqNetworkStatsTest {
public: public:
static const int kPayloadSizeByte = 30; static const int kPayloadSizeByte = 30;
static const int kFrameSizeMs = 20; static const int kFrameSizeMs = 20;
static const uint8_t kPayloadType = 95;
static const int kOutputLengthMs = 10;
enum logic { enum logic {
kIgnore, kIgnore,
@ -145,17 +153,19 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
NetEqNetworkStatistics stats_ref; NetEqNetworkStatistics stats_ref;
}; };
NetEqNetworkStatsTest(NetEqDecoder codec, NetEqNetworkStatsTest(const SdpAudioFormat& format, MockAudioDecoder* decoder)
int sample_rate_hz, : decoder_(decoder),
MockAudioDecoder* decoder) decoder_factory_(
: NetEqExternalDecoderTest(codec, sample_rate_hz, decoder), new rtc::RefCountedObject<AudioDecoderProxyFactory>(decoder)),
external_decoder_(decoder), samples_per_ms_(format.clockrate_hz / 1000),
samples_per_ms_(sample_rate_hz / 1000),
frame_size_samples_(kFrameSizeMs * samples_per_ms_), frame_size_samples_(kFrameSizeMs * samples_per_ms_),
rtp_generator_(new test::RtpGenerator(samples_per_ms_)), rtp_generator_(new RtpGenerator(samples_per_ms_)),
last_lost_time_(0), last_lost_time_(0),
packet_loss_interval_(0xffffffff) { packet_loss_interval_(0xffffffff) {
Init(); NetEq::Config config;
config.sample_rate_hz = format.clockrate_hz;
neteq_ = absl::WrapUnique(NetEq::Create(config, decoder_factory_));
neteq_->RegisterPayloadType(kPayloadType, format);
} }
bool Lost(uint32_t send_time) { bool Lost(uint32_t send_time) {
@ -179,7 +189,7 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
// expects.x = 2, 'x' in current stats should > 'x' in |stats_ref| // expects.x = 2, 'x' in current stats should > 'x' in |stats_ref|
void CheckNetworkStatistics(NetEqNetworkStatsCheck expects) { void CheckNetworkStatistics(NetEqNetworkStatsCheck expects) {
NetEqNetworkStatistics stats; NetEqNetworkStatistics stats;
neteq()->NetworkStatistics(&stats); neteq_->NetworkStatistics(&stats);
#define CHECK_NETEQ_NETWORK_STATS(x) \ #define CHECK_NETEQ_NETWORK_STATS(x) \
switch (expects.x) { \ switch (expects.x) { \
@ -212,7 +222,7 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
#undef CHECK_NETEQ_NETWORK_STATS #undef CHECK_NETEQ_NETWORK_STATS
// Compare with CurrentDelay, which should be identical. // Compare with CurrentDelay, which should be identical.
EXPECT_EQ(stats.current_buffer_size_ms, neteq()->CurrentDelayMs()); EXPECT_EQ(stats.current_buffer_size_ms, neteq_->CurrentDelayMs());
} }
void RunTest(int num_loops, NetEqNetworkStatsCheck expects) { void RunTest(int num_loops, NetEqNetworkStatsCheck expects) {
@ -229,18 +239,26 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
kPayloadType, frame_size_samples_, &rtp_header_); kPayloadType, frame_size_samples_, &rtp_header_);
if (!Lost(next_send_time)) { if (!Lost(next_send_time)) {
static const uint8_t payload[kPayloadSizeByte] = {0}; static const uint8_t payload[kPayloadSizeByte] = {0};
InsertPacket(rtp_header_, payload, next_send_time); ASSERT_EQ(NetEq::kOK,
neteq_->InsertPacket(rtp_header_, payload, next_send_time));
} }
} }
GetOutputAudio(&output_frame_); bool muted = true;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_frame_, &muted));
ASSERT_FALSE(muted);
EXPECT_EQ(decoder_->Channels(), output_frame_.num_channels_);
EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * samples_per_ms_),
output_frame_.samples_per_channel_);
EXPECT_EQ(48000, neteq_->last_output_sample_rate_hz());
time_now += kOutputLengthMs; time_now += kOutputLengthMs;
} }
CheckNetworkStatistics(expects); CheckNetworkStatistics(expects);
neteq()->FlushBuffers(); neteq_->FlushBuffers();
} }
void DecodeFecTest() { void DecodeFecTest() {
external_decoder_->set_fec_enabled(false); decoder_->set_fec_enabled(false);
NetEqNetworkStatsCheck expects = {kIgnore, // current_buffer_size_ms NetEqNetworkStatsCheck expects = {kIgnore, // current_buffer_size_ms
kIgnore, // preferred_buffer_size_ms kIgnore, // preferred_buffer_size_ms
kIgnore, // jitter_peaks_found kIgnore, // jitter_peaks_found
@ -263,7 +281,7 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
RunTest(50, expects); RunTest(50, expects);
// Next we enable FEC. // Next we enable FEC.
external_decoder_->set_fec_enabled(true); decoder_->set_fec_enabled(true);
// If FEC fills in the lost packets, no packet loss will be counted. // If FEC fills in the lost packets, no packet loss will be counted.
expects.stats_ref.packet_loss_rate = 0; expects.stats_ref.packet_loss_rate = 0;
expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0; expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0;
@ -295,10 +313,13 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
} }
private: private:
MockAudioDecoder* external_decoder_; MockAudioDecoder* decoder_;
rtc::scoped_refptr<AudioDecoderProxyFactory> decoder_factory_;
std::unique_ptr<NetEq> neteq_;
const int samples_per_ms_; const int samples_per_ms_;
const size_t frame_size_samples_; const size_t frame_size_samples_;
std::unique_ptr<test::RtpGenerator> rtp_generator_; std::unique_ptr<RtpGenerator> rtp_generator_;
RTPHeader rtp_header_; RTPHeader rtp_header_;
uint32_t last_lost_time_; uint32_t last_lost_time_;
uint32_t packet_loss_interval_; uint32_t packet_loss_interval_;
@ -307,21 +328,21 @@ class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
TEST(NetEqNetworkStatsTest, DecodeFec) { TEST(NetEqNetworkStatsTest, DecodeFec) {
MockAudioDecoder decoder(48000, 1); MockAudioDecoder decoder(48000, 1);
NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder); NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
test.DecodeFecTest(); test.DecodeFecTest();
EXPECT_CALL(decoder, Die()).Times(1); EXPECT_CALL(decoder, Die()).Times(1);
} }
TEST(NetEqNetworkStatsTest, StereoDecodeFec) { TEST(NetEqNetworkStatsTest, StereoDecodeFec) {
MockAudioDecoder decoder(48000, 2); MockAudioDecoder decoder(48000, 2);
NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder); NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
test.DecodeFecTest(); test.DecodeFecTest();
EXPECT_CALL(decoder, Die()).Times(1); EXPECT_CALL(decoder, Die()).Times(1);
} }
TEST(NetEqNetworkStatsTest, NoiseExpansionTest) { TEST(NetEqNetworkStatsTest, NoiseExpansionTest) {
MockAudioDecoder decoder(48000, 1); MockAudioDecoder decoder(48000, 1);
NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder); NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
test.NoiseExpansionTest(); test.NoiseExpansionTest();
EXPECT_CALL(decoder, Die()).Times(1); EXPECT_CALL(decoder, Die()).Times(1);
} }

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
#include "api/audio/audio_frame.h"
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "rtc_base/format_macros.h"
#include "test/gtest.h"
namespace webrtc {
namespace test {
NetEqExternalDecoderTest::NetEqExternalDecoderTest(NetEqDecoder codec,
int sample_rate_hz,
AudioDecoder* decoder)
: codec_(codec),
decoder_(decoder),
sample_rate_hz_(sample_rate_hz),
channels_(decoder_->Channels()) {
NetEq::Config config;
config.sample_rate_hz = sample_rate_hz_;
neteq_.reset(NetEq::Create(config, CreateBuiltinAudioDecoderFactory()));
}
void NetEqExternalDecoderTest::Init() {
ASSERT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(decoder_, codec_, name_,
kPayloadType));
}
void NetEqExternalDecoderTest::InsertPacket(
RTPHeader rtp_header,
rtc::ArrayView<const uint8_t> payload,
uint32_t receive_timestamp) {
ASSERT_EQ(NetEq::kOK,
neteq_->InsertPacket(rtp_header, payload, receive_timestamp));
}
void NetEqExternalDecoderTest::GetOutputAudio(AudioFrame* output) {
// Get audio from regular instance.
bool muted;
EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(output, &muted));
ASSERT_FALSE(muted);
EXPECT_EQ(channels_, output->num_channels_);
EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * sample_rate_hz_ / 1000),
output->samples_per_channel_);
EXPECT_EQ(sample_rate_hz_, neteq_->last_output_sample_rate_hz());
}
} // namespace test
} // namespace webrtc

View File

@ -1,63 +0,0 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
#define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
#include <memory>
#include <string>
#include "api/audio_codecs/audio_decoder.h"
#include "modules/audio_coding/neteq/include/neteq.h"
namespace webrtc {
namespace test {
// This test class provides a way run NetEQ with an external decoder.
class NetEqExternalDecoderTest {
protected:
static const uint8_t kPayloadType = 95;
static const int kOutputLengthMs = 10;
// The external decoder |decoder| is suppose to be of type |codec|.
NetEqExternalDecoderTest(NetEqDecoder codec,
int sample_rate_hz,
AudioDecoder* decoder);
virtual ~NetEqExternalDecoderTest() {}
// In Init(), we register the external decoder.
void Init();
// Inserts a new packet with |rtp_header| and |payload| of
// |payload_size_bytes| bytes. The |receive_timestamp| is an indication
// of the time when the packet was received, and should be measured with
// the same tick rate as the RTP timestamp of the current payload.
virtual void InsertPacket(RTPHeader rtp_header,
rtc::ArrayView<const uint8_t> payload,
uint32_t receive_timestamp);
// Get 10 ms of audio data.
void GetOutputAudio(AudioFrame* output);
NetEq* neteq() { return neteq_.get(); }
private:
NetEqDecoder codec_;
std::string name_ = "dummy name";
AudioDecoder* decoder_;
int sample_rate_hz_;
size_t channels_;
std::unique_ptr<NetEq> neteq_;
};
} // namespace test
} // namespace webrtc
#endif // MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_