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:
@ -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",
|
||||||
|
|||||||
@ -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|.
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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_
|
|
||||||
@ -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 "
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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_
|
|
||||||
Reference in New Issue
Block a user