diff options
Diffstat (limited to 'webrtc/modules/audio_coding/neteq')
57 files changed, 892 insertions, 666 deletions
diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc index a9ea44d6a6..d800cc7dbe 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.cc @@ -13,13 +13,13 @@ #include <assert.h> #include "webrtc/base/checks.h" -#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" -#include "webrtc/modules/audio_coding/codecs/g711/include/audio_decoder_pcm.h" +#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" +#include "webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h" #ifdef WEBRTC_CODEC_G722 -#include "webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h" +#include "webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h" #endif #ifdef WEBRTC_CODEC_ILBC -#include "webrtc/modules/audio_coding/codecs/ilbc/include/audio_decoder_ilbc.h" +#include "webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h" #endif #ifdef WEBRTC_CODEC_ISACFX #include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h" @@ -30,9 +30,9 @@ #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h" #endif #ifdef WEBRTC_CODEC_OPUS -#include "webrtc/modules/audio_coding/codecs/opus/include/audio_decoder_opus.h" +#include "webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h" #endif -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/audio_decoder_pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h index 3229033d92..bc8bdd9626 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_impl.h @@ -16,11 +16,11 @@ #include "webrtc/engine_configurations.h" #include "webrtc/base/constructormagic.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" -#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" +#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" #ifdef WEBRTC_CODEC_G722 -#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h" +#include "webrtc/modules/audio_coding/codecs/g722/g722_interface.h" #endif -#include "webrtc/modules/audio_coding/main/acm2/rent_a_codec.h" +#include "webrtc/modules/audio_coding/acm2/rent_a_codec.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc index 8f82fb11a4..599929e78d 100644 --- a/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/audio_decoder_unittest.cc @@ -18,20 +18,20 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/audio_coding/codecs/g711/include/audio_decoder_pcm.h" -#include "webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h" -#include "webrtc/modules/audio_coding/codecs/g722/include/audio_decoder_g722.h" -#include "webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h" -#include "webrtc/modules/audio_coding/codecs/ilbc/include/audio_decoder_ilbc.h" -#include "webrtc/modules/audio_coding/codecs/ilbc/include/audio_encoder_ilbc.h" +#include "webrtc/modules/audio_coding/codecs/g711/audio_decoder_pcm.h" +#include "webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h" +#include "webrtc/modules/audio_coding/codecs/g722/audio_decoder_g722.h" +#include "webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.h" +#include "webrtc/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h" +#include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h" #include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h" #include "webrtc/modules/audio_coding/codecs/isac/fix/include/audio_encoder_isacfix.h" #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h" #include "webrtc/modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h" -#include "webrtc/modules/audio_coding/codecs/opus/include/audio_decoder_opus.h" -#include "webrtc/modules/audio_coding/codecs/opus/include/audio_encoder_opus.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/audio_decoder_pcm16b.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/opus/audio_decoder_opus.h" +#include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h" #include "webrtc/modules/audio_coding/neteq/tools/resample_input_audio_file.h" #include "webrtc/system_wrappers/include/data_log.h" #include "webrtc/test/testsupport/fileutils.h" @@ -158,7 +158,10 @@ class AudioDecoderTest : public ::testing::Test { interleaved_input.get()); encoded_info_ = audio_encoder_->Encode( - 0, interleaved_input.get(), audio_encoder_->SampleRateHz() / 100, + 0, rtc::ArrayView<const int16_t>(interleaved_input.get(), + audio_encoder_->NumChannels() * + audio_encoder_->SampleRateHz() / + 100), data_length_ * 2, output); } EXPECT_EQ(payload_type_, encoded_info_.payload_type); @@ -563,18 +566,14 @@ TEST_F(AudioDecoderIsacSwbTest, SetTargetBitrate) { TestSetAndGetTargetBitratesWithFixedCodec(audio_encoder_.get(), 32000); } -// Fails Android ARM64. https://code.google.com/p/webrtc/issues/detail?id=4198 -#if defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM64) -#define MAYBE_EncodeDecode DISABLED_EncodeDecode -#else -#define MAYBE_EncodeDecode EncodeDecode -#endif -TEST_F(AudioDecoderIsacFixTest, MAYBE_EncodeDecode) { +TEST_F(AudioDecoderIsacFixTest, EncodeDecode) { int tolerance = 11034; double mse = 3.46e6; int delay = 54; // Delay from input to output. -#ifdef WEBRTC_ANDROID +#if defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM) static const int kEncodedBytes = 685; +#elif defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM64) + static const int kEncodedBytes = 673; #else static const int kEncodedBytes = 671; #endif diff --git a/webrtc/modules/audio_coding/neteq/comfort_noise.cc b/webrtc/modules/audio_coding/neteq/comfort_noise.cc index 3fe6607778..a5b08469be 100644 --- a/webrtc/modules/audio_coding/neteq/comfort_noise.cc +++ b/webrtc/modules/audio_coding/neteq/comfort_noise.cc @@ -14,7 +14,7 @@ #include "webrtc/base/logging.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" -#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" +#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" #include "webrtc/modules/audio_coding/neteq/decoder_database.h" #include "webrtc/modules/audio_coding/neteq/dsp_helper.h" #include "webrtc/modules/audio_coding/neteq/sync_buffer.h" diff --git a/webrtc/modules/audio_coding/neteq/decision_logic.cc b/webrtc/modules/audio_coding/neteq/decision_logic.cc index 14e0426d7d..39bb4662c7 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic.cc +++ b/webrtc/modules/audio_coding/neteq/decision_logic.cc @@ -128,9 +128,6 @@ Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer, const size_t cur_size_samples = samples_left + packet_buffer_.NumSamplesInBuffer(decoder_database_, decoder_frame_length); - LOG(LS_VERBOSE) << "Buffers: " << packet_buffer_.NumPacketsInBuffer() << - " packets * " << decoder_frame_length << " samples/packet + " << - samples_left << " samples in sync buffer = " << cur_size_samples; prev_time_scale_ = prev_time_scale_ && (prev_mode == kModeAccelerateSuccess || diff --git a/webrtc/modules/audio_coding/neteq/decision_logic_normal.cc b/webrtc/modules/audio_coding/neteq/decision_logic_normal.cc index d3f6fa6dd4..0252d1cdfa 100644 --- a/webrtc/modules/audio_coding/neteq/decision_logic_normal.cc +++ b/webrtc/modules/audio_coding/neteq/decision_logic_normal.cc @@ -20,7 +20,7 @@ #include "webrtc/modules/audio_coding/neteq/expand.h" #include "webrtc/modules/audio_coding/neteq/packet_buffer.h" #include "webrtc/modules/audio_coding/neteq/sync_buffer.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.cc b/webrtc/modules/audio_coding/neteq/decoder_database.cc index 41803f754a..92d4bab1e4 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database.cc +++ b/webrtc/modules/audio_coding/neteq/decoder_database.cc @@ -13,6 +13,7 @@ #include <assert.h> #include <utility> // pair +#include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" @@ -38,17 +39,17 @@ void DecoderDatabase::Reset() { } int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type, - NetEqDecoder codec_type) { + NetEqDecoder codec_type, + const std::string& name) { if (rtp_payload_type > 0x7F) { return kInvalidRtpPayloadType; } if (!CodecSupported(codec_type)) { return kCodecNotSupported; } - int fs_hz = CodecSampleRateHz(codec_type); - std::pair<DecoderMap::iterator, bool> ret; - DecoderInfo info(codec_type, fs_hz, NULL, false); - ret = decoders_.insert(std::make_pair(rtp_payload_type, info)); + const int fs_hz = CodecSampleRateHz(codec_type); + DecoderInfo info(codec_type, name, fs_hz, NULL, false); + auto ret = decoders_.insert(std::make_pair(rtp_payload_type, info)); if (ret.second == false) { // Database already contains a decoder with type |rtp_payload_type|. return kDecoderExists; @@ -58,6 +59,7 @@ int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type, int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type, NetEqDecoder codec_type, + const std::string& codec_name, int fs_hz, AudioDecoder* decoder) { if (rtp_payload_type > 0x7F) { @@ -73,7 +75,7 @@ int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type, return kInvalidPointer; } std::pair<DecoderMap::iterator, bool> ret; - DecoderInfo info(codec_type, fs_hz, decoder, true); + DecoderInfo info(codec_type, codec_name, fs_hz, decoder, true); ret = decoders_.insert(std::make_pair(rtp_payload_type, info)); if (ret.second == false) { // Database already contains a decoder with type |rtp_payload_type|. diff --git a/webrtc/modules/audio_coding/neteq/decoder_database.h b/webrtc/modules/audio_coding/neteq/decoder_database.h index ea70997c14..f34904fda8 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database.h +++ b/webrtc/modules/audio_coding/neteq/decoder_database.h @@ -12,8 +12,10 @@ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_DECODER_DATABASE_H_ #include <map> +#include <string> #include "webrtc/base/constructormagic.h" +#include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" // NULL #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h" #include "webrtc/modules/audio_coding/neteq/packet.h" @@ -35,25 +37,28 @@ class DecoderDatabase { // Struct used to store decoder info in the database. struct DecoderInfo { - // Constructors. - DecoderInfo() - : codec_type(NetEqDecoder::kDecoderArbitrary), - fs_hz(8000), - decoder(NULL), - external(false) {} + DecoderInfo() = default; DecoderInfo(NetEqDecoder ct, int fs, AudioDecoder* dec, bool ext) + : DecoderInfo(ct, "", fs, dec, ext) {} + DecoderInfo(NetEqDecoder ct, + const std::string& nm, + int fs, + AudioDecoder* dec, + bool ext) : codec_type(ct), + name(nm), fs_hz(fs), + rtp_sample_rate_hz(fs), decoder(dec), - external(ext) { - } - // Destructor. (Defined in decoder_database.cc.) + external(ext) {} ~DecoderInfo(); - NetEqDecoder codec_type; - int fs_hz; - AudioDecoder* decoder; - bool external; + NetEqDecoder codec_type = NetEqDecoder::kDecoderArbitrary; + std::string name; + int fs_hz = 8000; + int rtp_sample_rate_hz = 8000; + AudioDecoder* decoder = nullptr; + bool external = false; }; // Maximum value for 8 bits, and an invalid RTP payload type (since it is @@ -75,16 +80,21 @@ class DecoderDatabase { // using InsertExternal(). virtual void Reset(); - // Registers |rtp_payload_type| as a decoder of type |codec_type|. Returns - // kOK on success; otherwise an error code. + // Registers |rtp_payload_type| as a decoder of type |codec_type|. The |name| + // is only used to populate the name field in the DecoderInfo struct in the + // database, and can be arbitrary (including empty). Returns kOK on success; + // otherwise an error code. virtual int RegisterPayload(uint8_t rtp_payload_type, - NetEqDecoder codec_type); + NetEqDecoder codec_type, + const std::string& name); // 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, - int fs_hz, AudioDecoder* decoder); + const std::string& codec_name, + int fs_hz, + AudioDecoder* decoder); // Removes the entry for |rtp_payload_type| from the database. // Returns kDecoderNotFound or kOK depending on the outcome of the operation. diff --git a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc index e85d8d32fb..85aaef1143 100644 --- a/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/decoder_database_unittest.cc @@ -19,7 +19,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h" -#include "webrtc/test/testsupport/gtest_disable.h" namespace webrtc { @@ -32,8 +31,10 @@ TEST(DecoderDatabase, CreateAndDestroy) { TEST(DecoderDatabase, InsertAndRemove) { DecoderDatabase db; const uint8_t kPayloadType = 0; - EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu)); + const std::string kCodecName = "Robert\'); DROP TABLE Students;"; + EXPECT_EQ( + DecoderDatabase::kOK, + db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName)); EXPECT_EQ(1, db.Size()); EXPECT_FALSE(db.Empty()); EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType)); @@ -44,14 +45,17 @@ TEST(DecoderDatabase, InsertAndRemove) { TEST(DecoderDatabase, GetDecoderInfo) { DecoderDatabase db; const uint8_t kPayloadType = 0; - EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu)); + const std::string kCodecName = "Robert\'); DROP TABLE Students;"; + EXPECT_EQ( + DecoderDatabase::kOK, + db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName)); const DecoderDatabase::DecoderInfo* info; info = db.GetDecoderInfo(kPayloadType); ASSERT_TRUE(info != NULL); EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type); EXPECT_EQ(NULL, info->decoder); EXPECT_EQ(8000, info->fs_hz); + EXPECT_EQ(kCodecName, info->name); EXPECT_FALSE(info->external); info = db.GetDecoderInfo(kPayloadType + 1); // Other payload type. EXPECT_TRUE(info == NULL); // Should not be found. @@ -60,8 +64,10 @@ TEST(DecoderDatabase, GetDecoderInfo) { TEST(DecoderDatabase, GetRtpPayloadType) { DecoderDatabase db; const uint8_t kPayloadType = 0; - EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu)); + const std::string kCodecName = "Robert\'); DROP TABLE Students;"; + EXPECT_EQ( + DecoderDatabase::kOK, + db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName)); EXPECT_EQ(kPayloadType, db.GetRtpPayloadType(NetEqDecoder::kDecoderPCMu)); const uint8_t expected_value = DecoderDatabase::kRtpPayloadTypeError; EXPECT_EQ(expected_value, @@ -72,8 +78,10 @@ TEST(DecoderDatabase, GetRtpPayloadType) { TEST(DecoderDatabase, GetDecoder) { DecoderDatabase db; const uint8_t kPayloadType = 0; + const std::string kCodecName = "Robert\'); DROP TABLE Students;"; EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCM16B)); + db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCM16B, + kCodecName)); AudioDecoder* dec = db.GetDecoder(kPayloadType); ASSERT_TRUE(dec != NULL); } @@ -86,14 +94,18 @@ TEST(DecoderDatabase, TypeTests) { const uint8_t kPayloadTypeRed = 101; const uint8_t kPayloadNotUsed = 102; // Load into database. + EXPECT_EQ( + DecoderDatabase::kOK, + db.RegisterPayload(kPayloadTypePcmU, NetEqDecoder::kDecoderPCMu, "pcmu")); EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadTypePcmU, NetEqDecoder::kDecoderPCMu)); - EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadTypeCng, NetEqDecoder::kDecoderCNGnb)); - EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadTypeDtmf, NetEqDecoder::kDecoderAVT)); - EXPECT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(kPayloadTypeRed, NetEqDecoder::kDecoderRED)); + db.RegisterPayload(kPayloadTypeCng, NetEqDecoder::kDecoderCNGnb, + "cng-nb")); + EXPECT_EQ( + DecoderDatabase::kOK, + db.RegisterPayload(kPayloadTypeDtmf, NetEqDecoder::kDecoderAVT, "avt")); + EXPECT_EQ( + DecoderDatabase::kOK, + db.RegisterPayload(kPayloadTypeRed, NetEqDecoder::kDecoderRED, "red")); EXPECT_EQ(4, db.Size()); // Test. EXPECT_FALSE(db.IsComfortNoise(kPayloadNotUsed)); @@ -112,11 +124,12 @@ TEST(DecoderDatabase, TypeTests) { TEST(DecoderDatabase, ExternalDecoder) { DecoderDatabase db; 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, 8000, - &decoder)); + db.InsertExternal(kPayloadType, NetEqDecoder::kDecoderPCMu, + kCodecName, 8000, &decoder)); EXPECT_EQ(1, db.Size()); // Get decoder and make sure we get the external one. EXPECT_EQ(&decoder, db.GetDecoder(kPayloadType)); @@ -125,6 +138,7 @@ TEST(DecoderDatabase, ExternalDecoder) { info = db.GetDecoderInfo(kPayloadType); ASSERT_TRUE(info != NULL); EXPECT_EQ(NetEqDecoder::kDecoderPCMu, info->codec_type); + EXPECT_EQ(kCodecName, info->name); EXPECT_EQ(&decoder, info->decoder); EXPECT_EQ(8000, info->fs_hz); EXPECT_TRUE(info->external); @@ -146,7 +160,7 @@ TEST(DecoderDatabase, CheckPayloadTypes) { for (uint8_t payload_type = 0; payload_type < kNumPayloads; ++payload_type) { EXPECT_EQ( DecoderDatabase::kOK, - db.RegisterPayload(payload_type, NetEqDecoder::kDecoderArbitrary)); + db.RegisterPayload(payload_type, NetEqDecoder::kDecoderArbitrary, "")); } PacketList packet_list; for (int i = 0; i < kNumPayloads + 1; ++i) { @@ -185,11 +199,11 @@ TEST(DecoderDatabase, IF_ISAC(ActiveDecoders)) { DecoderDatabase db; // Load payload types. ASSERT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu)); + db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu, "pcmu")); ASSERT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(103, NetEqDecoder::kDecoderISAC)); + db.RegisterPayload(103, NetEqDecoder::kDecoderISAC, "isac")); ASSERT_EQ(DecoderDatabase::kOK, - db.RegisterPayload(13, NetEqDecoder::kDecoderCNGnb)); + db.RegisterPayload(13, NetEqDecoder::kDecoderCNGnb, "cng-nb")); // Verify that no decoders are active from the start. EXPECT_EQ(NULL, db.GetActiveDecoder()); EXPECT_EQ(NULL, db.GetActiveCngDecoder()); diff --git a/webrtc/modules/audio_coding/neteq/delay_manager.cc b/webrtc/modules/audio_coding/neteq/delay_manager.cc index 5140c0620f..806d02b8de 100644 --- a/webrtc/modules/audio_coding/neteq/delay_manager.cc +++ b/webrtc/modules/audio_coding/neteq/delay_manager.cc @@ -17,7 +17,7 @@ #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" #include "webrtc/modules/audio_coding/neteq/delay_peak_detector.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/logging.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/expand.cc b/webrtc/modules/audio_coding/neteq/expand.cc index 2aa9fb0a8d..ef7af46597 100644 --- a/webrtc/modules/audio_coding/neteq/expand.cc +++ b/webrtc/modules/audio_coding/neteq/expand.cc @@ -519,7 +519,7 @@ void Expand::AnalyzeSignal(int16_t* random_vector) { energy2 = WebRtcSpl_DotProductWithScale(vector2, vector2, expansion_length, correlation_scale); // Confirm that amplitude ratio sqrt(energy1 / energy2) is within 0.5 - 2.0, - // i.e., energy1 / energy1 is within 0.25 - 4. + // i.e., energy1 / energy2 is within 0.25 - 4. int16_t amplitude_ratio; if ((energy1 / 4 < energy2) && (energy1 > energy2 / 4)) { // Energy constraint fulfilled. Use both vectors and scale them diff --git a/webrtc/modules/audio_coding/neteq/include/neteq.h b/webrtc/modules/audio_coding/neteq/include/neteq.h index 205a0dfe80..1322223970 100644 --- a/webrtc/modules/audio_coding/neteq/include/neteq.h +++ b/webrtc/modules/audio_coding/neteq/include/neteq.h @@ -81,6 +81,7 @@ class NetEq { Config() : sample_rate_hz(16000), enable_audio_classifier(false), + enable_post_decode_vad(false), max_packets_in_buffer(50), // |max_delay_ms| has the same effect as calling SetMaximumDelay(). max_delay_ms(2000), @@ -92,6 +93,7 @@ class NetEq { int sample_rate_hz; // Initial value. Will change with input data. bool enable_audio_classifier; + bool enable_post_decode_vad; size_t max_packets_in_buffer; int max_delay_ms; BackgroundNoiseMode background_noise_mode; @@ -145,8 +147,7 @@ class NetEq { // the same tick rate as the RTP timestamp of the current payload. // Returns 0 on success, -1 on failure. virtual int InsertPacket(const WebRtcRTPHeader& rtp_header, - const uint8_t* payload, - size_t length_bytes, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp) = 0; // Inserts a sync-packet into packet queue. Sync-packets are decoded to @@ -170,20 +171,27 @@ class NetEq { // The speech type is written to |type|, if |type| is not NULL. // Returns kOK on success, or kFail in case of an error. virtual int GetAudio(size_t max_length, int16_t* output_audio, - size_t* samples_per_channel, int* num_channels, + size_t* samples_per_channel, size_t* num_channels, NetEqOutputType* type) = 0; - // Associates |rtp_payload_type| with |codec| and stores the information in - // the codec database. Returns 0 on success, -1 on failure. + // Associates |rtp_payload_type| with |codec| and |codec_name|, and stores the + // information in the codec database. Returns 0 on success, -1 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 RegisterPayloadType(NetEqDecoder codec, + const std::string& codec_name, 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|. The decoder will produce samples - // at the rate |sample_rate_hz|. Returns kOK on success, kFail on failure. + // associates it with |rtp_payload_type| and |codec_name|. The decoder will + // produce samples at the rate |sample_rate_hz|. 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, int sample_rate_hz) = 0; @@ -250,6 +258,11 @@ class NetEq { // Returns true if the RTP timestamp is valid, otherwise false. virtual bool GetPlayoutTimestamp(uint32_t* timestamp) = 0; + // Returns the sample rate in Hz of the audio produced in the last GetAudio + // call. If GetAudio has not been called yet, the configured sample rate + // (Config::sample_rate_hz) is returned. + virtual int last_output_sample_rate_hz() const = 0; + // Not implemented. virtual int SetTargetNumberOfChannels() = 0; diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h b/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h index 8debcbbb1e..c1cc09cb5e 100644 --- a/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h +++ b/webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h @@ -22,9 +22,8 @@ class MockAudioDecoder : public AudioDecoder { MockAudioDecoder() {} virtual ~MockAudioDecoder() { Die(); } MOCK_METHOD0(Die, void()); - MOCK_METHOD6( - Decode, - int(const uint8_t*, size_t, int, size_t, int16_t*, SpeechType*)); + MOCK_METHOD5(DecodeInternal, + int(const uint8_t*, size_t, int, int16_t*, SpeechType*)); MOCK_CONST_METHOD0(HasDecodePlc, bool()); MOCK_METHOD2(DecodePlc, size_t(size_t, int16_t*)); MOCK_METHOD0(Reset, void()); diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h index d127c5d810..1b4a3c9da5 100644 --- a/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h +++ b/webrtc/modules/audio_coding/neteq/mock/mock_decoder_database.h @@ -11,6 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DECODER_DATABASE_H_ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DECODER_DATABASE_H_ +#include <string> + #include "webrtc/modules/audio_coding/neteq/decoder_database.h" #include "testing/gmock/include/gmock/gmock.h" @@ -27,10 +29,12 @@ class MockDecoderDatabase : public DecoderDatabase { int()); MOCK_METHOD0(Reset, void()); - MOCK_METHOD2(RegisterPayload, - int(uint8_t rtp_payload_type, NetEqDecoder codec_type)); - MOCK_METHOD4(InsertExternal, - int(uint8_t rtp_payload_type, NetEqDecoder codec_type, int fs_hz, + MOCK_METHOD3(RegisterPayload, + int(uint8_t rtp_payload_type, NetEqDecoder codec_type, + const std::string& name)); + MOCK_METHOD5(InsertExternal, + int(uint8_t rtp_payload_type, NetEqDecoder codec_type, + const std::string& codec_name, int fs_hz, AudioDecoder* decoder)); MOCK_METHOD1(Remove, int(uint8_t rtp_payload_type)); diff --git a/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h b/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h index 8cf89c083d..42c17ae054 100644 --- a/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h +++ b/webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h @@ -15,7 +15,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -30,7 +30,6 @@ class ExternalPcm16B : public AudioDecoder { ExternalPcm16B() {} void Reset() override {} - protected: int DecodeInternal(const uint8_t* encoded, size_t encoded_len, int sample_rate_hz, @@ -52,8 +51,8 @@ class MockExternalPcm16B : public ExternalPcm16B { public: MockExternalPcm16B() { // By default, all calls are delegated to the real object. - ON_CALL(*this, Decode(_, _, _, _, _, _)) - .WillByDefault(Invoke(&real_, &ExternalPcm16B::Decode)); + ON_CALL(*this, DecodeInternal(_, _, _, _, _)) + .WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodeInternal)); ON_CALL(*this, HasDecodePlc()) .WillByDefault(Invoke(&real_, &ExternalPcm16B::HasDecodePlc)); ON_CALL(*this, DecodePlc(_, _)) @@ -68,11 +67,10 @@ class MockExternalPcm16B : public ExternalPcm16B { virtual ~MockExternalPcm16B() { Die(); } MOCK_METHOD0(Die, void()); - MOCK_METHOD6(Decode, + MOCK_METHOD5(DecodeInternal, int(const uint8_t* encoded, size_t encoded_len, int sample_rate_hz, - size_t max_decoded_bytes, int16_t* decoded, SpeechType* speech_type)); MOCK_CONST_METHOD0(HasDecodePlc, diff --git a/webrtc/modules/audio_coding/neteq/nack.cc b/webrtc/modules/audio_coding/neteq/nack.cc index fd3d762605..011914b3d9 100644 --- a/webrtc/modules/audio_coding/neteq/nack.cc +++ b/webrtc/modules/audio_coding/neteq/nack.cc @@ -15,7 +15,7 @@ #include <algorithm> // For std::max. #include "webrtc/base/checks.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/logging.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/nack.h b/webrtc/modules/audio_coding/neteq/nack.h index 116b7e2192..17fef46464 100644 --- a/webrtc/modules/audio_coding/neteq/nack.h +++ b/webrtc/modules/audio_coding/neteq/nack.h @@ -15,7 +15,7 @@ #include <map> #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/audio_coding/main/include/audio_coding_module_typedefs.h" +#include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h" #include "webrtc/test/testsupport/gtest_prod_util.h" // diff --git a/webrtc/modules/audio_coding/neteq/nack_unittest.cc b/webrtc/modules/audio_coding/neteq/nack_unittest.cc index 853af94ede..53b19dc50f 100644 --- a/webrtc/modules/audio_coding/neteq/nack_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/nack_unittest.cc @@ -17,7 +17,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/typedefs.h" -#include "webrtc/modules/audio_coding/main/include/audio_coding_module_typedefs.h" +#include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h" namespace webrtc { namespace { diff --git a/webrtc/modules/audio_coding/neteq/neteq.cc b/webrtc/modules/audio_coding/neteq/neteq.cc index ca51c9602d..c31dbdc1a3 100644 --- a/webrtc/modules/audio_coding/neteq/neteq.cc +++ b/webrtc/modules/audio_coding/neteq/neteq.cc @@ -32,6 +32,8 @@ std::string NetEq::Config::ToString() const { std::stringstream ss; ss << "sample_rate_hz=" << sample_rate_hz << ", enable_audio_classifier=" << (enable_audio_classifier ? "true" : "false") + << ", enable_post_decode_vad=" + << (enable_post_decode_vad ? "true" : "false") << ", max_packets_in_buffer=" << max_packets_in_buffer << ", background_noise_mode=" << background_noise_mode << ", playout_mode=" << playout_mode diff --git a/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc index 09eb5614fe..c03fbb7347 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc @@ -98,14 +98,16 @@ class NetEqExternalDecoderUnitTest : public test::NetEqExternalDecoderTest { next_arrival_time = GetArrivalTime(next_send_time); } while (Lost()); // If lost, immediately read the next packet. - EXPECT_CALL(*external_decoder_, - Decode(_, payload_size_bytes_, 1000 * samples_per_ms_, _, _, _)) + EXPECT_CALL( + *external_decoder_, + DecodeInternal(_, payload_size_bytes_, 1000 * samples_per_ms_, _, _)) .Times(NumExpectedDecodeCalls(num_loops)); uint32_t time_now = 0; for (int k = 0; k < num_loops; ++k) { while (time_now >= next_arrival_time) { - InsertPacket(rtp_header_, encoded_, payload_size_bytes_, + InsertPacket(rtp_header_, rtc::ArrayView<const uint8_t>( + encoded_, payload_size_bytes_), next_arrival_time); // Get next input packet. do { @@ -124,17 +126,14 @@ class NetEqExternalDecoderUnitTest : public test::NetEqExternalDecoderTest { } } - void InsertPacket(WebRtcRTPHeader rtp_header, const uint8_t* payload, - size_t payload_size_bytes, + void InsertPacket(WebRtcRTPHeader rtp_header, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp) override { - EXPECT_CALL(*external_decoder_, - IncomingPacket(_, - payload_size_bytes, - rtp_header.header.sequenceNumber, - rtp_header.header.timestamp, - receive_timestamp)); + EXPECT_CALL( + *external_decoder_, + IncomingPacket(_, payload.size(), rtp_header.header.sequenceNumber, + rtp_header.header.timestamp, receive_timestamp)); NetEqExternalDecoderTest::InsertPacket(rtp_header, payload, - payload_size_bytes, receive_timestamp); } @@ -181,15 +180,15 @@ class NetEqExternalVsInternalDecoderTest : public NetEqExternalDecoderUnitTest, } void SetUp() override { - ASSERT_EQ(NetEq::kOK, - neteq_internal_->RegisterPayloadType( - NetEqDecoder::kDecoderPCM16Bswb32kHz, kPayloadType)); + ASSERT_EQ(NetEq::kOK, neteq_internal_->RegisterPayloadType( + NetEqDecoder::kDecoderPCM16Bswb32kHz, + "pcm16-swb32", kPayloadType)); } void GetAndVerifyOutput() override { NetEqOutputType output_type; size_t samples_per_channel; - int num_channels; + size_t num_channels; // Get audio from internal decoder instance. EXPECT_EQ(NetEq::kOK, neteq_internal_->GetAudio(kMaxBlockSize, @@ -197,7 +196,7 @@ class NetEqExternalVsInternalDecoderTest : public NetEqExternalDecoderUnitTest, &samples_per_channel, &num_channels, &output_type)); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * sample_rate_hz_ / 1000), samples_per_channel); @@ -210,18 +209,15 @@ class NetEqExternalVsInternalDecoderTest : public NetEqExternalDecoderUnitTest, } } - void InsertPacket(WebRtcRTPHeader rtp_header, const uint8_t* payload, - size_t payload_size_bytes, + void InsertPacket(WebRtcRTPHeader rtp_header, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp) override { // Insert packet in internal decoder. - ASSERT_EQ( - NetEq::kOK, - neteq_internal_->InsertPacket( - rtp_header, payload, payload_size_bytes, receive_timestamp)); + ASSERT_EQ(NetEq::kOK, neteq_internal_->InsertPacket(rtp_header, payload, + receive_timestamp)); // Insert packet in external decoder instance. NetEqExternalDecoderUnitTest::InsertPacket(rtp_header, payload, - payload_size_bytes, receive_timestamp); } diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index 92ce41e2ea..6c07da46f0 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -18,6 +18,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/base/safe_conversions.h" +#include "webrtc/base/trace_event.h" #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" #include "webrtc/modules/audio_coding/neteq/accelerate.h" @@ -42,7 +43,7 @@ #include "webrtc/modules/audio_coding/neteq/preemptive_expand.h" #include "webrtc/modules/audio_coding/neteq/sync_buffer.h" #include "webrtc/modules/audio_coding/neteq/timestamp_scaler.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" // Modify the code to obtain backwards bit-exactness. Once bit-exactness is no @@ -106,28 +107,28 @@ NetEqImpl::NetEqImpl(const NetEq::Config& config, } fs_hz_ = fs; fs_mult_ = fs / 8000; + last_output_sample_rate_hz_ = fs; output_size_samples_ = static_cast<size_t>(kOutputSizeMs * 8 * fs_mult_); decoder_frame_length_ = 3 * output_size_samples_; WebRtcSpl_Init(); if (create_components) { SetSampleRateAndChannels(fs, 1); // Default is 1 channel. } + RTC_DCHECK(!vad_->enabled()); + if (config.enable_post_decode_vad) { + vad_->Enable(); + } } NetEqImpl::~NetEqImpl() = default; int NetEqImpl::InsertPacket(const WebRtcRTPHeader& rtp_header, - const uint8_t* payload, - size_t length_bytes, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp) { + TRACE_EVENT0("webrtc", "NetEqImpl::InsertPacket"); CriticalSectionScoped lock(crit_sect_.get()); - LOG(LS_VERBOSE) << "InsertPacket: ts=" << rtp_header.header.timestamp << - ", sn=" << rtp_header.header.sequenceNumber << - ", pt=" << static_cast<int>(rtp_header.header.payloadType) << - ", ssrc=" << rtp_header.header.ssrc << - ", len=" << length_bytes; - int error = InsertPacketInternal(rtp_header, payload, length_bytes, - receive_timestamp, false); + int error = + InsertPacketInternal(rtp_header, payload, receive_timestamp, false); if (error != 0) { error_code_ = error; return kFail; @@ -138,15 +139,9 @@ int NetEqImpl::InsertPacket(const WebRtcRTPHeader& rtp_header, int NetEqImpl::InsertSyncPacket(const WebRtcRTPHeader& rtp_header, uint32_t receive_timestamp) { CriticalSectionScoped lock(crit_sect_.get()); - LOG(LS_VERBOSE) << "InsertPacket-Sync: ts=" - << rtp_header.header.timestamp << - ", sn=" << rtp_header.header.sequenceNumber << - ", pt=" << static_cast<int>(rtp_header.header.payloadType) << - ", ssrc=" << rtp_header.header.ssrc; - const uint8_t kSyncPayload[] = { 's', 'y', 'n', 'c' }; - int error = InsertPacketInternal( - rtp_header, kSyncPayload, sizeof(kSyncPayload), receive_timestamp, true); + int error = + InsertPacketInternal(rtp_header, kSyncPayload, receive_timestamp, true); if (error != 0) { error_code_ = error; @@ -156,14 +151,12 @@ int NetEqImpl::InsertSyncPacket(const WebRtcRTPHeader& rtp_header, } int NetEqImpl::GetAudio(size_t max_length, int16_t* output_audio, - size_t* samples_per_channel, int* num_channels, + size_t* samples_per_channel, size_t* num_channels, NetEqOutputType* type) { + TRACE_EVENT0("webrtc", "NetEqImpl::GetAudio"); CriticalSectionScoped lock(crit_sect_.get()); - LOG(LS_VERBOSE) << "GetAudio"; int error = GetAudioInternal(max_length, output_audio, samples_per_channel, num_channels); - LOG(LS_VERBOSE) << "Produced " << *samples_per_channel << - " samples/channel for " << *num_channels << " channel(s)"; if (error != 0) { error_code_ = error; return kFail; @@ -171,16 +164,24 @@ int NetEqImpl::GetAudio(size_t max_length, int16_t* output_audio, if (type) { *type = LastOutputType(); } + last_output_sample_rate_hz_ = + rtc::checked_cast<int>(*samples_per_channel * 100); + RTC_DCHECK(last_output_sample_rate_hz_ == 8000 || + last_output_sample_rate_hz_ == 16000 || + last_output_sample_rate_hz_ == 32000 || + last_output_sample_rate_hz_ == 48000) + << "Unexpected sample rate " << last_output_sample_rate_hz_; return kOK; } int NetEqImpl::RegisterPayloadType(NetEqDecoder codec, + const std::string& name, uint8_t rtp_payload_type) { CriticalSectionScoped lock(crit_sect_.get()); LOG(LS_VERBOSE) << "RegisterPayloadType " << static_cast<int>(rtp_payload_type) << " " << static_cast<int>(codec); - int ret = decoder_database_->RegisterPayload(rtp_payload_type, codec); + int ret = decoder_database_->RegisterPayload(rtp_payload_type, codec, name); if (ret != DecoderDatabase::kOK) { switch (ret) { case DecoderDatabase::kInvalidRtpPayloadType: @@ -202,6 +203,7 @@ int NetEqImpl::RegisterPayloadType(NetEqDecoder codec, int NetEqImpl::RegisterExternalDecoder(AudioDecoder* decoder, NetEqDecoder codec, + const std::string& codec_name, uint8_t rtp_payload_type, int sample_rate_hz) { CriticalSectionScoped lock(crit_sect_.get()); @@ -213,8 +215,8 @@ int NetEqImpl::RegisterExternalDecoder(AudioDecoder* decoder, assert(false); return kFail; } - int ret = decoder_database_->InsertExternal(rtp_payload_type, codec, - sample_rate_hz, decoder); + int ret = decoder_database_->InsertExternal( + rtp_payload_type, codec, codec_name, sample_rate_hz, decoder); if (ret != DecoderDatabase::kOK) { switch (ret) { case DecoderDatabase::kInvalidRtpPayloadType: @@ -370,6 +372,11 @@ bool NetEqImpl::GetPlayoutTimestamp(uint32_t* timestamp) { return true; } +int NetEqImpl::last_output_sample_rate_hz() const { + CriticalSectionScoped lock(crit_sect_.get()); + return last_output_sample_rate_hz_; +} + int NetEqImpl::SetTargetNumberOfChannels() { return kNotImplemented; } @@ -441,12 +448,11 @@ const SyncBuffer* NetEqImpl::sync_buffer_for_test() const { // Methods below this line are private. int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, - const uint8_t* payload, - size_t length_bytes, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp, bool is_sync_packet) { - if (!payload) { - LOG_F(LS_ERROR) << "payload == NULL"; + if (payload.empty()) { + LOG_F(LS_ERROR) << "payload is empty"; return kInvalidPointer; } // Sanity checks for sync-packets. @@ -482,7 +488,7 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, packet->header.timestamp = rtp_header.header.timestamp; packet->header.ssrc = rtp_header.header.ssrc; packet->header.numCSRCs = 0; - packet->payload_length = length_bytes; + packet->payload_length = payload.size(); packet->primary = true; packet->waiting_time = 0; packet->payload = new uint8_t[packet->payload_length]; @@ -490,8 +496,8 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, if (!packet->payload) { LOG_F(LS_ERROR) << "Payload pointer is NULL."; } - assert(payload); // Already checked above. - memcpy(packet->payload, payload, packet->payload_length); + assert(!payload.empty()); // Already checked above. + memcpy(packet->payload, payload.data(), packet->payload_length); // Insert packet in a packet list. packet_list.push_back(packet); // Save main payloads header for later. @@ -738,7 +744,7 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, int NetEqImpl::GetAudioInternal(size_t max_length, int16_t* output, size_t* samples_per_channel, - int* num_channels) { + size_t* num_channels) { PacketList packet_list; DtmfEvent dtmf_event; Operations operation; @@ -749,8 +755,6 @@ int NetEqImpl::GetAudioInternal(size_t max_length, last_mode_ = kModeError; return return_value; } - LOG(LS_VERBOSE) << "GetDecision returned operation=" << operation << - " and " << packet_list.size() << " packet(s)"; AudioDecoder::SpeechType speech_type; int length = 0; @@ -864,10 +868,7 @@ int NetEqImpl::GetAudioInternal(size_t max_length, const size_t samples_from_sync = sync_buffer_->GetNextAudioInterleaved(num_output_samples_per_channel, output); - *num_channels = static_cast<int>(sync_buffer_->Channels()); - LOG(LS_VERBOSE) << "Sync buffer (" << *num_channels << " channel(s)):" << - " insert " << algorithm_buffer_->Size() << " samples, extract " << - samples_from_sync << " samples"; + *num_channels = sync_buffer_->Channels(); if (sync_buffer_->FutureLength() < expand_->overlap_length()) { // The sync buffer should always contain |overlap_length| samples, but now // too many samples have been extracted. Reinstall the |overlap_length| @@ -1325,7 +1326,6 @@ int NetEqImpl::DecodeCng(AudioDecoder* decoder, int* decoded_length, &decoded_buffer_[*decoded_length], speech_type); if (length > 0) { *decoded_length += length; - LOG(LS_VERBOSE) << "Decoded " << length << " CNG samples"; } else { // Error. LOG(LS_WARNING) << "Failed to decode CNG"; @@ -1365,34 +1365,17 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation, int decode_length; if (packet->sync_packet) { // Decode to silence with the same frame size as the last decode. - LOG(LS_VERBOSE) << "Decoding sync-packet: " << - " ts=" << packet->header.timestamp << - ", sn=" << packet->header.sequenceNumber << - ", pt=" << static_cast<int>(packet->header.payloadType) << - ", ssrc=" << packet->header.ssrc << - ", len=" << packet->payload_length; memset(&decoded_buffer_[*decoded_length], 0, decoder_frame_length_ * decoder->Channels() * sizeof(decoded_buffer_[0])); decode_length = rtc::checked_cast<int>(decoder_frame_length_); } else if (!packet->primary) { // This is a redundant payload; call the special decoder method. - LOG(LS_VERBOSE) << "Decoding packet (redundant):" << - " ts=" << packet->header.timestamp << - ", sn=" << packet->header.sequenceNumber << - ", pt=" << static_cast<int>(packet->header.payloadType) << - ", ssrc=" << packet->header.ssrc << - ", len=" << packet->payload_length; decode_length = decoder->DecodeRedundant( packet->payload, packet->payload_length, fs_hz_, (decoded_buffer_length_ - *decoded_length) * sizeof(int16_t), &decoded_buffer_[*decoded_length], speech_type); } else { - LOG(LS_VERBOSE) << "Decoding packet: ts=" << packet->header.timestamp << - ", sn=" << packet->header.sequenceNumber << - ", pt=" << static_cast<int>(packet->header.payloadType) << - ", ssrc=" << packet->header.ssrc << - ", len=" << packet->payload_length; decode_length = decoder->Decode( packet->payload, packet->payload_length, fs_hz_, @@ -1408,9 +1391,6 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation, // Update |decoder_frame_length_| with number of samples per channel. decoder_frame_length_ = static_cast<size_t>(decode_length) / decoder->Channels(); - LOG(LS_VERBOSE) << "Decoded " << decode_length << " samples (" - << decoder->Channels() << " channel(s) -> " - << decoder_frame_length_ << " samples per channel)"; } else if (decode_length < 0) { // Error. LOG(LS_WARNING) << "Decode " << decode_length << " " << payload_length; diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.h b/webrtc/modules/audio_coding/neteq/neteq_impl.h index c001e53b81..940deadd2f 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.h +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.h @@ -11,6 +11,8 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_NETEQ_IMPL_H_ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_NETEQ_IMPL_H_ +#include <string> + #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/base/thread_annotations.h" @@ -79,8 +81,7 @@ class NetEqImpl : public webrtc::NetEq { // the same tick rate as the RTP timestamp of the current payload. // Returns 0 on success, -1 on failure. int InsertPacket(const WebRtcRTPHeader& rtp_header, - const uint8_t* payload, - size_t length_bytes, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp) override; // Inserts a sync-packet into packet queue. Sync-packets are decoded to @@ -106,20 +107,16 @@ class NetEqImpl : public webrtc::NetEq { int GetAudio(size_t max_length, int16_t* output_audio, size_t* samples_per_channel, - int* num_channels, + size_t* num_channels, NetEqOutputType* type) override; - // Associates |rtp_payload_type| with |codec| and stores the information in - // the codec database. Returns kOK on success, kFail on failure. int RegisterPayloadType(NetEqDecoder codec, + const std::string& codec_name, uint8_t rtp_payload_type) override; - // 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|. The decoder will produce samples - // at the rate |sample_rate_hz|. Returns kOK on success, kFail on failure. int RegisterExternalDecoder(AudioDecoder* decoder, NetEqDecoder codec, + const std::string& codec_name, uint8_t rtp_payload_type, int sample_rate_hz) override; @@ -169,6 +166,8 @@ class NetEqImpl : public webrtc::NetEq { bool GetPlayoutTimestamp(uint32_t* timestamp) override; + int last_output_sample_rate_hz() const override; + int SetTargetNumberOfChannels() override; int SetTargetSampleRate() override; @@ -207,8 +206,7 @@ class NetEqImpl : public webrtc::NetEq { // above. Returns 0 on success, otherwise an error code. // TODO(hlundin): Merge this with InsertPacket above? int InsertPacketInternal(const WebRtcRTPHeader& rtp_header, - const uint8_t* payload, - size_t length_bytes, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp, bool is_sync_packet) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); @@ -222,7 +220,8 @@ class NetEqImpl : public webrtc::NetEq { int GetAudioInternal(size_t max_length, int16_t* output, size_t* samples_per_channel, - int* num_channels) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); + size_t* num_channels) + EXCLUSIVE_LOCKS_REQUIRED(crit_sect_); // Provides a decision to the GetAudioInternal method. The decision what to // do is written to |operation|. Packets to decode are written to @@ -377,6 +376,7 @@ class NetEqImpl : public webrtc::NetEq { StatisticsCalculator stats_ GUARDED_BY(crit_sect_); int fs_hz_ GUARDED_BY(crit_sect_); int fs_mult_ GUARDED_BY(crit_sect_); + int last_output_sample_rate_hz_ GUARDED_BY(crit_sect_); size_t output_size_samples_ GUARDED_BY(crit_sect_); size_t decoder_frame_length_ GUARDED_BY(crit_sect_); Modes last_mode_ GUARDED_BY(crit_sect_); diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc index 90640ca1d2..f734883635 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -240,9 +240,10 @@ TEST_F(NetEqImplTest, RegisterPayloadType) { CreateInstance(); uint8_t rtp_payload_type = 0; NetEqDecoder codec_type = NetEqDecoder::kDecoderPCMu; + const std::string kCodecName = "Robert\'); DROP TABLE Students;"; EXPECT_CALL(*mock_decoder_database_, - RegisterPayload(rtp_payload_type, codec_type)); - neteq_->RegisterPayloadType(codec_type, rtp_payload_type); + RegisterPayload(rtp_payload_type, codec_type, kCodecName)); + neteq_->RegisterPayloadType(codec_type, kCodecName, rtp_payload_type); } TEST_F(NetEqImplTest, RemovePayloadType) { @@ -359,13 +360,12 @@ TEST_F(NetEqImplTest, InsertPacket) { .WillRepeatedly(Return(PayloadSplitter::kOK)); // Insert first packet. - neteq_->InsertPacket(rtp_header, payload, kPayloadLength, kFirstReceiveTime); + neteq_->InsertPacket(rtp_header, payload, kFirstReceiveTime); // Insert second packet. rtp_header.header.timestamp += 160; rtp_header.header.sequenceNumber += 1; - neteq_->InsertPacket(rtp_header, payload, kPayloadLength, - kFirstReceiveTime + 155); + neteq_->InsertPacket(rtp_header, payload, kFirstReceiveTime + 155); } TEST_F(NetEqImplTest, InsertPacketsUntilBufferIsFull) { @@ -384,13 +384,12 @@ TEST_F(NetEqImplTest, InsertPacketsUntilBufferIsFull) { rtp_header.header.ssrc = 0x87654321; EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType( - NetEqDecoder::kDecoderPCM16B, kPayloadType)); + NetEqDecoder::kDecoderPCM16B, "", kPayloadType)); // Insert packets. The buffer should not flush. for (size_t i = 1; i <= config_.max_packets_in_buffer; ++i) { EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); rtp_header.header.timestamp += kPayloadLengthSamples; rtp_header.header.sequenceNumber += 1; EXPECT_EQ(i, packet_buffer_->NumPacketsInBuffer()); @@ -399,8 +398,7 @@ TEST_F(NetEqImplTest, InsertPacketsUntilBufferIsFull) { // Insert one more packet and make sure the buffer got flushed. That is, it // should only hold one single packet. EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); EXPECT_EQ(1u, packet_buffer_->NumPacketsInBuffer()); const RTPHeader* test_header = packet_buffer_->NextRtpHeader(); EXPECT_EQ(rtp_header.header.timestamp, test_header->timestamp); @@ -434,12 +432,11 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) { CountingSamplesDecoder() : next_value_(1) {} // Produce as many samples as input bytes (|encoded_len|). - int Decode(const uint8_t* encoded, - size_t encoded_len, - int /* sample_rate_hz */, - size_t /* max_decoded_bytes */, - int16_t* decoded, - SpeechType* speech_type) override { + int DecodeInternal(const uint8_t* encoded, + size_t encoded_len, + int /* sample_rate_hz */, + int16_t* decoded, + SpeechType* speech_type) override { for (size_t i = 0; i < encoded_len; ++i) { decoded[i] = next_value_++; } @@ -459,25 +456,24 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) { EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( &decoder_, NetEqDecoder::kDecoderPCM16B, - kPayloadType, kSampleRateHz)); + "dummy name", kPayloadType, kSampleRateHz)); // Insert one packet. EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); // Pull audio once. const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000); int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; NetEqOutputType type; EXPECT_EQ( NetEq::kOK, neteq_->GetAudio( kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputNormal, type); // Start with a simple check that the fake decoder is behaving as expected. @@ -531,33 +527,32 @@ TEST_F(NetEqImplTest, ReorderedPacket) { int16_t dummy_output[kPayloadLengthSamples] = {0}; // The below expectation will make the mock decoder write // |kPayloadLengthSamples| zeros to the output array, and mark it as speech. - EXPECT_CALL(mock_decoder, - Decode(Pointee(0), kPayloadLengthBytes, kSampleRateHz, _, _, _)) - .WillOnce(DoAll(SetArrayArgument<4>(dummy_output, + EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(0), kPayloadLengthBytes, + kSampleRateHz, _, _)) + .WillOnce(DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kPayloadLengthSamples), - SetArgPointee<5>(AudioDecoder::kSpeech), + SetArgPointee<4>(AudioDecoder::kSpeech), Return(kPayloadLengthSamples))); EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( &mock_decoder, NetEqDecoder::kDecoderPCM16B, - kPayloadType, kSampleRateHz)); + "dummy name", kPayloadType, kSampleRateHz)); // Insert one packet. EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); // Pull audio once. const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000); int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; NetEqOutputType type; EXPECT_EQ( NetEq::kOK, neteq_->GetAudio( kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputNormal, type); // Insert two more packets. The first one is out of order, and is already too @@ -566,22 +561,20 @@ TEST_F(NetEqImplTest, ReorderedPacket) { rtp_header.header.timestamp -= kPayloadLengthSamples; payload[0] = 1; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); rtp_header.header.sequenceNumber += 2; rtp_header.header.timestamp += 2 * kPayloadLengthSamples; payload[0] = 2; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); // Expect only the second packet to be decoded (the one with "2" as the first // payload byte). - EXPECT_CALL(mock_decoder, - Decode(Pointee(2), kPayloadLengthBytes, kSampleRateHz, _, _, _)) - .WillOnce(DoAll(SetArrayArgument<4>(dummy_output, + EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(2), kPayloadLengthBytes, + kSampleRateHz, _, _)) + .WillOnce(DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kPayloadLengthSamples), - SetArgPointee<5>(AudioDecoder::kSpeech), + SetArgPointee<4>(AudioDecoder::kSpeech), Return(kPayloadLengthSamples))); // Pull audio once. @@ -590,7 +583,7 @@ TEST_F(NetEqImplTest, ReorderedPacket) { neteq_->GetAudio( kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputNormal, type); // Now check the packet buffer, and make sure it is empty, since the @@ -622,35 +615,33 @@ TEST_F(NetEqImplTest, FirstPacketUnknown) { // Insert one packet. Note that we have not registered any payload type, so // this packet will be rejected. EXPECT_EQ(NetEq::kFail, - neteq_->InsertPacket(rtp_header, payload, kPayloadLengthBytes, - kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); EXPECT_EQ(NetEq::kUnknownRtpPayloadType, neteq_->LastError()); // Pull audio once. const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000); int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; NetEqOutputType type; EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); ASSERT_LE(samples_per_channel, kMaxOutputSize); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputPLC, type); // Register the payload type. EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType( - NetEqDecoder::kDecoderPCM16B, kPayloadType)); + NetEqDecoder::kDecoderPCM16B, "", kPayloadType)); // Insert 10 packets. for (size_t i = 0; i < 10; ++i) { rtp_header.header.sequenceNumber++; rtp_header.header.timestamp += kPayloadLengthSamples; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_header, payload, kPayloadLengthBytes, - kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); EXPECT_EQ(i + 1, packet_buffer_->NumPacketsInBuffer()); } @@ -661,7 +652,7 @@ TEST_F(NetEqImplTest, FirstPacketUnknown) { &num_channels, &type)); ASSERT_LE(samples_per_channel, kMaxOutputSize); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputNormal, type) << "NetEq did not decode the packets as expected."; } @@ -697,54 +688,53 @@ TEST_F(NetEqImplTest, CodecInternalCng) { // Pointee(x) verifies that first byte of the payload equals x, this makes it // possible to verify that the correct payload is fed to Decode(). - EXPECT_CALL(mock_decoder, Decode(Pointee(0), kPayloadLengthBytes, - kSampleRateKhz * 1000, _, _, _)) - .WillOnce(DoAll(SetArrayArgument<4>(dummy_output, + EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(0), kPayloadLengthBytes, + kSampleRateKhz * 1000, _, _)) + .WillOnce(DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kPayloadLengthSamples), - SetArgPointee<5>(AudioDecoder::kSpeech), + SetArgPointee<4>(AudioDecoder::kSpeech), Return(kPayloadLengthSamples))); - EXPECT_CALL(mock_decoder, Decode(Pointee(1), kPayloadLengthBytes, - kSampleRateKhz * 1000, _, _, _)) - .WillOnce(DoAll(SetArrayArgument<4>(dummy_output, + EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(1), kPayloadLengthBytes, + kSampleRateKhz * 1000, _, _)) + .WillOnce(DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kPayloadLengthSamples), - SetArgPointee<5>(AudioDecoder::kComfortNoise), + SetArgPointee<4>(AudioDecoder::kComfortNoise), Return(kPayloadLengthSamples))); - EXPECT_CALL(mock_decoder, Decode(IsNull(), 0, kSampleRateKhz * 1000, _, _, _)) - .WillOnce(DoAll(SetArrayArgument<4>(dummy_output, + EXPECT_CALL(mock_decoder, + DecodeInternal(IsNull(), 0, kSampleRateKhz * 1000, _, _)) + .WillOnce(DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kPayloadLengthSamples), - SetArgPointee<5>(AudioDecoder::kComfortNoise), + SetArgPointee<4>(AudioDecoder::kComfortNoise), Return(kPayloadLengthSamples))); - EXPECT_CALL(mock_decoder, Decode(Pointee(2), kPayloadLengthBytes, - kSampleRateKhz * 1000, _, _, _)) - .WillOnce(DoAll(SetArrayArgument<4>(dummy_output, + EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(2), kPayloadLengthBytes, + kSampleRateKhz * 1000, _, _)) + .WillOnce(DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kPayloadLengthSamples), - SetArgPointee<5>(AudioDecoder::kSpeech), + SetArgPointee<4>(AudioDecoder::kSpeech), Return(kPayloadLengthSamples))); EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( &mock_decoder, NetEqDecoder::kDecoderOpus, - kPayloadType, kSampleRateKhz * 1000)); + "dummy name", kPayloadType, kSampleRateKhz * 1000)); // Insert one packet (decoder will return speech). EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); // Insert second packet (decoder will return CNG). payload[0] = 1; rtp_header.header.sequenceNumber++; rtp_header.header.timestamp += kPayloadLengthSamples; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateKhz); int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; uint32_t timestamp; uint32_t last_timestamp; NetEqOutputType type; @@ -769,7 +759,7 @@ TEST_F(NetEqImplTest, CodecInternalCng) { for (size_t i = 1; i < 6; ++i) { ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(expected_type[i - 1], type); EXPECT_TRUE(neteq_->GetPlayoutTimestamp(×tamp)); EXPECT_EQ(NetEq::kOK, @@ -785,12 +775,11 @@ TEST_F(NetEqImplTest, CodecInternalCng) { rtp_header.header.sequenceNumber += 2; rtp_header.header.timestamp += 2 * kPayloadLengthSamples; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); for (size_t i = 6; i < 8; ++i) { ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(expected_type[i - 1], type); EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, @@ -810,7 +799,7 @@ TEST_F(NetEqImplTest, UnsupportedDecoder) { UseNoMocks(); CreateInstance(); static const size_t kNetEqMaxFrameSize = 2880; // 60 ms @ 48 kHz. - static const int kChannels = 2; + static const size_t kChannels = 2; const uint8_t kPayloadType = 17; // Just an arbitrary number. const uint32_t kReceiveTime = 17; // Value doesn't matter for this test. @@ -866,13 +855,12 @@ TEST_F(NetEqImplTest, UnsupportedDecoder) { EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( &decoder_, NetEqDecoder::kDecoderPCM16B, - kPayloadType, kSampleRateHz)); + "dummy name", kPayloadType, kSampleRateHz)); // Insert one packet. payload[0] = kFirstPayloadValue; // This will make Decode() fail. EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); // Insert another packet. payload[0] = kSecondPayloadValue; // This will make Decode() successful. @@ -881,14 +869,12 @@ TEST_F(NetEqImplTest, UnsupportedDecoder) { // the second packet get decoded. rtp_header.header.timestamp += 3 * kPayloadLengthSamples; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, kPayloadLengthBytes, kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); - const size_t kMaxOutputSize = - static_cast<size_t>(10 * kSampleRateHz / 1000 * kChannels); + const size_t kMaxOutputSize = 10 * kSampleRateHz / 1000 * kChannels; int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; NetEqOutputType type; EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(kMaxOutputSize, output, @@ -926,14 +912,13 @@ TEST_F(NetEqImplTest, FloodBufferAndGetNetworkStats) { rtp_header.header.ssrc = 0x87654321; EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType( - NetEqDecoder::kDecoderPCM16B, kPayloadType)); + NetEqDecoder::kDecoderPCM16B, "", kPayloadType)); // Insert packets until the buffer flushes. for (size_t i = 0; i <= config_.max_packets_in_buffer; ++i) { EXPECT_EQ(i, packet_buffer_->NumPacketsInBuffer()); EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_header, payload, kPayloadLengthBytes, - kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); rtp_header.header.timestamp += rtc::checked_cast<uint32_t>(kPayloadLengthSamples); ++rtp_header.header.sequenceNumber; @@ -975,20 +960,19 @@ TEST_F(NetEqImplTest, DecodedPayloadTooShort) { // |kPayloadLengthSamples| - 5 zeros to the output array, and mark it as // speech. That is, the decoded length is 5 samples shorter than the expected. EXPECT_CALL(mock_decoder, - Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _)) + DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _)) .WillOnce( - DoAll(SetArrayArgument<4>(dummy_output, + DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kPayloadLengthSamples - 5), - SetArgPointee<5>(AudioDecoder::kSpeech), + SetArgPointee<4>(AudioDecoder::kSpeech), Return(kPayloadLengthSamples - 5))); EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( &mock_decoder, NetEqDecoder::kDecoderPCM16B, - kPayloadType, kSampleRateHz)); + "dummy name", kPayloadType, kSampleRateHz)); // Insert one packet. EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_header, payload, kPayloadLengthBytes, - kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); EXPECT_EQ(5u, neteq_->sync_buffer_for_test()->FutureLength()); @@ -996,13 +980,13 @@ TEST_F(NetEqImplTest, DecodedPayloadTooShort) { const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000); int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; NetEqOutputType type; EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); ASSERT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputNormal, type); EXPECT_CALL(mock_decoder, Die()); @@ -1050,57 +1034,56 @@ TEST_F(NetEqImplTest, DecodingError) { InSequence sequence; // Dummy variable. // Mock decoder works normally the first time. EXPECT_CALL(mock_decoder, - Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _)) + DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _)) .Times(3) .WillRepeatedly( - DoAll(SetArrayArgument<4>(dummy_output, + DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kFrameLengthSamples), - SetArgPointee<5>(AudioDecoder::kSpeech), + SetArgPointee<4>(AudioDecoder::kSpeech), Return(kFrameLengthSamples))) .RetiresOnSaturation(); // Then mock decoder fails. A common reason for failure can be buffer being // too short EXPECT_CALL(mock_decoder, - Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _)) + DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _)) .WillOnce(Return(-1)) .RetiresOnSaturation(); // Mock decoder finally returns to normal. EXPECT_CALL(mock_decoder, - Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _)) + DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _)) .Times(2) .WillRepeatedly( - DoAll(SetArrayArgument<4>(dummy_output, - dummy_output + kFrameLengthSamples), - SetArgPointee<5>(AudioDecoder::kSpeech), + DoAll(SetArrayArgument<3>(dummy_output, + dummy_output + kFrameLengthSamples), + SetArgPointee<4>(AudioDecoder::kSpeech), Return(kFrameLengthSamples))); } EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( &mock_decoder, NetEqDecoder::kDecoderPCM16B, - kPayloadType, kSampleRateHz)); + "dummy name", kPayloadType, kSampleRateHz)); // Insert packets. for (int i = 0; i < 6; ++i) { rtp_header.header.sequenceNumber += 1; rtp_header.header.timestamp += kFrameLengthSamples; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_header, payload, kPayloadLengthBytes, - kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); } // Pull audio. const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000); int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; NetEqOutputType type; EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputNormal, type); // Pull audio again. Decoder fails. @@ -1110,7 +1093,7 @@ TEST_F(NetEqImplTest, DecodingError) { EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError()); EXPECT_EQ(kDecoderErrorCode, neteq_->LastDecoderError()); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); // TODO(minyue): should NetEq better give kOutputPLC, since it is actually an // expansion. EXPECT_EQ(kOutputNormal, type); @@ -1120,7 +1103,7 @@ TEST_F(NetEqImplTest, DecodingError) { neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputPLC, type); // Pull audio again, should behave normal. @@ -1128,7 +1111,7 @@ TEST_F(NetEqImplTest, DecodingError) { neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputNormal, type); EXPECT_CALL(mock_decoder, Die()); @@ -1174,55 +1157,54 @@ TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) { InSequence sequence; // Dummy variable. // Mock decoder works normally the first 2 times. EXPECT_CALL(mock_decoder, - Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _)) + DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _)) .Times(2) .WillRepeatedly( - DoAll(SetArrayArgument<4>(dummy_output, + DoAll(SetArrayArgument<3>(dummy_output, dummy_output + kFrameLengthSamples), - SetArgPointee<5>(AudioDecoder::kComfortNoise), + SetArgPointee<4>(AudioDecoder::kComfortNoise), Return(kFrameLengthSamples))) .RetiresOnSaturation(); // Then mock decoder fails. A common reason for failure can be buffer being // too short - EXPECT_CALL(mock_decoder, Decode(nullptr, 0, kSampleRateHz, _, _, _)) + EXPECT_CALL(mock_decoder, DecodeInternal(nullptr, 0, kSampleRateHz, _, _)) .WillOnce(Return(-1)) .RetiresOnSaturation(); // Mock decoder finally returns to normal. - EXPECT_CALL(mock_decoder, Decode(nullptr, 0, kSampleRateHz, _, _, _)) + EXPECT_CALL(mock_decoder, DecodeInternal(nullptr, 0, kSampleRateHz, _, _)) .Times(2) .WillRepeatedly( - DoAll(SetArrayArgument<4>(dummy_output, - dummy_output + kFrameLengthSamples), - SetArgPointee<5>(AudioDecoder::kComfortNoise), + DoAll(SetArrayArgument<3>(dummy_output, + dummy_output + kFrameLengthSamples), + SetArgPointee<4>(AudioDecoder::kComfortNoise), Return(kFrameLengthSamples))); } EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( &mock_decoder, NetEqDecoder::kDecoderPCM16B, - kPayloadType, kSampleRateHz)); + "dummy name", kPayloadType, kSampleRateHz)); // Insert 2 packets. This will make netEq into codec internal CNG mode. for (int i = 0; i < 2; ++i) { rtp_header.header.sequenceNumber += 1; rtp_header.header.timestamp += kFrameLengthSamples; EXPECT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_header, payload, kPayloadLengthBytes, - kReceiveTime)); + neteq_->InsertPacket(rtp_header, payload, kReceiveTime)); } // Pull audio. const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000); int16_t output[kMaxOutputSize]; size_t samples_per_channel; - int num_channels; + size_t num_channels; NetEqOutputType type; EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputCNG, type); // Pull audio again. Decoder fails. @@ -1232,7 +1214,7 @@ TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) { EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError()); EXPECT_EQ(kDecoderErrorCode, neteq_->LastDecoderError()); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); // TODO(minyue): should NetEq better give kOutputPLC, since it is actually an // expansion. EXPECT_EQ(kOutputCNG, type); @@ -1242,10 +1224,19 @@ TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) { neteq_->GetAudio(kMaxOutputSize, output, &samples_per_channel, &num_channels, &type)); EXPECT_EQ(kMaxOutputSize, samples_per_channel); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(kOutputCNG, type); EXPECT_CALL(mock_decoder, Die()); } +// Tests that the return value from last_output_sample_rate_hz() is equal to the +// configured inital sample rate. +TEST_F(NetEqImplTest, InitialLastOutputSampleRate) { + UseNoMocks(); + config_.sample_rate_hz = 48000; + CreateInstance(); + EXPECT_EQ(48000, neteq_->last_output_sample_rate_hz()); +} + }// namespace webrtc diff --git a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc index 16fa04c234..34ca9ea856 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_network_stats_unittest.cc @@ -191,8 +191,7 @@ struct NetEqNetworkStatsCheck { frame_size_samples_, &rtp_header_); if (!Lost(next_send_time)) { - InsertPacket(rtp_header_, payload_, kPayloadSizeByte, - next_send_time); + InsertPacket(rtp_header_, payload_, next_send_time); } } GetOutputAudio(kMaxOutputSize, output_, &output_type); diff --git a/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc index 66874b8a50..d3f59ec668 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_stereo_unittest.cc @@ -16,19 +16,18 @@ #include "testing/gtest/include/gtest/gtest.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" #include "webrtc/test/testsupport/fileutils.h" -#include "webrtc/test/testsupport/gtest_disable.h" namespace webrtc { struct TestParameters { int frame_size; int sample_rate; - int num_channels; + size_t num_channels; }; // This is a parameterized test. The test parameters are supplied through a @@ -127,11 +126,10 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> { default: FAIL() << "We shouldn't get here."; } + ASSERT_EQ(NetEq::kOK, neteq_mono_->RegisterPayloadType(mono_decoder, "mono", + kPayloadTypeMono)); ASSERT_EQ(NetEq::kOK, - neteq_mono_->RegisterPayloadType(mono_decoder, - kPayloadTypeMono)); - ASSERT_EQ(NetEq::kOK, - neteq_->RegisterPayloadType(multi_decoder, + neteq_->RegisterPayloadType(multi_decoder, "multi-channel", kPayloadTypeMulti)); } @@ -165,7 +163,7 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> { void VerifyOutput(size_t num_samples) { for (size_t i = 0; i < num_samples; ++i) { - for (int j = 0; j < num_channels_; ++j) { + for (size_t j = 0; j < num_channels_; ++j) { ASSERT_EQ(output_[i], output_multi_channel_[i * num_channels_ + j]) << "Diff in sample " << i << ", channel " << j << "."; } @@ -196,14 +194,16 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> { while (time_now >= next_arrival_time) { // Insert packet in mono instance. ASSERT_EQ(NetEq::kOK, - neteq_mono_->InsertPacket(rtp_header_mono_, encoded_, - payload_size_bytes_, + neteq_mono_->InsertPacket(rtp_header_mono_, + rtc::ArrayView<const uint8_t>( + encoded_, payload_size_bytes_), next_arrival_time)); // Insert packet in multi-channel instance. - ASSERT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_header_, encoded_multi_channel_, - multi_payload_size_bytes_, - next_arrival_time)); + ASSERT_EQ(NetEq::kOK, neteq_->InsertPacket( + rtp_header_, rtc::ArrayView<const uint8_t>( + encoded_multi_channel_, + multi_payload_size_bytes_), + next_arrival_time)); // Get next input packets (mono and multi-channel). do { next_send_time = GetNewPackets(); @@ -214,12 +214,12 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> { NetEqOutputType output_type; // Get audio from mono instance. size_t samples_per_channel; - int num_channels; + size_t num_channels; EXPECT_EQ(NetEq::kOK, neteq_mono_->GetAudio(kMaxBlockSize, output_, &samples_per_channel, &num_channels, &output_type)); - EXPECT_EQ(1, num_channels); + EXPECT_EQ(1u, num_channels); EXPECT_EQ(output_size_samples_, samples_per_channel); // Get audio from multi-channel instance. ASSERT_EQ(NetEq::kOK, @@ -239,7 +239,7 @@ class NetEqStereoTest : public ::testing::TestWithParam<TestParameters> { } } - const int num_channels_; + const size_t num_channels_; const int sample_rate_hz_; const int samples_per_ms_; const int frame_size_ms_; @@ -275,7 +275,12 @@ class NetEqStereoTestNoJitter : public NetEqStereoTest { } }; -TEST_P(NetEqStereoTestNoJitter, DISABLED_ON_ANDROID(RunTest)) { +#if defined(WEBRTC_ANDROID) +#define MAYBE_RunTest DISABLED_RunTest +#else +#define MAYBE_RunTest RunTest +#endif +TEST_P(NetEqStereoTestNoJitter, MAYBE_RunTest) { RunTest(8); } @@ -300,7 +305,7 @@ class NetEqStereoTestPositiveDrift : public NetEqStereoTest { double drift_factor; }; -TEST_P(NetEqStereoTestPositiveDrift, DISABLED_ON_ANDROID(RunTest)) { +TEST_P(NetEqStereoTestPositiveDrift, MAYBE_RunTest) { RunTest(100); } @@ -313,7 +318,7 @@ class NetEqStereoTestNegativeDrift : public NetEqStereoTestPositiveDrift { } }; -TEST_P(NetEqStereoTestNegativeDrift, DISABLED_ON_ANDROID(RunTest)) { +TEST_P(NetEqStereoTestNegativeDrift, MAYBE_RunTest) { RunTest(100); } @@ -341,7 +346,7 @@ class NetEqStereoTestDelays : public NetEqStereoTest { int frame_index_; }; -TEST_P(NetEqStereoTestDelays, DISABLED_ON_ANDROID(RunTest)) { +TEST_P(NetEqStereoTestDelays, MAYBE_RunTest) { RunTest(1000); } @@ -360,7 +365,10 @@ class NetEqStereoTestLosses : public NetEqStereoTest { int frame_index_; }; -TEST_P(NetEqStereoTestLosses, DISABLED_ON_ANDROID(RunTest)) { +// TODO(pbos): Enable on non-Android, this went failing while being accidentally +// disabled on all platforms and not just Android. +// https://bugs.chromium.org/p/webrtc/issues/detail?id=5387 +TEST_P(NetEqStereoTestLosses, DISABLED_RunTest) { RunTest(100); } diff --git a/webrtc/modules/audio_coding/neteq/neteq_tests.gypi b/webrtc/modules/audio_coding/neteq/neteq_tests.gypi index ee9583ab85..f02d3deee9 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_tests.gypi +++ b/webrtc/modules/audio_coding/neteq/neteq_tests.gypi @@ -39,6 +39,21 @@ 'defines': [ ], }, # neteq_rtpplay + { + 'target_name': 'neteq_unittest_proto', + 'type': 'static_library', + 'sources': [ + 'neteq_unittest.proto', + ], + 'variables': { + 'proto_in_dir': '.', + # Workaround to protect against gyp's pathname relativization when + # this file is included by modules.gyp. + 'proto_out_protected': 'webrtc/audio_coding/neteq', + 'proto_out_dir': '<(proto_out_protected)', + }, + 'includes': ['../../../build/protoc.gypi',], + }, ], }], ], @@ -56,6 +71,7 @@ 'isac', 'neteq_test_tools', # Test helpers 'pcm16b', + 'webrtc_opus', ], 'defines': [ 'CODEC_ILBC', @@ -72,6 +88,7 @@ 'CODEC_CNGCODEC32', 'CODEC_ATEVENT_DECODE', 'CODEC_RED', + 'CODEC_OPUS', ], 'include_dirs': [ 'include', diff --git a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc index 4340f54975..8d52c615da 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc @@ -28,29 +28,91 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "webrtc/test/testsupport/fileutils.h" -#include "webrtc/test/testsupport/gtest_disable.h" #include "webrtc/typedefs.h" +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT +#ifdef WEBRTC_ANDROID_PLATFORM_BUILD +#include "external/webrtc/webrtc/modules/audio_coding/neteq/neteq_unittest.pb.h" +#else +#include "webrtc/audio_coding/neteq/neteq_unittest.pb.h" +#endif +#endif + DEFINE_bool(gen_ref, false, "Generate reference files."); -namespace webrtc { +namespace { -static bool IsAllZero(const int16_t* buf, size_t buf_length) { +bool IsAllZero(const int16_t* buf, size_t buf_length) { bool all_zero = true; for (size_t n = 0; n < buf_length && all_zero; ++n) all_zero = buf[n] == 0; return all_zero; } -static bool IsAllNonZero(const int16_t* buf, size_t buf_length) { +bool IsAllNonZero(const int16_t* buf, size_t buf_length) { bool all_non_zero = true; for (size_t n = 0; n < buf_length && all_non_zero; ++n) all_non_zero = buf[n] != 0; return all_non_zero; } +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT +void Convert(const webrtc::NetEqNetworkStatistics& stats_raw, + webrtc::neteq_unittest::NetEqNetworkStatistics* stats) { + stats->set_current_buffer_size_ms(stats_raw.current_buffer_size_ms); + stats->set_preferred_buffer_size_ms(stats_raw.preferred_buffer_size_ms); + stats->set_jitter_peaks_found(stats_raw.jitter_peaks_found); + stats->set_packet_loss_rate(stats_raw.packet_loss_rate); + stats->set_packet_discard_rate(stats_raw.packet_discard_rate); + stats->set_expand_rate(stats_raw.expand_rate); + stats->set_speech_expand_rate(stats_raw.speech_expand_rate); + stats->set_preemptive_rate(stats_raw.preemptive_rate); + stats->set_accelerate_rate(stats_raw.accelerate_rate); + stats->set_secondary_decoded_rate(stats_raw.secondary_decoded_rate); + stats->set_clockdrift_ppm(stats_raw.clockdrift_ppm); + stats->set_added_zero_samples(stats_raw.added_zero_samples); + stats->set_mean_waiting_time_ms(stats_raw.mean_waiting_time_ms); + stats->set_median_waiting_time_ms(stats_raw.median_waiting_time_ms); + stats->set_min_waiting_time_ms(stats_raw.min_waiting_time_ms); + stats->set_max_waiting_time_ms(stats_raw.max_waiting_time_ms); +} + +void Convert(const webrtc::RtcpStatistics& stats_raw, + webrtc::neteq_unittest::RtcpStatistics* stats) { + stats->set_fraction_lost(stats_raw.fraction_lost); + stats->set_cumulative_lost(stats_raw.cumulative_lost); + stats->set_extended_max_sequence_number( + stats_raw.extended_max_sequence_number); + stats->set_jitter(stats_raw.jitter); +} + +void WriteMessage(FILE* file, const std::string& message) { + int32_t size = message.length(); + ASSERT_EQ(1u, fwrite(&size, sizeof(size), 1, file)); + if (size <= 0) + return; + ASSERT_EQ(static_cast<size_t>(size), + fwrite(message.data(), sizeof(char), size, file)); +} + +void ReadMessage(FILE* file, std::string* message) { + int32_t size; + ASSERT_EQ(1u, fread(&size, sizeof(size), 1, file)); + if (size <= 0) + return; + rtc::scoped_ptr<char[]> buffer(new char[size]); + ASSERT_EQ(static_cast<size_t>(size), + fread(buffer.get(), sizeof(char), size, file)); + message->assign(buffer.get(), size); +} +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT + +} // namespace + +namespace webrtc { + class RefFiles { public: RefFiles(const std::string& input_file, const std::string& output_file); @@ -128,92 +190,84 @@ void RefFiles::ReadFromFileAndCompare(const T (&test_results)[n], } } -void RefFiles::WriteToFile(const NetEqNetworkStatistics& stats) { - if (output_fp_) { - ASSERT_EQ(1u, fwrite(&stats, sizeof(NetEqNetworkStatistics), 1, - output_fp_)); - } +void RefFiles::WriteToFile(const NetEqNetworkStatistics& stats_raw) { +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!output_fp_) + return; + neteq_unittest::NetEqNetworkStatistics stats; + Convert(stats_raw, &stats); + + std::string stats_string; + ASSERT_TRUE(stats.SerializeToString(&stats_string)); + WriteMessage(output_fp_, stats_string); +#else + FAIL() << "Writing to reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } void RefFiles::ReadFromFileAndCompare( const NetEqNetworkStatistics& stats) { - // TODO(minyue): Update resource/audio_coding/neteq_network_stats.dat and - // resource/audio_coding/neteq_network_stats_win32.dat. - struct NetEqNetworkStatisticsOld { - uint16_t current_buffer_size_ms; // Current jitter buffer size in ms. - uint16_t preferred_buffer_size_ms; // Target buffer size in ms. - uint16_t jitter_peaks_found; // 1 if adding extra delay due to peaky - // jitter; 0 otherwise. - uint16_t packet_loss_rate; // Loss rate (network + late) in Q14. - uint16_t packet_discard_rate; // Late loss rate in Q14. - uint16_t expand_rate; // Fraction (of original stream) of synthesized - // audio inserted through expansion (in Q14). - uint16_t preemptive_rate; // Fraction of data inserted through pre-emptive - // expansion (in Q14). - uint16_t accelerate_rate; // Fraction of data removed through acceleration - // (in Q14). - int32_t clockdrift_ppm; // Average clock-drift in parts-per-million - // (positive or negative). - int added_zero_samples; // Number of zero samples added in "off" mode. - }; - if (input_fp_) { - // Read from ref file. - size_t stat_size = sizeof(NetEqNetworkStatisticsOld); - NetEqNetworkStatisticsOld ref_stats; - ASSERT_EQ(1u, fread(&ref_stats, stat_size, 1, input_fp_)); - // Compare - ASSERT_EQ(stats.current_buffer_size_ms, ref_stats.current_buffer_size_ms); - ASSERT_EQ(stats.preferred_buffer_size_ms, - ref_stats.preferred_buffer_size_ms); - ASSERT_EQ(stats.jitter_peaks_found, ref_stats.jitter_peaks_found); - ASSERT_EQ(stats.packet_loss_rate, ref_stats.packet_loss_rate); - ASSERT_EQ(stats.packet_discard_rate, ref_stats.packet_discard_rate); - ASSERT_EQ(stats.expand_rate, ref_stats.expand_rate); - ASSERT_EQ(stats.preemptive_rate, ref_stats.preemptive_rate); - ASSERT_EQ(stats.accelerate_rate, ref_stats.accelerate_rate); - ASSERT_EQ(stats.clockdrift_ppm, ref_stats.clockdrift_ppm); - ASSERT_EQ(stats.added_zero_samples, - static_cast<size_t>(ref_stats.added_zero_samples)); - ASSERT_EQ(stats.secondary_decoded_rate, 0); - ASSERT_LE(stats.speech_expand_rate, ref_stats.expand_rate); - } +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!input_fp_) + return; + + std::string stats_string; + ReadMessage(input_fp_, &stats_string); + neteq_unittest::NetEqNetworkStatistics ref_stats; + ASSERT_TRUE(ref_stats.ParseFromString(stats_string)); + + // Compare + ASSERT_EQ(stats.current_buffer_size_ms, ref_stats.current_buffer_size_ms()); + ASSERT_EQ(stats.preferred_buffer_size_ms, + ref_stats.preferred_buffer_size_ms()); + ASSERT_EQ(stats.jitter_peaks_found, ref_stats.jitter_peaks_found()); + ASSERT_EQ(stats.packet_loss_rate, ref_stats.packet_loss_rate()); + ASSERT_EQ(stats.packet_discard_rate, ref_stats.packet_discard_rate()); + ASSERT_EQ(stats.expand_rate, ref_stats.expand_rate()); + ASSERT_EQ(stats.preemptive_rate, ref_stats.preemptive_rate()); + ASSERT_EQ(stats.accelerate_rate, ref_stats.accelerate_rate()); + ASSERT_EQ(stats.clockdrift_ppm, ref_stats.clockdrift_ppm()); + ASSERT_EQ(stats.added_zero_samples, ref_stats.added_zero_samples()); + ASSERT_EQ(stats.secondary_decoded_rate, ref_stats.secondary_decoded_rate()); + ASSERT_LE(stats.speech_expand_rate, ref_stats.expand_rate()); +#else + FAIL() << "Reading from reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } -void RefFiles::WriteToFile(const RtcpStatistics& stats) { - if (output_fp_) { - ASSERT_EQ(1u, fwrite(&(stats.fraction_lost), sizeof(stats.fraction_lost), 1, - output_fp_)); - ASSERT_EQ(1u, fwrite(&(stats.cumulative_lost), - sizeof(stats.cumulative_lost), 1, output_fp_)); - ASSERT_EQ(1u, fwrite(&(stats.extended_max_sequence_number), - sizeof(stats.extended_max_sequence_number), 1, - output_fp_)); - ASSERT_EQ(1u, fwrite(&(stats.jitter), sizeof(stats.jitter), 1, - output_fp_)); - } +void RefFiles::WriteToFile(const RtcpStatistics& stats_raw) { +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!output_fp_) + return; + neteq_unittest::RtcpStatistics stats; + Convert(stats_raw, &stats); + + std::string stats_string; + ASSERT_TRUE(stats.SerializeToString(&stats_string)); + WriteMessage(output_fp_, stats_string); +#else + FAIL() << "Writing to reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } -void RefFiles::ReadFromFileAndCompare( - const RtcpStatistics& stats) { - if (input_fp_) { - // Read from ref file. - RtcpStatistics ref_stats; - ASSERT_EQ(1u, fread(&(ref_stats.fraction_lost), - sizeof(ref_stats.fraction_lost), 1, input_fp_)); - ASSERT_EQ(1u, fread(&(ref_stats.cumulative_lost), - sizeof(ref_stats.cumulative_lost), 1, input_fp_)); - ASSERT_EQ(1u, fread(&(ref_stats.extended_max_sequence_number), - sizeof(ref_stats.extended_max_sequence_number), 1, - input_fp_)); - ASSERT_EQ(1u, fread(&(ref_stats.jitter), sizeof(ref_stats.jitter), 1, - input_fp_)); - // Compare - ASSERT_EQ(ref_stats.fraction_lost, stats.fraction_lost); - ASSERT_EQ(ref_stats.cumulative_lost, stats.cumulative_lost); - ASSERT_EQ(ref_stats.extended_max_sequence_number, - stats.extended_max_sequence_number); - ASSERT_EQ(ref_stats.jitter, stats.jitter); - } +void RefFiles::ReadFromFileAndCompare(const RtcpStatistics& stats) { +#ifdef WEBRTC_NETEQ_UNITTEST_BITEXACT + if (!input_fp_) + return; + std::string stats_string; + ReadMessage(input_fp_, &stats_string); + neteq_unittest::RtcpStatistics ref_stats; + ASSERT_TRUE(ref_stats.ParseFromString(stats_string)); + + // Compare + ASSERT_EQ(stats.fraction_lost, ref_stats.fraction_lost()); + ASSERT_EQ(stats.cumulative_lost, ref_stats.cumulative_lost()); + ASSERT_EQ(stats.extended_max_sequence_number, + ref_stats.extended_max_sequence_number()); + ASSERT_EQ(stats.jitter, ref_stats.jitter()); +#else + FAIL() << "Reading from reference file requires Proto Buffer."; +#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT } class NetEqDecodingTest : public ::testing::Test { @@ -224,7 +278,8 @@ class NetEqDecodingTest : public ::testing::Test { static const size_t kBlockSize8kHz = kTimeStepMs * 8; static const size_t kBlockSize16kHz = kTimeStepMs * 16; static const size_t kBlockSize32kHz = kTimeStepMs * 32; - static const size_t kMaxBlockSize = kBlockSize32kHz; + static const size_t kBlockSize48kHz = kTimeStepMs * 48; + static const size_t kMaxBlockSize = kBlockSize48kHz; static const int kInitSampleRateHz = 8000; NetEqDecodingTest(); @@ -234,10 +289,12 @@ class NetEqDecodingTest : public ::testing::Test { void LoadDecoders(); void OpenInputFile(const std::string &rtp_file); void Process(size_t* out_len); + void DecodeAndCompare(const std::string& rtp_file, const std::string& ref_file, const std::string& stat_ref_file, const std::string& rtcp_ref_file); + static void PopulateRtpInfo(int frame_index, int timestamp, WebRtcRTPHeader* rtp_info); @@ -304,32 +361,45 @@ void NetEqDecodingTest::TearDown() { void NetEqDecodingTest::LoadDecoders() { // Load PCMu. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMu, 0)); + ASSERT_EQ(0, + neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMu, "pcmu", 0)); // Load PCMa. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMa, 8)); + ASSERT_EQ(0, + neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMa, "pcma", 8)); #ifdef WEBRTC_CODEC_ILBC // Load iLBC. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderILBC, 102)); + ASSERT_EQ( + 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderILBC, "ilbc", 102)); #endif #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) // Load iSAC. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, 103)); + ASSERT_EQ( + 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, "isac", 103)); #endif #ifdef WEBRTC_CODEC_ISAC // Load iSAC SWB. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISACswb, 104)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISACswb, + "isac-swb", 104)); +#endif +#ifdef WEBRTC_CODEC_OPUS + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderOpus, + "opus", 111)); #endif // Load PCM16B nb. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16B, 93)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16B, + "pcm16-nb", 93)); // Load PCM16B wb. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bwb, 94)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bwb, + "pcm16-wb", 94)); // Load PCM16B swb32. - ASSERT_EQ( - 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bswb32kHz, 95)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bswb32kHz, + "pcm16-swb32", 95)); // Load CNG 8 kHz. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGnb, 13)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGnb, + "cng-nb", 13)); // Load CNG 16 kHz. - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGwb, 98)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGwb, + "cng-wb", 98)); } void NetEqDecodingTest::OpenInputFile(const std::string &rtp_file) { @@ -343,10 +413,11 @@ void NetEqDecodingTest::Process(size_t* out_len) { WebRtcRTPHeader rtp_header; packet_->ConvertHeader(&rtp_header); ASSERT_EQ(0, neteq_->InsertPacket( - rtp_header, packet_->payload(), - packet_->payload_length_bytes(), - static_cast<uint32_t>( - packet_->time_ms() * (output_sample_rate_ / 1000)))); + rtp_header, + rtc::ArrayView<const uint8_t>( + packet_->payload(), packet_->payload_length_bytes()), + static_cast<uint32_t>(packet_->time_ms() * + (output_sample_rate_ / 1000)))); } // Get next packet. packet_.reset(rtp_source_->NextPacket()); @@ -354,13 +425,15 @@ void NetEqDecodingTest::Process(size_t* out_len) { // Get audio from NetEq. NetEqOutputType type; - int num_channels; + size_t num_channels; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, out_len, &num_channels, &type)); ASSERT_TRUE((*out_len == kBlockSize8kHz) || (*out_len == kBlockSize16kHz) || - (*out_len == kBlockSize32kHz)); + (*out_len == kBlockSize32kHz) || + (*out_len == kBlockSize48kHz)); output_sample_rate_ = static_cast<int>(*out_len / 10 * 1000); + EXPECT_EQ(output_sample_rate_, neteq_->last_output_sample_rate_hz()); // Increase time. sim_clock_ += kTimeStepMs; @@ -442,17 +515,17 @@ void NetEqDecodingTest::PopulateCng(int frame_index, *payload_len = 1; // Only noise level, no spectral parameters. } -#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISAC)) && \ +#if !defined(WEBRTC_IOS) && !defined(WEBRTC_ANDROID) && \ + defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && \ + (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \ defined(WEBRTC_CODEC_ILBC) && defined(WEBRTC_CODEC_G722) -#define IF_ALL_CODECS(x) x +#define MAYBE_TestBitExactness TestBitExactness #else -#define IF_ALL_CODECS(x) DISABLED_##x +#define MAYBE_TestBitExactness DISABLED_TestBitExactness #endif - -TEST_F(NetEqDecodingTest, - DISABLED_ON_IOS(DISABLED_ON_ANDROID(IF_ALL_CODECS(TestBitExactness)))) { - const std::string input_rtp_file = webrtc::test::ProjectRootPath() + - "resources/audio_coding/neteq_universal_new.rtp"; +TEST_F(NetEqDecodingTest, MAYBE_TestBitExactness) { + const std::string input_rtp_file = + webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"); // Note that neteq4_universal_ref.pcm and neteq4_universal_ref_win_32.pcm // are identical. The latter could have been removed, but if clients still // have a copy of the file, the test will fail. @@ -480,6 +553,34 @@ TEST_F(NetEqDecodingTest, } } +#if !defined(WEBRTC_IOS) && !defined(WEBRTC_ANDROID) && \ + defined(WEBRTC_NETEQ_UNITTEST_BITEXACT) && \ + defined(WEBRTC_CODEC_OPUS) +#define MAYBE_TestOpusBitExactness TestOpusBitExactness +#else +#define MAYBE_TestOpusBitExactness DISABLED_TestOpusBitExactness +#endif +TEST_F(NetEqDecodingTest, MAYBE_TestOpusBitExactness) { + const std::string input_rtp_file = + webrtc::test::ResourcePath("audio_coding/neteq_opus", "rtp"); + const std::string input_ref_file = + webrtc::test::ResourcePath("audio_coding/neteq4_opus_ref", "pcm"); + const std::string network_stat_ref_file = + webrtc::test::ResourcePath("audio_coding/neteq4_opus_network_stats", + "dat"); + const std::string rtcp_stat_ref_file = + webrtc::test::ResourcePath("audio_coding/neteq4_opus_rtcp_stats", "dat"); + + if (FLAGS_gen_ref) { + DecodeAndCompare(input_rtp_file, "", "", ""); + } else { + DecodeAndCompare(input_rtp_file, + input_ref_file, + network_stat_ref_file, + rtcp_stat_ref_file); + } +} + // Use fax mode to avoid time-scaling. This is to simplify the testing of // packet waiting times in the packet buffer. class NetEqDecodingTestFaxMode : public NetEqDecodingTest { @@ -495,22 +596,19 @@ TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) { const size_t kSamples = 10 * 16; const size_t kPayloadBytes = kSamples * 2; for (size_t i = 0; i < num_frames; ++i) { - uint16_t payload[kSamples] = {0}; + const uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; rtp_info.header.sequenceNumber = i; rtp_info.header.timestamp = i * kSamples; rtp_info.header.ssrc = 0x1234; // Just an arbitrary SSRC. rtp_info.header.payloadType = 94; // PCM16b WB codec. rtp_info.header.markerBit = 0; - ASSERT_EQ(0, neteq_->InsertPacket( - rtp_info, - reinterpret_cast<uint8_t*>(payload), - kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); } // Pull out all data. for (size_t i = 0; i < num_frames; ++i) { size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -549,13 +647,13 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimeNegative) { uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++frame_index; } // Pull out data once. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -580,13 +678,13 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimePositive) { uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(frame_index, frame_index * kSamples, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++frame_index; } // Pull out data once. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -611,7 +709,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, double next_input_time_ms = 0.0; double t_ms; size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; // Insert speech for 5 seconds. @@ -623,7 +721,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; next_input_time_ms += static_cast<double>(kFrameSizeMs) * drift_factor; @@ -649,7 +747,9 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, size_t payload_len; WebRtcRTPHeader rtp_info; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ(0, neteq_->InsertPacket( + rtp_info, + rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); ++seq_no; timestamp += kCngPeriodSamples; next_input_time_ms += static_cast<double>(kCngPeriodMs) * drift_factor; @@ -696,7 +796,9 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, size_t payload_len; WebRtcRTPHeader rtp_info; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ(0, neteq_->InsertPacket( + rtp_info, + rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); ++seq_no; timestamp += kCngPeriodSamples; next_input_time_ms += kCngPeriodMs * drift_factor; @@ -712,7 +814,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; next_input_time_ms += kFrameSizeMs * drift_factor; @@ -823,31 +925,30 @@ TEST_F(NetEqDecodingTest, UnknownPayloadType) { WebRtcRTPHeader rtp_info; PopulateRtpInfo(0, 0, &rtp_info); rtp_info.header.payloadType = 1; // Not registered as a decoder. - EXPECT_EQ(NetEq::kFail, - neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + EXPECT_EQ(NetEq::kFail, neteq_->InsertPacket(rtp_info, payload, 0)); EXPECT_EQ(NetEq::kUnknownRtpPayloadType, neteq_->LastError()); } -#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) -#define IF_ISAC(x) x +#if defined(WEBRTC_ANDROID) +#define MAYBE_DecoderError DISABLED_DecoderError #else -#define IF_ISAC(x) DISABLED_##x +#define MAYBE_DecoderError DecoderError #endif - -TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(IF_ISAC(DecoderError))) { +#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) +TEST_F(NetEqDecodingTest, MAYBE_DecoderError) { const size_t kPayloadBytes = 100; uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; PopulateRtpInfo(0, 0, &rtp_info); rtp_info.header.payloadType = 103; // iSAC, but the payload is invalid. - EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); NetEqOutputType type; // Set all of |out_data_| to 1, and verify that it was set to 0 by the call // to GetAudio. for (size_t i = 0; i < kMaxBlockSize; ++i) { out_data_[i] = 1; } - int num_channels; + size_t num_channels; size_t samples_per_channel; EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(kMaxBlockSize, out_data_, @@ -872,6 +973,7 @@ TEST_F(NetEqDecodingTest, DISABLED_ON_ANDROID(IF_ISAC(DecoderError))) { EXPECT_EQ(1, out_data_[i]); } } +#endif TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { NetEqOutputType type; @@ -880,7 +982,7 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { for (size_t i = 0; i < kMaxBlockSize; ++i) { out_data_[i] = 1; } - int num_channels; + size_t num_channels; size_t samples_per_channel; EXPECT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &samples_per_channel, @@ -894,6 +996,8 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { SCOPED_TRACE(ss.str()); // Print out the parameter values on failure. EXPECT_EQ(0, out_data_[i]); } + // Verify that the sample rate did not change from the initial configuration. + EXPECT_EQ(config_.sample_rate_hz, neteq_->last_output_sample_rate_hz()); } class NetEqBgnTest : public NetEqDecodingTest { @@ -934,27 +1038,29 @@ class NetEqBgnTest : public NetEqDecodingTest { PopulateRtpInfo(0, 0, &rtp_info); rtp_info.header.payloadType = payload_type; - int number_channels = 0; + size_t number_channels = 0; size_t samples_per_channel = 0; uint32_t receive_timestamp = 0; for (int n = 0; n < 10; ++n) { // Insert few packets and get audio. - size_t enc_len_bytes = WebRtcPcm16b_Encode( - input.GetNextBlock(), expected_samples_per_channel, payload); + auto block = input.GetNextBlock(); + ASSERT_EQ(expected_samples_per_channel, block.size()); + size_t enc_len_bytes = + WebRtcPcm16b_Encode(block.data(), block.size(), payload); ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2); number_channels = 0; samples_per_channel = 0; - ASSERT_EQ(0, - neteq_->InsertPacket(rtp_info, payload, enc_len_bytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>( + payload, enc_len_bytes), + receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize32kHz, output, &samples_per_channel, &number_channels, &type)); - ASSERT_EQ(1, number_channels); + ASSERT_EQ(1u, number_channels); ASSERT_EQ(expected_samples_per_channel, samples_per_channel); ASSERT_EQ(kOutputNormal, type); @@ -976,7 +1082,7 @@ class NetEqBgnTest : public NetEqDecodingTest { &samples_per_channel, &number_channels, &type)); - ASSERT_EQ(1, number_channels); + ASSERT_EQ(1u, number_channels); ASSERT_EQ(expected_samples_per_channel, samples_per_channel); // To be able to test the fading of background noise we need at lease to @@ -997,7 +1103,7 @@ class NetEqBgnTest : public NetEqDecodingTest { &samples_per_channel, &number_channels, &type)); - ASSERT_EQ(1, number_channels); + ASSERT_EQ(1u, number_channels); ASSERT_EQ(expected_samples_per_channel, samples_per_channel); if (type == kOutputPLCtoCNG) { plc_to_cng = true; @@ -1065,7 +1171,8 @@ TEST_F(NetEqBgnTestFade, RunTest) { CheckBgn(32000); } -TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { +#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) +TEST_F(NetEqDecodingTest, SyncPacketInsert) { WebRtcRTPHeader rtp_info; uint32_t receive_timestamp = 0; // For the readability use the following payloads instead of the defaults of @@ -1081,20 +1188,20 @@ TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { // Register decoders. ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bwb, - kPcm16WbPayloadType)); + "pcm16-wb", kPcm16WbPayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGnb, - kCngNbPayloadType)); + "cng-nb", kCngNbPayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGwb, - kCngWbPayloadType)); + "cng-wb", kCngWbPayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGswb32kHz, - kCngSwb32PayloadType)); + "cng-swb32", kCngSwb32PayloadType)); ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGswb48kHz, - kCngSwb48PayloadType)); - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderAVT, + "cng-swb48", kCngSwb48PayloadType)); + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderAVT, "avt", kAvtPayloadType)); - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderRED, + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderRED, "red", kRedPayloadType)); - ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, + ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, "isac", kIsacPayloadType)); PopulateRtpInfo(0, 0, &rtp_info); @@ -1106,8 +1213,7 @@ TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { // Payload length of 10 ms PCM16 16 kHz. const size_t kPayloadBytes = kBlockSize16kHz * sizeof(int16_t); uint8_t payload[kPayloadBytes] = {0}; - ASSERT_EQ(0, neteq_->InsertPacket( - rtp_info, payload, kPayloadBytes, receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); // Next packet. Last packet contained 10 ms audio. rtp_info.header.sequenceNumber++; @@ -1145,6 +1251,7 @@ TEST_F(NetEqDecodingTest, IF_ISAC(SyncPacketInsert)) { --rtp_info.header.ssrc; EXPECT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp)); } +#endif // First insert several noise like packets, then sync-packets. Decoding all // packets should not produce error, statistics should not show any packet loss @@ -1165,17 +1272,16 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { // Insert some packets which decode to noise. We are not interested in // actual decoded values. NetEqOutputType output_type; - int num_channels; + size_t num_channels; size_t samples_per_channel; uint32_t receive_timestamp = 0; for (int n = 0; n < 100; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; @@ -1193,7 +1299,7 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); if (n > algorithmic_frame_delay) { EXPECT_TRUE(IsAllZero(decoded, samples_per_channel * num_channels)); } @@ -1205,8 +1311,7 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { // We insert regular packets, if sync packet are not correctly buffered then // network statistics would show some packet loss. for (int n = 0; n <= algorithmic_frame_delay + 10; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, &samples_per_channel, &num_channels, &output_type)); @@ -1243,18 +1348,17 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { // Insert some packets which decode to noise. We are not interested in // actual decoded values. NetEqOutputType output_type; - int num_channels; + size_t num_channels; size_t samples_per_channel; uint32_t receive_timestamp = 0; int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1; for (int n = 0; n < algorithmic_frame_delay; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ASSERT_EQ(0, neteq_->GetAudio(kBlockSize16kHz, decoded, &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; receive_timestamp += kBlockSize16kHz; @@ -1281,8 +1385,7 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { // Insert. for (int n = 0; n < kNumSyncPackets; ++n) { - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); rtp_info.header.sequenceNumber++; rtp_info.header.timestamp += kBlockSize16kHz; receive_timestamp += kBlockSize16kHz; @@ -1294,7 +1397,7 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); EXPECT_TRUE(IsAllNonZero(decoded, samples_per_channel * num_channels)); } } @@ -1312,7 +1415,7 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, const size_t kPayloadBytes = kSamples * sizeof(int16_t); double next_input_time_ms = 0.0; int16_t decoded[kBlockSize16kHz]; - int num_channels; + size_t num_channels; size_t samples_per_channel; NetEqOutputType output_type; uint32_t receive_timestamp = 0; @@ -1334,8 +1437,7 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, if (drop_seq_numbers.find(seq_no) == drop_seq_numbers.end()) { // This sequence number was not in the set to drop. Insert it. ASSERT_EQ(0, - neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, - receive_timestamp)); + neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); ++packets_inserted; } NetEqNetworkStatistics network_stats; @@ -1366,7 +1468,7 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, &samples_per_channel, &num_channels, &output_type)); ASSERT_EQ(kBlockSize16kHz, samples_per_channel); - ASSERT_EQ(1, num_channels); + ASSERT_EQ(1u, num_channels); // Expect delay (in samples) to be less than 2 packets. EXPECT_LE(timestamp - PlayoutTimestamp(), @@ -1417,13 +1519,13 @@ void NetEqDecodingTest::DuplicateCng() { // Insert three speech packets. Three are needed to get the frame length // correct. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; uint8_t payload[kPayloadBytes] = {0}; WebRtcRTPHeader rtp_info; for (int i = 0; i < 3; ++i) { PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; @@ -1442,7 +1544,9 @@ void NetEqDecodingTest::DuplicateCng() { size_t payload_len; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); // This is the first time this CNG packet is inserted. - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ( + 0, neteq_->InsertPacket( + rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); // Pull audio once and make sure CNG is played. ASSERT_EQ(0, @@ -1454,7 +1558,9 @@ void NetEqDecodingTest::DuplicateCng() { // Insert the same CNG packet again. Note that at this point it is old, since // we have already decoded the first copy of it. - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ( + 0, neteq_->InsertPacket( + rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); // Pull audio until we have played |kCngPeriodMs| of CNG. Start at 10 ms since // we have already pulled out CNG once. @@ -1472,7 +1578,7 @@ void NetEqDecodingTest::DuplicateCng() { ++seq_no; timestamp += kCngPeriodSamples; PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); // Pull audio once and verify that the output is speech again. ASSERT_EQ(0, @@ -1507,14 +1613,16 @@ TEST_F(NetEqDecodingTest, CngFirst) { WebRtcRTPHeader rtp_info; PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len); - ASSERT_EQ(NetEq::kOK, - neteq_->InsertPacket(rtp_info, payload, payload_len, 0)); + ASSERT_EQ( + NetEq::kOK, + neteq_->InsertPacket( + rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); ++seq_no; timestamp += kCngPeriodSamples; // Pull audio once and make sure CNG is played. size_t out_len; - int num_channels; + size_t num_channels; NetEqOutputType type; ASSERT_EQ(0, neteq_->GetAudio(kMaxBlockSize, out_data_, &out_len, &num_channels, &type)); @@ -1524,7 +1632,7 @@ TEST_F(NetEqDecodingTest, CngFirst) { // Insert some speech packets. for (int i = 0; i < 3; ++i) { PopulateRtpInfo(seq_no, timestamp, &rtp_info); - ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, kPayloadBytes, 0)); + ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); ++seq_no; timestamp += kSamples; diff --git a/webrtc/modules/audio_coding/neteq/neteq_unittest.proto b/webrtc/modules/audio_coding/neteq/neteq_unittest.proto new file mode 100644 index 0000000000..4b59848eb2 --- /dev/null +++ b/webrtc/modules/audio_coding/neteq/neteq_unittest.proto @@ -0,0 +1,29 @@ +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +package webrtc.neteq_unittest; + +message NetEqNetworkStatistics { + optional uint32 current_buffer_size_ms = 1; + optional uint32 preferred_buffer_size_ms = 2; + optional uint32 jitter_peaks_found = 3; + optional uint32 packet_loss_rate = 4; + optional uint32 packet_discard_rate = 5; + optional uint32 expand_rate = 6; + optional uint32 speech_expand_rate = 7; + optional uint32 preemptive_rate = 8; + optional uint32 accelerate_rate = 9; + optional uint32 secondary_decoded_rate = 10; + optional int32 clockdrift_ppm = 11; + optional uint64 added_zero_samples = 12; + optional int32 mean_waiting_time_ms = 13; + optional int32 median_waiting_time_ms = 14; + optional int32 min_waiting_time_ms = 15; + optional int32 max_waiting_time_ms = 16; +} + +message RtcpStatistics { + optional uint32 fraction_lost = 1; + optional uint32 cumulative_lost = 2; + optional uint32 extended_max_sequence_number = 3; + optional uint32 jitter = 4; +}
\ No newline at end of file diff --git a/webrtc/modules/audio_coding/neteq/normal.cc b/webrtc/modules/audio_coding/neteq/normal.cc index ebecbf94bd..1b888f70d1 100644 --- a/webrtc/modules/audio_coding/neteq/normal.cc +++ b/webrtc/modules/audio_coding/neteq/normal.cc @@ -16,7 +16,7 @@ #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" -#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h" +#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" #include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h" #include "webrtc/modules/audio_coding/neteq/background_noise.h" #include "webrtc/modules/audio_coding/neteq/decoder_database.h" diff --git a/webrtc/modules/audio_coding/neteq/packet.h b/webrtc/modules/audio_coding/neteq/packet.h index 723ed8b0a3..64b325e027 100644 --- a/webrtc/modules/audio_coding/neteq/packet.h +++ b/webrtc/modules/audio_coding/neteq/packet.h @@ -13,7 +13,7 @@ #include <list> -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc b/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc index bf26a8f517..07c4bac0b6 100644 --- a/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/payload_splitter_unittest.cc @@ -310,10 +310,10 @@ TEST(RedPayloadSplitter, CheckRedPayloads) { // easier to just register the payload types and let the actual implementation // do its job. DecoderDatabase decoder_database; - decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderCNGnb); - decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu); - decoder_database.RegisterPayload(2, NetEqDecoder::kDecoderAVT); - decoder_database.RegisterPayload(3, NetEqDecoder::kDecoderILBC); + decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderCNGnb, "cng-nb"); + decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu"); + decoder_database.RegisterPayload(2, NetEqDecoder::kDecoderAVT, "avt"); + decoder_database.RegisterPayload(3, NetEqDecoder::kDecoderILBC, "ilbc"); PayloadSplitter splitter; splitter.CheckRedPayloads(&packet_list, decoder_database); @@ -745,8 +745,8 @@ TEST(FecPayloadSplitter, MixedPayload) { PacketList packet_list; DecoderDatabase decoder_database; - decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderOpus); - decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu); + decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderOpus, "opus"); + decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu"); Packet* packet = CreatePacket(0, 10, 0xFF, true); packet_list.push_back(packet); @@ -802,7 +802,7 @@ TEST(FecPayloadSplitter, EmbedFecInRed) { const int kTimestampOffset = 20 * 48; // 20 ms * 48 kHz. uint8_t payload_types[] = {0, 0}; - decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderOpus); + decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderOpus, "opus"); Packet* packet = CreateRedPayload(2, payload_types, kTimestampOffset, true); packet_list.push_back(packet); diff --git a/webrtc/modules/audio_coding/neteq/rtcp.cc b/webrtc/modules/audio_coding/neteq/rtcp.cc index cf8e0280bb..7ef40bc814 100644 --- a/webrtc/modules/audio_coding/neteq/rtcp.cc +++ b/webrtc/modules/audio_coding/neteq/rtcp.cc @@ -15,7 +15,7 @@ #include <algorithm> #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/statistics_calculator.cc b/webrtc/modules/audio_coding/neteq/statistics_calculator.cc index e6a6fbf705..8f873762c5 100644 --- a/webrtc/modules/audio_coding/neteq/statistics_calculator.cc +++ b/webrtc/modules/audio_coding/neteq/statistics_calculator.cc @@ -50,7 +50,7 @@ void StatisticsCalculator::PeriodicUmaLogger::AdvanceClock(int step_ms) { } void StatisticsCalculator::PeriodicUmaLogger::LogToUma(int value) const { - RTC_HISTOGRAM_COUNTS(uma_name_, value, 1, max_value_, 50); + RTC_HISTOGRAM_COUNTS_SPARSE(uma_name_, value, 1, max_value_, 50); } StatisticsCalculator::PeriodicUmaCount::PeriodicUmaCount( @@ -187,9 +187,9 @@ void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) { } void StatisticsCalculator::LogDelayedPacketOutageEvent(int outage_duration_ms) { - RTC_HISTOGRAM_COUNTS("WebRTC.Audio.DelayedPacketOutageEventMs", - outage_duration_ms, 1 /* min */, 2000 /* max */, - 100 /* bucket count */); + RTC_HISTOGRAM_COUNTS_SPARSE("WebRTC.Audio.DelayedPacketOutageEventMs", + outage_duration_ms, 1 /* min */, 2000 /* max */, + 100 /* bucket count */); delayed_packet_outage_counter_.RegisterSample(); } diff --git a/webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h b/webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h index 3fbce8be5c..56ed72fcee 100644 --- a/webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h +++ b/webrtc/modules/audio_coding/neteq/test/NETEQTEST_RTPpacket.h @@ -14,7 +14,7 @@ #include <map> #include <stdio.h> #include "webrtc/typedefs.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" enum stereoModes { stereoModeMono, diff --git a/webrtc/modules/audio_coding/neteq/test/PayloadTypes.h b/webrtc/modules/audio_coding/neteq/test/PayloadTypes.h index c46a3daece..aba525b162 100644 --- a/webrtc/modules/audio_coding/neteq/test/PayloadTypes.h +++ b/webrtc/modules/audio_coding/neteq/test/PayloadTypes.h @@ -39,7 +39,7 @@ #define NETEQ_CODEC_G722_1_16_PT 108 #define NETEQ_CODEC_G722_1_24_PT 109 #define NETEQ_CODEC_G722_1_32_PT 110 -#define NETEQ_CODEC_SC3_PT 111 +#define NETEQ_CODEC_OPUS_PT 111 #define NETEQ_CODEC_AMR_PT 112 #define NETEQ_CODEC_GSMEFR_PT 113 //#define NETEQ_CODEC_ILBCRCU_PT 114 diff --git a/webrtc/modules/audio_coding/neteq/test/RTPencode.cc b/webrtc/modules/audio_coding/neteq/test/RTPencode.cc index cbb7436152..45586ee111 100644 --- a/webrtc/modules/audio_coding/neteq/test/RTPencode.cc +++ b/webrtc/modules/audio_coding/neteq/test/RTPencode.cc @@ -25,7 +25,9 @@ #include <algorithm> +#include "webrtc/base/checks.h" #include "webrtc/typedefs.h" + // needed for NetEqDecoder #include "webrtc/modules/audio_coding/neteq/audio_decoder_impl.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" @@ -36,6 +38,10 @@ #include "PayloadTypes.h" +namespace { +const size_t kRtpDataSize = 8000; +} + /*********************/ /* Misc. definitions */ /*********************/ @@ -126,10 +132,10 @@ void stereoInterleave(unsigned char* data, size_t dataLen, size_t stride); #include "webrtc_vad.h" #if ((defined CODEC_PCM16B) || (defined NETEQ_ARBITRARY_CODEC)) -#include "pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #endif #ifdef CODEC_G711 -#include "g711_interface.h" +#include "webrtc/modules/audio_coding/codecs/g711/g711_interface.h" #endif #ifdef CODEC_G729 #include "G729Interface.h" @@ -146,19 +152,19 @@ void stereoInterleave(unsigned char* data, size_t dataLen, size_t stride); #include "AMRWBCreation.h" #endif #ifdef CODEC_ILBC -#include "ilbc.h" +#include "webrtc/modules/audio_coding/codecs/ilbc/ilbc.h" #endif #if (defined CODEC_ISAC || defined CODEC_ISAC_SWB) -#include "isac.h" +#include "webrtc/modules/audio_coding/codecs/isac/main/include/isac.h" #endif #ifdef NETEQ_ISACFIX_CODEC -#include "isacfix.h" +#include "webrtc/modules/audio_coding/codecs/isac/fix/include/isacfix.h" #ifdef CODEC_ISAC #error Cannot have both ISAC and ISACfix defined. Please de-select one. #endif #endif #ifdef CODEC_G722 -#include "g722_interface.h" +#include "webrtc/modules/audio_coding/codecs/g722/g722_interface.h" #endif #ifdef CODEC_G722_1_24 #include "G722_1Interface.h" @@ -188,11 +194,14 @@ void stereoInterleave(unsigned char* data, size_t dataLen, size_t stride); #endif #if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \ defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48)) -#include "webrtc_cng.h" +#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h" #endif #if ((defined CODEC_SPEEX_8) || (defined CODEC_SPEEX_16)) #include "SpeexInterface.h" #endif +#ifdef CODEC_OPUS +#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" +#endif /***********************************/ /* Global codec instance variables */ @@ -264,6 +273,9 @@ SPEEX_encinst_t* SPEEX8enc_inst[2]; #ifdef CODEC_SPEEX_16 SPEEX_encinst_t* SPEEX16enc_inst[2]; #endif +#ifdef CODEC_OPUS +OpusEncInst* opus_inst[2]; +#endif int main(int argc, char* argv[]) { size_t packet_size; @@ -275,7 +287,7 @@ int main(int argc, char* argv[]) { int useRed = 0; size_t len, enc_len; int16_t org_data[4000]; - unsigned char rtp_data[8000]; + unsigned char rtp_data[kRtpDataSize]; int16_t seqNo = 0xFFF; uint32_t ssrc = 1235412312; uint32_t timestamp = 0xAC1245; @@ -286,12 +298,12 @@ int main(int argc, char* argv[]) { uint32_t red_TS[2] = {0}; uint16_t red_len[2] = {0}; size_t RTPheaderLen = 12; - uint8_t red_data[8000]; + uint8_t red_data[kRtpDataSize]; #ifdef INSERT_OLD_PACKETS uint16_t old_length, old_plen; size_t old_enc_len; int first_old_packet = 1; - unsigned char old_rtp_data[8000]; + unsigned char old_rtp_data[kRtpDataSize]; size_t packet_age = 0; #endif #ifdef INSERT_DTMF_PACKETS @@ -429,6 +441,10 @@ int main(int argc, char* argv[]) { printf(" : red_isac Redundancy RTP packet with 2*iSAC " "frames\n"); #endif +#endif // CODEC_RED +#ifdef CODEC_OPUS + printf(" : opus Opus codec with FEC (48kHz, 32kbps, FEC" + " on and tuned for 5%% packet losses)\n"); #endif printf("\n"); @@ -880,6 +896,10 @@ void NetEQTest_GetCodec_and_PT(char* name, *PT = NETEQ_CODEC_ISAC_PT; /* this will be the PT for the sub-headers */ *fs = 16000; *useRed = 1; + } else if (!strcmp(name, "opus")) { + *codec = webrtc::NetEqDecoder::kDecoderOpus; + *PT = NETEQ_CODEC_OPUS_PT; /* this will be the PT for the sub-headers */ + *fs = 48000; } else { printf("Error: Not a supported codec (%s)\n", name); exit(0); @@ -1411,12 +1431,23 @@ int NetEQTest_init_coders(webrtc::NetEqDecoder coder, } break; #endif +#ifdef CODEC_OPUS + case webrtc::NetEqDecoder::kDecoderOpus: + ok = WebRtcOpus_EncoderCreate(&opus_inst[k], 1, 0); + if (ok != 0) { + printf("Error: Couldn't allocate memory for Opus encoding " + "instance\n"); + exit(0); + } + WebRtcOpus_EnableFec(opus_inst[k]); + WebRtcOpus_SetPacketLossRate(opus_inst[k], 5); + break; +#endif default: printf("Error: unknown codec in call to NetEQTest_init_coders.\n"); exit(0); break; } - if (ok != 0) { return (ok); } @@ -1543,6 +1574,11 @@ int NetEQTest_free_coders(webrtc::NetEqDecoder coder, size_t numChannels) { WebRtcGSMFR_FreeEnc(GSMFRenc_inst[k]); break; #endif +#ifdef CODEC_OPUS + case webrtc::NetEqDecoder::kDecoderOpus: + WebRtcOpus_EncoderFree(opus_inst[k]); + break; +#endif default: printf("Error: unknown codec in call to NetEQTest_init_coders.\n"); exit(0); @@ -1687,6 +1723,11 @@ size_t NetEQTest_encode(webrtc::NetEqDecoder coder, cdlen = static_cast<size_t>(res); } #endif +#ifdef CODEC_OPUS + cdlen = WebRtcOpus_Encode(opus_inst[k], indata, frameLen, kRtpDataSize - 12, + encoded); + RTC_CHECK_GT(cdlen, 0u); +#endif indata += frameLen; encoded += cdlen; totalLen += cdlen; diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc index 2042e0d2b8..0c09e92b4d 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_ilbc_quality_test.cc @@ -11,7 +11,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/safe_conversions.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/audio_coding/codecs/ilbc/include/audio_encoder_ilbc.h" +#include "webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h" #include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h" #include "webrtc/test/testsupport/fileutils.h" @@ -50,7 +50,7 @@ class NetEqIlbcQualityTest : public NetEqQualityTest { NetEqDecoder::kDecoderILBC) {} void SetUp() override { - ASSERT_EQ(1, channels_) << "iLBC supports only mono audio."; + ASSERT_EQ(1u, channels_) << "iLBC supports only mono audio."; AudioEncoderIlbc::Config config; config.frame_size_ms = FLAGS_frame_size_ms; encoder_.reset(new AudioEncoderIlbc(config)); @@ -66,8 +66,10 @@ class NetEqIlbcQualityTest : public NetEqQualityTest { uint32_t dummy_timestamp = 0; AudioEncoder::EncodedInfo info; do { - info = encoder_->Encode(dummy_timestamp, &in_data[encoded_samples], - kFrameSizeSamples, max_bytes, payload); + info = encoder_->Encode(dummy_timestamp, + rtc::ArrayView<const int16_t>( + in_data + encoded_samples, kFrameSizeSamples), + max_bytes, payload); encoded_samples += kFrameSizeSamples; } while (info.encoded_bytes == 0); return rtc::checked_cast<int>(info.encoded_bytes); diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc index 66b0903f66..4ccebb3e66 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_isac_quality_test.cc @@ -59,7 +59,7 @@ NetEqIsacQualityTest::NetEqIsacQualityTest() bit_rate_kbps_(FLAGS_bit_rate_kbps) {} void NetEqIsacQualityTest::SetUp() { - ASSERT_EQ(1, channels_) << "iSAC supports only mono audio."; + ASSERT_EQ(1u, channels_) << "iSAC supports only mono audio."; // Create encoder memory. WebRtcIsacfix_Create(&isac_encoder_); ASSERT_TRUE(isac_encoder_ != NULL); diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc index 5e8b2297d4..5ab55ba9e8 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_opus_quality_test.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/audio_coding/codecs/opus/include/opus_interface.h" +#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" #include "webrtc/modules/audio_coding/codecs/opus/opus_inst.h" #include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h" diff --git a/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc b/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc index 422a9fa6eb..ac478ab5ac 100644 --- a/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/test/neteq_pcmu_quality_test.cc @@ -11,7 +11,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/safe_conversions.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h" +#include "webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.h" #include "webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h" #include "webrtc/test/testsupport/fileutils.h" @@ -50,7 +50,7 @@ class NetEqPcmuQualityTest : public NetEqQualityTest { NetEqDecoder::kDecoderPCMu) {} void SetUp() override { - ASSERT_EQ(1, channels_) << "PCMu supports only mono audio."; + ASSERT_EQ(1u, channels_) << "PCMu supports only mono audio."; AudioEncoderPcmU::Config config; config.frame_size_ms = FLAGS_frame_size_ms; encoder_.reset(new AudioEncoderPcmU(config)); @@ -66,8 +66,10 @@ class NetEqPcmuQualityTest : public NetEqQualityTest { uint32_t dummy_timestamp = 0; AudioEncoder::EncodedInfo info; do { - info = encoder_->Encode(dummy_timestamp, &in_data[encoded_samples], - kFrameSizeSamples, max_bytes, payload); + info = encoder_->Encode(dummy_timestamp, + rtc::ArrayView<const int16_t>( + in_data + encoded_samples, kFrameSizeSamples), + max_bytes, payload); encoded_samples += kFrameSizeSamples; } while (info.encoded_bytes == 0); return rtc::checked_cast<int>(info.encoded_bytes); diff --git a/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc b/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc index eb69ac7889..c1abdc30f5 100644 --- a/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc +++ b/webrtc/modules/audio_coding/neteq/timestamp_scaler.cc @@ -52,19 +52,11 @@ uint32_t TimestampScaler::ToInternal(uint32_t external_timestamp, denominator_ = 1; break; } - case NetEqDecoder::kDecoderCNGswb48kHz: { - // Use timestamp scaling with factor 2/3 (32 kHz sample rate, but RTP - // timestamps run on 48 kHz). - // TODO(tlegrand): Remove scaling for kDecoderCNGswb48kHz once ACM has - // full 48 kHz support. - numerator_ = 2; - denominator_ = 3; - break; - } case NetEqDecoder::kDecoderAVT: case NetEqDecoder::kDecoderCNGnb: case NetEqDecoder::kDecoderCNGwb: - case NetEqDecoder::kDecoderCNGswb32kHz: { + case NetEqDecoder::kDecoderCNGswb32kHz: + case NetEqDecoder::kDecoderCNGswb48kHz: { // Do not change the timestamp scaling settings for DTMF or CNG. break; } @@ -87,8 +79,6 @@ uint32_t TimestampScaler::ToInternal(uint32_t external_timestamp, assert(denominator_ > 0); // Should not be possible. external_ref_ = external_timestamp; internal_ref_ += (external_diff * numerator_) / denominator_; - LOG(LS_VERBOSE) << "Converting timestamp: " << external_timestamp << - " -> " << internal_ref_; return internal_ref_; } else { // No scaling. diff --git a/webrtc/modules/audio_coding/neteq/tools/audio_loop.cc b/webrtc/modules/audio_coding/neteq/tools/audio_loop.cc index 2d2a7e3dd4..eed95753f0 100644 --- a/webrtc/modules/audio_coding/neteq/tools/audio_loop.cc +++ b/webrtc/modules/audio_coding/neteq/tools/audio_loop.cc @@ -43,13 +43,14 @@ bool AudioLoop::Init(const std::string file_name, return true; } -const int16_t* AudioLoop::GetNextBlock() { +rtc::ArrayView<const int16_t> AudioLoop::GetNextBlock() { // Check that the AudioLoop is initialized. - if (block_length_samples_ == 0) return NULL; + if (block_length_samples_ == 0) + return rtc::ArrayView<const int16_t>(); const int16_t* output_ptr = &audio_array_[next_index_]; next_index_ = (next_index_ + block_length_samples_) % loop_length_samples_; - return output_ptr; + return rtc::ArrayView<const int16_t>(output_ptr, block_length_samples_); } diff --git a/webrtc/modules/audio_coding/neteq/tools/audio_loop.h b/webrtc/modules/audio_coding/neteq/tools/audio_loop.h index a897ee5aef..14e20f68ac 100644 --- a/webrtc/modules/audio_coding/neteq/tools/audio_loop.h +++ b/webrtc/modules/audio_coding/neteq/tools/audio_loop.h @@ -13,6 +13,7 @@ #include <string> +#include "webrtc/base/array_view.h" #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/typedefs.h" @@ -40,10 +41,9 @@ class AudioLoop { bool Init(const std::string file_name, size_t max_loop_length_samples, size_t block_length_samples); - // Returns a pointer to the next block of audio. The number given as - // |block_length_samples| to the Init() function determines how many samples - // that can be safely read from the pointer. - const int16_t* GetNextBlock(); + // Returns a (pointer,size) pair for the next block of audio. The size is + // equal to the |block_length_samples| Init() argument. + rtc::ArrayView<const int16_t> GetNextBlock(); private: size_t next_index_; diff --git a/webrtc/modules/audio_coding/neteq/tools/audio_sink.h b/webrtc/modules/audio_coding/neteq/tools/audio_sink.h index 3bd2df5ca8..489a8b2ad8 100644 --- a/webrtc/modules/audio_coding/neteq/tools/audio_sink.h +++ b/webrtc/modules/audio_coding/neteq/tools/audio_sink.h @@ -12,7 +12,7 @@ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_SINK_H_ #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc b/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc index dc07030dd6..5a9f79f877 100644 --- a/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc +++ b/webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc @@ -13,7 +13,7 @@ #include <algorithm> #include "webrtc/base/checks.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "webrtc/modules/audio_coding/neteq/tools/packet.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc index 49750c26c8..694b9ed153 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc @@ -12,6 +12,7 @@ #include "webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/format_macros.h" namespace webrtc { namespace test { @@ -21,26 +22,25 @@ NetEqExternalDecoderTest::NetEqExternalDecoderTest(NetEqDecoder codec, : codec_(codec), decoder_(decoder), sample_rate_hz_(CodecSampleRateHz(codec_)), - channels_(static_cast<int>(decoder_->Channels())) { + channels_(decoder_->Channels()) { NetEq::Config config; config.sample_rate_hz = sample_rate_hz_; neteq_.reset(NetEq::Create(config)); - printf("%d\n", channels_); + printf("%" PRIuS "\n", channels_); } void NetEqExternalDecoderTest::Init() { - ASSERT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( - decoder_, codec_, kPayloadType, sample_rate_hz_)); + ASSERT_EQ(NetEq::kOK, + neteq_->RegisterExternalDecoder(decoder_, codec_, name_, + kPayloadType, sample_rate_hz_)); } -void NetEqExternalDecoderTest::InsertPacket(WebRtcRTPHeader rtp_header, - const uint8_t* payload, - size_t payload_size_bytes, - uint32_t receive_timestamp) { - ASSERT_EQ( - NetEq::kOK, - neteq_->InsertPacket( - rtp_header, payload, payload_size_bytes, receive_timestamp)); +void NetEqExternalDecoderTest::InsertPacket( + WebRtcRTPHeader rtp_header, + rtc::ArrayView<const uint8_t> payload, + uint32_t receive_timestamp) { + ASSERT_EQ(NetEq::kOK, + neteq_->InsertPacket(rtp_header, payload, receive_timestamp)); } size_t NetEqExternalDecoderTest::GetOutputAudio(size_t max_length, @@ -48,7 +48,7 @@ size_t NetEqExternalDecoderTest::GetOutputAudio(size_t max_length, NetEqOutputType* output_type) { // Get audio from regular instance. size_t samples_per_channel; - int num_channels; + size_t num_channels; EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(max_length, output, @@ -58,6 +58,7 @@ size_t NetEqExternalDecoderTest::GetOutputAudio(size_t max_length, EXPECT_EQ(channels_, num_channels); EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * sample_rate_hz_ / 1000), samples_per_channel); + EXPECT_EQ(sample_rate_hz_, neteq_->last_output_sample_rate_hz()); return samples_per_channel; } diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h index 0a41c6ec20..d7b01fe33a 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h @@ -11,10 +11,12 @@ #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_ +#include <string> + #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_coding/codecs/audio_decoder.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" namespace webrtc { namespace test { @@ -36,8 +38,8 @@ class NetEqExternalDecoderTest { // |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(WebRtcRTPHeader rtp_header, const uint8_t* payload, - size_t payload_size_bytes, + virtual void InsertPacket(WebRtcRTPHeader rtp_header, + rtc::ArrayView<const uint8_t> payload, uint32_t receive_timestamp); // Get 10 ms of audio data. The data is written to |output|, which can hold @@ -49,9 +51,10 @@ class NetEqExternalDecoderTest { private: NetEqDecoder codec_; + std::string name_ = "dummy name"; AudioDecoder* decoder_; int sample_rate_hz_; - int channels_; + size_t channels_; rtc::scoped_ptr<NetEq> neteq_; }; diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc index 9fe4dffa91..7d1f9f9798 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.cc @@ -10,7 +10,7 @@ #include "webrtc/modules/audio_coding/neteq/tools/neteq_performance_test.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" @@ -34,6 +34,7 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms, const int kSampRateHz = 32000; const webrtc::NetEqDecoder kDecoderType = webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz; + const std::string kDecoderName = "pcm16-swb32"; const int kPayloadType = 95; // Initialize NetEq instance. @@ -41,7 +42,7 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms, config.sample_rate_hz = kSampRateHz; NetEq* neteq = NetEq::Create(config); // Register decoder in |neteq|. - if (neteq->RegisterPayloadType(kDecoderType, kPayloadType) != 0) + if (neteq->RegisterPayloadType(kDecoderType, kDecoderName, kPayloadType) != 0) return -1; // Set up AudioLoop object. @@ -62,12 +63,13 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms, bool drift_flipped = false; int32_t packet_input_time_ms = rtp_gen.GetRtpHeader(kPayloadType, kInputBlockSizeSamples, &rtp_header); - const int16_t* input_samples = audio_loop.GetNextBlock(); - if (!input_samples) exit(1); + auto input_samples = audio_loop.GetNextBlock(); + if (input_samples.empty()) + exit(1); uint8_t input_payload[kInputBlockSizeSamples * sizeof(int16_t)]; - size_t payload_len = - WebRtcPcm16b_Encode(input_samples, kInputBlockSizeSamples, input_payload); - assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t)); + size_t payload_len = WebRtcPcm16b_Encode(input_samples.data(), + input_samples.size(), input_payload); + RTC_CHECK_EQ(sizeof(input_payload), payload_len); // Main loop. webrtc::Clock* clock = webrtc::Clock::GetRealTimeClock(); @@ -81,9 +83,9 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms, } if (!lost) { // Insert packet. - int error = neteq->InsertPacket( - rtp_header, input_payload, payload_len, - packet_input_time_ms * kSampRateHz / 1000); + int error = + neteq->InsertPacket(rtp_header, input_payload, + packet_input_time_ms * kSampRateHz / 1000); if (error != NetEq::kOK) return -1; } @@ -93,10 +95,10 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms, kInputBlockSizeSamples, &rtp_header); input_samples = audio_loop.GetNextBlock(); - if (!input_samples) return -1; - payload_len = WebRtcPcm16b_Encode(const_cast<int16_t*>(input_samples), - kInputBlockSizeSamples, - input_payload); + if (input_samples.empty()) + return -1; + payload_len = WebRtcPcm16b_Encode(input_samples.data(), + input_samples.size(), input_payload); assert(payload_len == kInputBlockSizeSamples * sizeof(int16_t)); } @@ -107,7 +109,7 @@ int64_t NetEqPerformanceTest::Run(int runtime_ms, static const size_t kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; int16_t out_data[kOutDataLen]; - int num_channels; + size_t num_channels; size_t samples_per_channel; int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, &num_channels, NULL); diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc index 6826d1be74..9c64e0fb48 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.cc @@ -210,7 +210,7 @@ NetEqQualityTest::NetEqQualityTest(int block_duration_ms, int out_sampling_khz, NetEqDecoder decoder_type) : decoder_type_(decoder_type), - channels_(FLAGS_channels), + channels_(static_cast<size_t>(FLAGS_channels)), decoded_time_ms_(0), decodable_time_ms_(0), drift_factor_(FLAGS_drift_factor), @@ -292,7 +292,8 @@ bool GilbertElliotLoss::Lost() { } void NetEqQualityTest::SetUp() { - ASSERT_EQ(0, neteq_->RegisterPayloadType(decoder_type_, kPayloadType)); + ASSERT_EQ(0, + neteq_->RegisterPayloadType(decoder_type_, "noname", kPayloadType)); rtp_generator_->set_drift_factor(drift_factor_); int units = block_duration_ms_ / kPacketLossTimeUnitMs; @@ -377,9 +378,10 @@ int NetEqQualityTest::Transmit() { << " ms "; if (payload_size_bytes_ > 0) { if (!PacketLost()) { - int ret = neteq_->InsertPacket(rtp_header_, &payload_[0], - payload_size_bytes_, - packet_input_time_ms * in_sampling_khz_); + int ret = neteq_->InsertPacket( + rtp_header_, + rtc::ArrayView<const uint8_t>(payload_.get(), payload_size_bytes_), + packet_input_time_ms * in_sampling_khz_); if (ret != NetEq::kOK) return -1; Log() << "was sent."; @@ -392,7 +394,7 @@ int NetEqQualityTest::Transmit() { } int NetEqQualityTest::DecodeBlock() { - int channels; + size_t channels; size_t samples; int ret = neteq_->GetAudio(out_size_samples_ * channels_, &out_data_[0], &samples, &channels, NULL); diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h index e20be5796b..c2b2effee2 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_quality_test.h @@ -99,7 +99,7 @@ class NetEqQualityTest : public ::testing::Test { std::ofstream& Log(); NetEqDecoder decoder_type_; - const int channels_; + const size_t channels_; private: int decoded_time_ms_; diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc index 0aaf8c71fd..3d79e5b5a2 100644 --- a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc +++ b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc @@ -26,7 +26,7 @@ #include "webrtc/base/checks.h" #include "webrtc/base/safe_conversions.h" #include "webrtc/base/scoped_ptr.h" -#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" +#include "webrtc/modules/audio_coding/codecs/pcm16b/pcm16b.h" #include "webrtc/modules/audio_coding/neteq/include/neteq.h" #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" #include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h" @@ -34,7 +34,7 @@ #include "webrtc/modules/audio_coding/neteq/tools/packet.h" #include "webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h" #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/system_wrappers/include/trace.h" #include "webrtc/test/rtp_file_reader.h" #include "webrtc/test/testsupport/fileutils.h" @@ -189,8 +189,9 @@ std::string CodecName(webrtc::NetEqDecoder codec) { void RegisterPayloadType(NetEq* neteq, webrtc::NetEqDecoder codec, + const std::string& name, google::int32 flag) { - if (neteq->RegisterPayloadType(codec, static_cast<uint8_t>(flag))) { + if (neteq->RegisterPayloadType(codec, name, static_cast<uint8_t>(flag))) { std::cerr << "Cannot register payload type " << flag << " as " << CodecName(codec) << std::endl; exit(1); @@ -200,30 +201,40 @@ void RegisterPayloadType(NetEq* neteq, // Registers all decoders in |neteq|. void RegisterPayloadTypes(NetEq* neteq) { assert(neteq); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCMu, FLAGS_pcmu); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCMa, FLAGS_pcma); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderILBC, FLAGS_ilbc); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderISAC, FLAGS_isac); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderISACswb, + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCMu, "pcmu", + FLAGS_pcmu); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCMa, "pcma", + FLAGS_pcma); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderILBC, "ilbc", + FLAGS_ilbc); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderISAC, "isac", + FLAGS_isac); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderISACswb, "isac-swb", FLAGS_isac_swb); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderOpus, FLAGS_opus); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCM16B, + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderOpus, "opus", + FLAGS_opus); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCM16B, "pcm16-nb", FLAGS_pcm16b); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCM16Bwb, + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb", FLAGS_pcm16b_wb); RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz, - FLAGS_pcm16b_swb32); + "pcm16-swb32", FLAGS_pcm16b_swb32); RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderPCM16Bswb48kHz, - FLAGS_pcm16b_swb48); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderG722, FLAGS_g722); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderAVT, FLAGS_avt); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderRED, FLAGS_red); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderCNGnb, FLAGS_cn_nb); - RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderCNGwb, FLAGS_cn_wb); + "pcm16-swb48", FLAGS_pcm16b_swb48); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderG722, "g722", + FLAGS_g722); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderAVT, "avt", + FLAGS_avt); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderRED, "red", + FLAGS_red); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderCNGnb, "cng-nb", + FLAGS_cn_nb); + RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderCNGwb, "cng-wb", + FLAGS_cn_wb); RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderCNGswb32kHz, - FLAGS_cn_swb32); + "cng-swb32", FLAGS_cn_swb32); RegisterPayloadType(neteq, webrtc::NetEqDecoder::kDecoderCNGswb48kHz, - FLAGS_cn_swb48); + "cng-swb48", FLAGS_cn_swb48); } void PrintCodecMappingEntry(webrtc::NetEqDecoder codec, google::int32 flag) { @@ -399,23 +410,12 @@ int main(int argc, char* argv[]) { printf("Input file: %s\n", argv[1]); - // TODO(ivoc): Modify the RtpFileSource::Create and RtcEventLogSource::Create - // functions to return a nullptr on failure instead of crashing - // the program. - - // This temporary solution uses a RtpFileReader directly to check if the file - // is a valid RtpDump file. bool is_rtp_dump = false; - { - rtc::scoped_ptr<webrtc::test::RtpFileReader> rtp_reader( - webrtc::test::RtpFileReader::Create( - webrtc::test::RtpFileReader::kRtpDump, argv[1])); - if (rtp_reader) - is_rtp_dump = true; - } rtc::scoped_ptr<webrtc::test::PacketSource> file_source; webrtc::test::RtcEventLogSource* event_log_source = nullptr; - if (is_rtp_dump) { + if (webrtc::test::RtpFileSource::ValidRtpDump(argv[1]) || + webrtc::test::RtpFileSource::ValidPcap(argv[1])) { + is_rtp_dump = true; file_source.reset(webrtc::test::RtpFileSource::Create(argv[1])); } else { event_log_source = webrtc::test::RtcEventLogSource::Create(argv[1]); @@ -558,7 +558,7 @@ int main(int argc, char* argv[]) { payload_ptr = payload.get(); } int error = neteq->InsertPacket( - rtp_header, payload_ptr, payload_len, + rtp_header, rtc::ArrayView<const uint8_t>(payload_ptr, payload_len), static_cast<uint32_t>(packet->time_ms() * sample_rate_hz / 1000)); if (error != NetEq::kOK) { if (neteq->LastError() == NetEq::kUnknownRtpPayloadType) { @@ -609,7 +609,7 @@ int main(int argc, char* argv[]) { static const size_t kOutDataLen = kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; int16_t out_data[kOutDataLen]; - int num_channels; + size_t num_channels; size_t samples_per_channel; int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, &num_channels, NULL); diff --git a/webrtc/modules/audio_coding/neteq/tools/packet.cc b/webrtc/modules/audio_coding/neteq/tools/packet.cc index b8b27afdec..2b2fcc286e 100644 --- a/webrtc/modules/audio_coding/neteq/tools/packet.cc +++ b/webrtc/modules/audio_coding/neteq/tools/packet.cc @@ -12,8 +12,8 @@ #include <string.h> -#include "webrtc/modules/interface/module_common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" +#include "webrtc/modules/include/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" namespace webrtc { namespace test { diff --git a/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.cc b/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.cc index 9b17ba8f64..dad72eaecd 100644 --- a/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.cc +++ b/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.cc @@ -18,7 +18,7 @@ #include "webrtc/base/checks.h" #include "webrtc/call/rtc_event_log.h" #include "webrtc/modules/audio_coding/neteq/tools/packet.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" // Files generated at build-time by the protobuf compiler. #ifdef WEBRTC_ANDROID_PLATFORM_BUILD diff --git a/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h b/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h index 7150bcfe89..90d5931224 100644 --- a/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h +++ b/webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h @@ -16,7 +16,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/audio_coding/neteq/tools/packet_source.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { diff --git a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc index 9681ad17ea..b7a3109c01 100644 --- a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc +++ b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.cc @@ -20,7 +20,7 @@ #include "webrtc/base/checks.h" #include "webrtc/modules/audio_coding/neteq/tools/packet.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" #include "webrtc/test/rtp_file_reader.h" namespace webrtc { @@ -32,6 +32,18 @@ RtpFileSource* RtpFileSource::Create(const std::string& file_name) { return source; } +bool RtpFileSource::ValidRtpDump(const std::string& file_name) { + rtc::scoped_ptr<RtpFileReader> temp_file( + RtpFileReader::Create(RtpFileReader::kRtpDump, file_name)); + return !!temp_file; +} + +bool RtpFileSource::ValidPcap(const std::string& file_name) { + rtc::scoped_ptr<RtpFileReader> temp_file( + RtpFileReader::Create(RtpFileReader::kPcap, file_name)); + return !!temp_file; +} + RtpFileSource::~RtpFileSource() { } diff --git a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h index d0856a819c..2febf68b91 100644 --- a/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h +++ b/webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h @@ -18,7 +18,7 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/common_types.h" #include "webrtc/modules/audio_coding/neteq/tools/packet_source.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" +#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" namespace webrtc { @@ -34,6 +34,10 @@ class RtpFileSource : public PacketSource { // opened, or has the wrong format, NULL will be returned. static RtpFileSource* Create(const std::string& file_name); + // Checks whether a files is a valid RTP dump or PCAP (Wireshark) file. + static bool ValidRtpDump(const std::string& file_name); + static bool ValidPcap(const std::string& file_name); + virtual ~RtpFileSource(); // Registers an RTP header extension and binds it to |id|. diff --git a/webrtc/modules/audio_coding/neteq/tools/rtp_generator.h b/webrtc/modules/audio_coding/neteq/tools/rtp_generator.h index 6c16192daa..53371be8f6 100644 --- a/webrtc/modules/audio_coding/neteq/tools/rtp_generator.h +++ b/webrtc/modules/audio_coding/neteq/tools/rtp_generator.h @@ -12,7 +12,7 @@ #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_RTP_GENERATOR_H_ #include "webrtc/base/constructormagic.h" -#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/include/module_common_types.h" #include "webrtc/typedefs.h" namespace webrtc { |