1. Make a clear distinction between codec internal FEC and RED, confusing mentioning of FEC in the old codes is replaced by RED
2. Add two new APIs to configure codec internal FEC
3. Add a test and listened to results. This is based modifying EncodeDecodeTest and deriving a new class from it.
New ACM gives good result.
Old ACM does not use NetEq 4, so FEC won't be decoded.
BUG=
R=tina.legrand@webrtc.org, turaj@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/11759004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6233 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/main/test/PacketLossTest.cc b/webrtc/modules/audio_coding/main/test/PacketLossTest.cc
new file mode 100644
index 0000000..e6ef392
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/test/PacketLossTest.cc
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_coding/main/test/PacketLossTest.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/common.h"
+#include "webrtc/test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+ReceiverWithPacketLoss::ReceiverWithPacketLoss()
+ : loss_rate_(0),
+ burst_length_(1),
+ packet_counter_(0),
+ lost_packet_counter_(0),
+ burst_lost_counter_(burst_length_) {
+}
+
+void ReceiverWithPacketLoss::Setup(AudioCodingModule *acm,
+ RTPStream *rtpStream,
+ std::string out_file_name,
+ int channels,
+ int loss_rate,
+ int burst_length) {
+ loss_rate_ = loss_rate;
+ burst_length_ = burst_length;
+ burst_lost_counter_ = burst_length_; // To prevent first packet gets lost.
+ std::stringstream ss;
+ ss << out_file_name << "_" << loss_rate_ << "_" << burst_length_ << "_";
+ Receiver::Setup(acm, rtpStream, ss.str(), channels);
+}
+
+bool ReceiverWithPacketLoss::IncomingPacket() {
+ if (!_rtpStream->EndOfFile()) {
+ if (packet_counter_ == 0) {
+ _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
+ _payloadSizeBytes, &_nextTime);
+ if (_realPayloadSizeBytes == 0) {
+ if (_rtpStream->EndOfFile()) {
+ packet_counter_ = 0;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ if (!PacketLost()) {
+ _acm->IncomingPacket(_incomingPayload, _realPayloadSizeBytes, _rtpInfo);
+ }
+ packet_counter_++;
+ _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
+ _payloadSizeBytes, &_nextTime);
+ if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
+ packet_counter_ = 0;
+ lost_packet_counter_ = 0;
+ }
+ }
+ return true;
+}
+
+bool ReceiverWithPacketLoss::PacketLost() {
+ if (burst_lost_counter_ < burst_length_) {
+ lost_packet_counter_++;
+ burst_lost_counter_++;
+ return true;
+ }
+
+ if (lost_packet_counter_ * 100 < loss_rate_ * packet_counter_) {
+ lost_packet_counter_++;
+ burst_lost_counter_ = 1;
+ return true;
+ }
+ return false;
+}
+
+SenderWithFEC::SenderWithFEC()
+ : expected_loss_rate_(0) {
+}
+
+void SenderWithFEC::Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+ std::string in_file_name, int sample_rate,
+ int channels, int expected_loss_rate) {
+ Sender::Setup(acm, rtpStream, in_file_name, sample_rate, channels);
+ EXPECT_TRUE(SetFEC(true));
+ EXPECT_TRUE(SetPacketLossRate(expected_loss_rate));
+}
+
+bool SenderWithFEC::SetFEC(bool enable_fec) {
+ if (_acm->SetCodecFEC(enable_fec) == 0) {
+ return true;
+ }
+ return false;
+}
+
+bool SenderWithFEC::SetPacketLossRate(int expected_loss_rate) {
+ if (_acm->SetPacketLossRate(expected_loss_rate) == 0) {
+ expected_loss_rate_ = expected_loss_rate;
+ return true;
+ }
+ return false;
+}
+
+PacketLossTest::PacketLossTest(int channels, int expected_loss_rate,
+ int actual_loss_rate, int burst_length)
+ : channels_(channels),
+ in_file_name_(channels_ == 1 ? "audio_coding/testfile32kHz" :
+ "audio_coding/teststereo32kHz"),
+ sample_rate_hz_(32000),
+ sender_(new SenderWithFEC),
+ receiver_(new ReceiverWithPacketLoss),
+ expected_loss_rate_(expected_loss_rate),
+ actual_loss_rate_(actual_loss_rate),
+ burst_length_(burst_length) {
+}
+
+void PacketLossTest::Perform() {
+#ifndef WEBRTC_CODEC_OPUS
+ return;
+#else
+ scoped_ptr<AudioCodingModule> acm(AudioCodingModule::Create(0));
+
+ int codec_id = acm->Codec("opus", 48000, channels_);
+
+ RTPFile rtpFile;
+ std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
+
+ // Encode to file
+ rtpFile.Open(fileName.c_str(), "wb+");
+ rtpFile.WriteHeader();
+
+ sender_->testMode = 0;
+ sender_->codeId = codec_id;
+
+ sender_->Setup(acm.get(), &rtpFile, in_file_name_, sample_rate_hz_, channels_,
+ expected_loss_rate_);
+ struct CodecInst sendCodecInst;
+ if (acm->SendCodec(&sendCodecInst) >= 0) {
+ sender_->Run();
+ }
+ sender_->Teardown();
+ rtpFile.Close();
+
+ // Decode to file
+ rtpFile.Open(fileName.c_str(), "rb");
+ rtpFile.ReadHeader();
+
+ receiver_->testMode = 0;
+ receiver_->codeId = codec_id;
+
+ receiver_->Setup(acm.get(), &rtpFile, "packetLoss_out", channels_,
+ actual_loss_rate_, burst_length_);
+ receiver_->Run();
+ receiver_->Teardown();
+ rtpFile.Close();
+#endif
+}
+
+} // namespace webrtc