RentACodec: New class that takes over part of ACMCodecDB's job
Following CLs will finish the takeover completely. After that,
RentACodec will also start creating and owning codecs, at which point
its name will start making sense.
BUG=webrtc:5028
Review URL: https://codereview.webrtc.org/1412683006
Cr-Commit-Position: refs/heads/master@{#10432}
diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn
index 7bbcd3a..d9a1a02 100644
--- a/webrtc/modules/audio_coding/BUILD.gn
+++ b/webrtc/modules/audio_coding/BUILD.gn
@@ -9,6 +9,39 @@
import("//build/config/arm.gni")
import("../../build/webrtc.gni")
+source_set("rent_a_codec") {
+ sources = [
+ "main/acm2/acm_codec_database.cc",
+ "main/acm2/acm_codec_database.h",
+ "main/acm2/rent_a_codec.cc",
+ "main/acm2/rent_a_codec.h",
+ ]
+ configs += [ "../..:common_config" ]
+ public_configs = [ "../..:common_inherited_config" ]
+ deps = [
+ "../..:webrtc_common",
+ ]
+
+ defines = []
+ if (rtc_include_opus) {
+ defines += [ "WEBRTC_CODEC_OPUS" ]
+ }
+ if (!build_with_mozilla) {
+ if (current_cpu == "arm") {
+ defines += [ "WEBRTC_CODEC_ISACFX" ]
+ } else {
+ defines += [ "WEBRTC_CODEC_ISAC" ]
+ }
+ defines += [ "WEBRTC_CODEC_G722" ]
+ }
+ if (!build_with_mozilla && !build_with_chromium) {
+ defines += [
+ "WEBRTC_CODEC_ILBC",
+ "WEBRTC_CODEC_RED",
+ ]
+ }
+}
+
config("audio_coding_config") {
include_dirs = [
"main/interface",
@@ -18,8 +51,6 @@
source_set("audio_coding") {
sources = [
- "main/acm2/acm_codec_database.cc",
- "main/acm2/acm_codec_database.h",
"main/acm2/acm_common_defs.h",
"main/acm2/acm_receiver.cc",
"main/acm2/acm_receiver.h",
@@ -69,6 +100,7 @@
":g711",
":neteq",
":pcm16b",
+ ":rent_a_codec",
"../..:rtc_event_log",
"../..:webrtc_common",
"../../common_audio",
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc
index bf12530..a619e82 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc
@@ -223,7 +223,7 @@
// TODO(tlegrand): replace memcpy with a pointer to the data base memory.
int ACMCodecDB::Codec(int codec_id, CodecInst* codec_inst) {
// Error check to see that codec_id is not out of bounds.
- if ((codec_id < 0) || (codec_id >= kNumCodecs)) {
+ if (static_cast<size_t>(codec_id) >= RentACodec::NumberOfCodecs()) {
return -1;
}
@@ -318,7 +318,7 @@
}
int ACMCodecDB::CodecId(const char* payload_name, int frequency, int channels) {
- for (int id = 0; id < kNumCodecs; id++) {
+ for (const CodecInst& ci : RentACodec::Database()) {
bool name_match = false;
bool frequency_match = false;
bool channels_match = false;
@@ -326,11 +326,11 @@
// Payload name, sampling frequency and number of channels need to match.
// NOTE! If |frequency| is -1, the frequency is not applicable, and is
// always treated as true, like for RED.
- name_match = (STR_CASE_CMP(database_[id].plname, payload_name) == 0);
- frequency_match = (frequency == database_[id].plfreq) || (frequency == -1);
+ name_match = (STR_CASE_CMP(ci.plname, payload_name) == 0);
+ frequency_match = (frequency == ci.plfreq) || (frequency == -1);
// The number of channels must match for all codecs but Opus.
if (STR_CASE_CMP(payload_name, "opus") != 0) {
- channels_match = (channels == database_[id].channels);
+ channels_match = (channels == ci.channels);
} else {
// For opus we just check that number of channels is valid.
channels_match = (channels == 1 || channels == 2);
@@ -338,7 +338,7 @@
if (name_match && frequency_match && channels_match) {
// We have found a matching codec in the list.
- return id;
+ return &ci - RentACodec::Database().data();
}
}
@@ -354,12 +354,9 @@
// Returns the codec sampling frequency for codec with id = "codec_id" in
// database.
int ACMCodecDB::CodecFreq(int codec_id) {
- // Error check to see that codec_id is not out of bounds.
- if (codec_id < 0 || codec_id >= kNumCodecs) {
- return -1;
- }
-
- return database_[codec_id].plfreq;
+ const size_t i = static_cast<size_t>(codec_id);
+ const auto db = RentACodec::Database();
+ return i < db.size() ? db[i].plfreq : -1;
}
// Checks if the payload type is in the valid range.
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h
index 13b3008..0913b79 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h
@@ -18,6 +18,7 @@
#include "webrtc/common_types.h"
#include "webrtc/engine_configurations.h"
+#include "webrtc/modules/audio_coding/main/acm2/rent_a_codec.h"
#include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
namespace webrtc {
@@ -27,85 +28,6 @@
// TODO(tlegrand): replace class ACMCodecDB with a namespace.
class ACMCodecDB {
public:
- // Enum with array indexes for the supported codecs. NOTE! The order MUST
- // be the same as when creating the database in acm_codec_database.cc.
- enum {
- kNone = -1
-#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
- , kISAC
-# if (defined(WEBRTC_CODEC_ISAC))
- , kISACSWB
-# endif
-#endif
- // Mono
- , kPCM16B
- , kPCM16Bwb
- , kPCM16Bswb32kHz
- // Stereo
- , kPCM16B_2ch
- , kPCM16Bwb_2ch
- , kPCM16Bswb32kHz_2ch
- // Mono
- , kPCMU
- , kPCMA
- // Stereo
- , kPCMU_2ch
- , kPCMA_2ch
-#ifdef WEBRTC_CODEC_ILBC
- , kILBC
-#endif
-#ifdef WEBRTC_CODEC_G722
- // Mono
- , kG722
- // Stereo
- , kG722_2ch
-#endif
-#ifdef WEBRTC_CODEC_OPUS
- // Mono and stereo
- , kOpus
-#endif
- , kCNNB
- , kCNWB
- , kCNSWB
-#ifdef ENABLE_48000_HZ
- , kCNFB
-#endif
- , kAVT
-#ifdef WEBRTC_CODEC_RED
- , kRED
-#endif
- , kNumCodecs
- };
-
- // Set unsupported codecs to -1
-#ifndef WEBRTC_CODEC_ISAC
- enum {kISACSWB = -1};
-# ifndef WEBRTC_CODEC_ISACFX
- enum {kISAC = -1};
-# endif
-#endif
- // 48 kHz not supported, always set to -1.
- enum {kPCM16Bswb48kHz = -1};
-#ifndef WEBRTC_CODEC_ILBC
- enum {kILBC = -1};
-#endif
-#ifndef WEBRTC_CODEC_G722
- // Mono
- enum {kG722 = -1};
- // Stereo
- enum {kG722_2ch = -1};
-#endif
-#ifndef WEBRTC_CODEC_OPUS
- // Mono and stereo
- enum {kOpus = -1};
-#endif
-#ifndef WEBRTC_CODEC_RED
- enum {kRED = -1};
-#endif
-#ifndef ENABLE_48000_HZ
- enum { kCNFB = -1 };
-#endif
-
// kMaxNumCodecs - Maximum number of codecs that can be activated in one
// build.
// kMaxNumPacketSize - Maximum number of allowed packet sizes for one codec.
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
index bfcf76c..23ffafc 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
@@ -111,9 +111,13 @@
}
// Is the given codec a CNG codec?
+// TODO(kwiberg): Move to RentACodec.
bool IsCng(int codec_id) {
- return (codec_id == ACMCodecDB::kCNNB || codec_id == ACMCodecDB::kCNWB ||
- codec_id == ACMCodecDB::kCNSWB || codec_id == ACMCodecDB::kCNFB);
+ auto i = RentACodec::CodecIdFromIndex(codec_id);
+ return (i && (*i == RentACodec::CodecId::kCNNB ||
+ *i == RentACodec::CodecId::kCNWB ||
+ *i == RentACodec::CodecId::kCNSWB ||
+ *i == RentACodec::CodecId::kCNFB));
}
} // namespace
@@ -241,7 +245,8 @@
if (last_audio_decoder_ && last_audio_decoder_->channels > 1)
return 0;
packet_type = InitialDelayManager::kCngPacket;
- } else if (decoder->acm_codec_id == ACMCodecDB::kAVT) {
+ } else if (decoder->acm_codec_id ==
+ *RentACodec::CodecIndexFromId(RentACodec::CodecId::kAVT)) {
packet_type = InitialDelayManager::kAvtPacket;
} else {
if (decoder != last_audio_decoder_) {
@@ -566,11 +571,13 @@
}
int AcmReceiver::RedPayloadType() const {
- if (ACMCodecDB::kRED >= 0) { // This ensures that RED is defined in WebRTC.
+ const auto red_index =
+ RentACodec::CodecIndexFromId(RentACodec::CodecId::kRED);
+ if (red_index) {
CriticalSectionScoped lock(crit_sect_.get());
for (const auto& decoder_pair : decoders_) {
const Decoder& decoder = decoder_pair.second;
- if (decoder.acm_codec_id == ACMCodecDB::kRED)
+ if (decoder.acm_codec_id == *red_index)
return decoder.payload_type;
}
}
@@ -737,8 +744,10 @@
const RTPHeader& rtp_header,
const uint8_t* payload) const {
auto it = decoders_.find(rtp_header.payloadType);
- if (ACMCodecDB::kRED >= 0 && // This ensures that RED is defined in WebRTC.
- it != decoders_.end() && ACMCodecDB::kRED == it->second.acm_codec_id) {
+ const auto red_index =
+ RentACodec::CodecIndexFromId(RentACodec::CodecId::kRED);
+ if (red_index && // This ensures that RED is defined in WebRTC.
+ it != decoders_.end() && it->second.acm_codec_id == *red_index) {
// This is a RED packet, get the payload of the audio codec.
it = decoders_.find(payload[0] & 0x7F);
}
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
index 12ea300..7330a9f 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc
@@ -37,6 +37,19 @@
return true;
}
+struct CodecIdInst {
+ explicit CodecIdInst(RentACodec::CodecId codec_id) {
+ const auto codec_ix = RentACodec::CodecIndexFromId(codec_id);
+ EXPECT_TRUE(codec_ix);
+ id = *codec_ix;
+ const auto codec_inst = RentACodec::CodecInstById(codec_id);
+ EXPECT_TRUE(codec_inst);
+ inst = *codec_inst;
+ }
+ int id;
+ CodecInst inst;
+};
+
} // namespace
class AcmReceiverTestOldApi : public AudioPacketizationCallback,
@@ -57,9 +70,7 @@
void SetUp() override {
ASSERT_TRUE(receiver_.get() != NULL);
ASSERT_TRUE(acm_.get() != NULL);
- for (int n = 0; n < ACMCodecDB::kNumCodecs; n++) {
- ASSERT_EQ(0, ACMCodecDB::Codec(n, &codecs_[n]));
- }
+ codecs_ = RentACodec::Database();
acm_->InitializeReceiver();
acm_->RegisterTransportCallback(this);
@@ -103,14 +114,14 @@
}
}
- // Last element of id should be negative.
- void AddSetOfCodecs(const int* id) {
- int n = 0;
- while (id[n] >= 0) {
- ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype,
- codecs_[id[n]].channels,
- codecs_[id[n]].plfreq, NULL));
- ++n;
+ template <size_t N>
+ void AddSetOfCodecs(const RentACodec::CodecId(&ids)[N]) {
+ for (auto id : ids) {
+ const auto i = RentACodec::CodecIndexFromId(id);
+ ASSERT_TRUE(i);
+ ASSERT_EQ(
+ 0, receiver_->AddCodec(*i, codecs_[*i].pltype, codecs_[*i].channels,
+ codecs_[*i].plfreq, nullptr));
}
}
@@ -144,7 +155,7 @@
}
rtc::scoped_ptr<AcmReceiver> receiver_;
- CodecInst codecs_[ACMCodecDB::kMaxNumCodecs];
+ rtc::ArrayView<const CodecInst> codecs_;
rtc::scoped_ptr<AudioCodingModule> acm_;
WebRtcRTPHeader rtp_header_;
uint32_t timestamp_;
@@ -155,14 +166,14 @@
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecGetCodec)) {
// Add codec.
- for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
+ for (size_t n = 0; n < codecs_.size(); ++n) {
if (n & 0x1) // Just add codecs with odd index.
EXPECT_EQ(0,
receiver_->AddCodec(n, codecs_[n].pltype, codecs_[n].channels,
codecs_[n].plfreq, NULL));
}
// Get codec and compare.
- for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
+ for (size_t n = 0; n < codecs_.size(); ++n) {
CodecInst my_codec;
if (n & 0x1) {
// Codecs with odd index should match the reference.
@@ -178,58 +189,52 @@
}
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) {
- const int codec_id = ACMCodecDB::kPCMA;
- CodecInst ref_codec1;
- EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &ref_codec1));
- CodecInst ref_codec2 = ref_codec1;
- ++ref_codec2.pltype;
+ const CodecIdInst codec1(RentACodec::CodecId::kPCMA);
+ CodecInst codec2 = codec1.inst;
+ ++codec2.pltype;
CodecInst test_codec;
// Register the same codec with different payloads.
- EXPECT_EQ(
- 0, receiver_->AddCodec(codec_id, ref_codec1.pltype, ref_codec1.channels,
- ref_codec1.plfreq, NULL));
- EXPECT_EQ(
- 0, receiver_->AddCodec(codec_id, ref_codec2.pltype, ref_codec2.channels,
- ref_codec2.plfreq, NULL));
+ EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec1.inst.pltype,
+ codec1.inst.channels, codec1.inst.plfreq,
+ nullptr));
+ EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec2.pltype, codec2.channels,
+ codec2.plfreq, NULL));
// Both payload types should exist.
- EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec1.pltype, &test_codec));
- EXPECT_EQ(true, CodecsEqual(ref_codec1, test_codec));
- EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec2.pltype, &test_codec));
- EXPECT_EQ(true, CodecsEqual(ref_codec2, test_codec));
+ EXPECT_EQ(0,
+ receiver_->DecoderByPayloadType(codec1.inst.pltype, &test_codec));
+ EXPECT_EQ(true, CodecsEqual(codec1.inst, test_codec));
+ EXPECT_EQ(0, receiver_->DecoderByPayloadType(codec2.pltype, &test_codec));
+ EXPECT_EQ(true, CodecsEqual(codec2, test_codec));
}
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecChangeCodecId)) {
- const int codec_id1 = ACMCodecDB::kPCMU;
- CodecInst ref_codec1;
- EXPECT_EQ(0, ACMCodecDB::Codec(codec_id1, &ref_codec1));
- const int codec_id2 = ACMCodecDB::kPCMA;
- CodecInst ref_codec2;
- EXPECT_EQ(0, ACMCodecDB::Codec(codec_id2, &ref_codec2));
- ref_codec2.pltype = ref_codec1.pltype;
+ const CodecIdInst codec1(RentACodec::CodecId::kPCMU);
+ CodecIdInst codec2(RentACodec::CodecId::kPCMA);
+ codec2.inst.pltype = codec1.inst.pltype;
CodecInst test_codec;
// Register the same payload type with different codec ID.
- EXPECT_EQ(
- 0, receiver_->AddCodec(codec_id1, ref_codec1.pltype, ref_codec1.channels,
- ref_codec1.plfreq, NULL));
- EXPECT_EQ(
- 0, receiver_->AddCodec(codec_id2, ref_codec2.pltype, ref_codec2.channels,
- ref_codec2.plfreq, NULL));
+ EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec1.inst.pltype,
+ codec1.inst.channels, codec1.inst.plfreq,
+ nullptr));
+ EXPECT_EQ(0, receiver_->AddCodec(codec2.id, codec2.inst.pltype,
+ codec2.inst.channels, codec2.inst.plfreq,
+ nullptr));
// Make sure that the last codec is used.
- EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec2.pltype, &test_codec));
- EXPECT_EQ(true, CodecsEqual(ref_codec2, test_codec));
+ EXPECT_EQ(0,
+ receiver_->DecoderByPayloadType(codec2.inst.pltype, &test_codec));
+ EXPECT_EQ(true, CodecsEqual(codec2.inst, test_codec));
}
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) {
- CodecInst codec;
- const int codec_id = ACMCodecDB::kPCMA;
- EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &codec));
- const int payload_type = codec.pltype;
- EXPECT_EQ(0, receiver_->AddCodec(codec_id, codec.pltype, codec.channels,
- codec.plfreq, NULL));
+ const CodecIdInst codec(RentACodec::CodecId::kPCMA);
+ const int payload_type = codec.inst.pltype;
+ EXPECT_EQ(
+ 0, receiver_->AddCodec(codec.id, codec.inst.pltype, codec.inst.channels,
+ codec.inst.plfreq, nullptr));
// Remove non-existing codec should not fail. ACM1 legacy.
EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1));
@@ -238,46 +243,43 @@
EXPECT_EQ(0, receiver_->RemoveCodec(payload_type));
// Ask for the removed codec, must fail.
- EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &codec));
+ CodecInst ci;
+ EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &ci));
}
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(SampleRate)) {
- const int kCodecId[] = {
- ACMCodecDB::kISAC, ACMCodecDB::kISACSWB,
- -1 // Terminator.
- };
+ const RentACodec::CodecId kCodecId[] = {RentACodec::CodecId::kISAC,
+ RentACodec::CodecId::kISACSWB};
AddSetOfCodecs(kCodecId);
AudioFrame frame;
const int kOutSampleRateHz = 8000; // Different than codec sample rate.
- int n = 0;
- while (kCodecId[n] >= 0) {
- const int num_10ms_frames = codecs_[kCodecId[n]].pacsize /
- (codecs_[kCodecId[n]].plfreq / 100);
- InsertOnePacketOfSilence(kCodecId[n]);
+ for (const auto codec_id : kCodecId) {
+ const CodecIdInst codec(codec_id);
+ const int num_10ms_frames = codec.inst.pacsize / (codec.inst.plfreq / 100);
+ InsertOnePacketOfSilence(codec.id);
for (int k = 0; k < num_10ms_frames; ++k) {
EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame));
}
- EXPECT_EQ(std::min(32000, codecs_[kCodecId[n]].plfreq),
+ EXPECT_EQ(std::min(32000, codec.inst.plfreq),
receiver_->current_sample_rate_hz());
- ++n;
}
}
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PostdecodingVad)) {
receiver_->EnableVad();
EXPECT_TRUE(receiver_->vad_enabled());
-
- const int id = ACMCodecDB::kPCM16Bwb;
- ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
- codecs_[id].plfreq, NULL));
+ const CodecIdInst codec(RentACodec::CodecId::kPCM16Bwb);
+ ASSERT_EQ(
+ 0, receiver_->AddCodec(codec.id, codec.inst.pltype, codec.inst.channels,
+ codec.inst.plfreq, nullptr));
const int kNumPackets = 5;
- const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
+ const int num_10ms_frames = codec.inst.pacsize / (codec.inst.plfreq / 100);
AudioFrame frame;
for (int n = 0; n < kNumPackets; ++n) {
- InsertOnePacketOfSilence(id);
+ InsertOnePacketOfSilence(codec.id);
for (int k = 0; k < num_10ms_frames; ++k)
- ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
+ ASSERT_EQ(0, receiver_->GetAudio(codec.inst.plfreq, &frame));
}
EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
@@ -285,9 +287,9 @@
EXPECT_FALSE(receiver_->vad_enabled());
for (int n = 0; n < kNumPackets; ++n) {
- InsertOnePacketOfSilence(id);
+ InsertOnePacketOfSilence(codec.id);
for (int k = 0; k < num_10ms_frames; ++k)
- ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
+ ASSERT_EQ(0, receiver_->GetAudio(codec.inst.plfreq, &frame));
}
EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
}
@@ -300,25 +302,20 @@
TEST_F(AcmReceiverTestOldApi,
DISABLED_ON_ANDROID(IF_ISAC_FLOAT(LastAudioCodec))) {
- const int kCodecId[] = {
- ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB,
- ACMCodecDB::kPCM16Bswb32kHz,
- -1 // Terminator.
- };
+ const RentACodec::CodecId kCodecId[] = {
+ RentACodec::CodecId::kISAC, RentACodec::CodecId::kPCMA,
+ RentACodec::CodecId::kISACSWB, RentACodec::CodecId::kPCM16Bswb32kHz};
AddSetOfCodecs(kCodecId);
- const int kCngId[] = { // Not including full-band.
- ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB,
- -1 // Terminator.
- };
+ const RentACodec::CodecId kCngId[] = {
+ // Not including full-band.
+ RentACodec::CodecId::kCNNB, RentACodec::CodecId::kCNWB,
+ RentACodec::CodecId::kCNSWB};
AddSetOfCodecs(kCngId);
// Register CNG at sender side.
- int n = 0;
- while (kCngId[n] > 0) {
- ASSERT_EQ(0, acm_->RegisterSendCodec(codecs_[kCngId[n]]));
- ++n;
- }
+ for (auto id : kCngId)
+ ASSERT_EQ(0, acm_->RegisterSendCodec(CodecIdInst(id).inst));
CodecInst codec;
// No audio payload is received.
@@ -327,7 +324,8 @@
// Start with sending DTX.
ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr));
packet_sent_ = false;
- InsertOnePacketOfSilence(kCodecId[0]); // Enough to test with one codec.
+ InsertOnePacketOfSilence(CodecIdInst(kCodecId[0]).id); // Enough to test
+ // with one codec.
ASSERT_TRUE(packet_sent_);
EXPECT_EQ(kAudioFrameCN, last_frame_type_);
@@ -335,18 +333,19 @@
EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
EXPECT_EQ(-1, receiver_->last_audio_codec_id());
- n = 0;
- while (kCodecId[n] >= 0) { // Loop over codecs.
+ for (auto id : kCodecId) {
+ const CodecIdInst c(id);
+
// Set DTX off to send audio payload.
acm_->SetVAD(false, false, VADAggr);
packet_sent_ = false;
- InsertOnePacketOfSilence(kCodecId[n]);
+ InsertOnePacketOfSilence(c.id);
// Sanity check if Actually an audio payload received, and it should be
// of type "speech."
ASSERT_TRUE(packet_sent_);
ASSERT_EQ(kAudioFrameSpeech, last_frame_type_);
- EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
+ EXPECT_EQ(c.id, receiver_->last_audio_codec_id());
// Set VAD on to send DTX. Then check if the "Last Audio codec" returns
// the expected codec.
@@ -355,13 +354,12 @@
// Do as many encoding until a DTX is sent.
while (last_frame_type_ != kAudioFrameCN) {
packet_sent_ = false;
- InsertOnePacketOfSilence(kCodecId[n]);
+ InsertOnePacketOfSilence(c.id);
ASSERT_TRUE(packet_sent_);
}
- EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
+ EXPECT_EQ(c.id, receiver_->last_audio_codec_id());
EXPECT_EQ(0, receiver_->LastAudioCodec(&codec));
- EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec));
- ++n;
+ EXPECT_TRUE(CodecsEqual(c.inst, codec));
}
}
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc
index 8a0980e..7754a9c 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc
@@ -12,8 +12,8 @@
#include "webrtc/base/checks.h"
#include "webrtc/common_types.h"
-#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
#include "webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h"
+#include "webrtc/modules/audio_coding/main/acm2/rent_a_codec.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "webrtc/system_wrappers/interface/trace.h"
@@ -38,29 +38,32 @@
return new acm2::AudioCodingModuleImpl(config);
}
-// Get number of supported codecs
int AudioCodingModule::NumberOfCodecs() {
- return acm2::ACMCodecDB::kNumCodecs;
+ return static_cast<int>(acm2::RentACodec::NumberOfCodecs());
}
-// Get supported codec parameters with id
int AudioCodingModule::Codec(int list_id, CodecInst* codec) {
- // Get the codec settings for the codec with the given list ID
- return acm2::ACMCodecDB::Codec(list_id, codec);
+ auto codec_id = acm2::RentACodec::CodecIdFromIndex(list_id);
+ if (!codec_id)
+ return -1;
+ auto ci = acm2::RentACodec::CodecInstById(*codec_id);
+ if (!ci)
+ return -1;
+ *codec = *ci;
+ return 0;
}
-// Get supported codec parameters with name, frequency and number of channels.
int AudioCodingModule::Codec(const char* payload_name,
CodecInst* codec,
int sampling_freq_hz,
int channels) {
- int codec_id;
-
- // Get the id of the codec from the database.
- codec_id = acm2::ACMCodecDB::CodecId(
+ rtc::Maybe<CodecInst> ci = acm2::RentACodec::CodecInstByParams(
payload_name, sampling_freq_hz, channels);
- if (codec_id < 0) {
- // We couldn't find a matching codec, set the parameters to unacceptable
+ if (ci) {
+ *codec = *ci;
+ return 0;
+ } else {
+ // We couldn't find a matching codec, so set the parameters to unacceptable
// values and return.
codec->plname[0] = '\0';
codec->pltype = -1;
@@ -69,35 +72,26 @@
codec->plfreq = 0;
return -1;
}
-
- // Get default codec settings.
- acm2::ACMCodecDB::Codec(codec_id, codec);
-
- // Keep the number of channels from the function call. For most codecs it
- // will be the same value as in default codec settings, but not for all.
- codec->channels = channels;
-
- return 0;
}
-// Get supported codec Index with name, frequency and number of channels.
int AudioCodingModule::Codec(const char* payload_name,
int sampling_freq_hz,
int channels) {
- return acm2::ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels);
+ rtc::Maybe<acm2::RentACodec::CodecId> ci = acm2::RentACodec::CodecIdByParams(
+ payload_name, sampling_freq_hz, channels);
+ if (!ci)
+ return -1;
+ rtc::Maybe<int> i = acm2::RentACodec::CodecIndexFromId(*ci);
+ return i ? *i : -1;
}
// Checks the validity of the parameters of the given codec
bool AudioCodingModule::IsCodecValid(const CodecInst& codec) {
- int codec_number = acm2::ACMCodecDB::CodecNumber(codec);
-
- if (codec_number < 0) {
+ bool valid = acm2::RentACodec::IsCodecValid(codec);
+ if (!valid)
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, -1,
"Invalid codec setting");
- return false;
- } else {
- return true;
- }
+ return valid;
}
} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
index 467e749..9154107 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -36,20 +36,12 @@
// TODO(turajs): the same functionality is used in NetEq. If both classes
// need them, make it a static function in ACMCodecDB.
-bool IsCodecRED(const CodecInst* codec) {
- return (STR_CASE_CMP(codec->plname, "RED") == 0);
+bool IsCodecRED(const CodecInst& codec) {
+ return (STR_CASE_CMP(codec.plname, "RED") == 0);
}
-bool IsCodecRED(int index) {
- return (IsCodecRED(&ACMCodecDB::database_[index]));
-}
-
-bool IsCodecCN(const CodecInst* codec) {
- return (STR_CASE_CMP(codec->plname, "CN") == 0);
-}
-
-bool IsCodecCN(int index) {
- return (IsCodecCN(&ACMCodecDB::database_[index]));
+bool IsCodecCN(const CodecInst& codec) {
+ return (STR_CASE_CMP(codec.plname, "CN") == 0);
}
// Stereo-to-mono can be used as in-place.
@@ -513,11 +505,12 @@
receiver_.FlushBuffers();
// Register RED and CN.
- for (int i = 0; i < ACMCodecDB::kNumCodecs; i++) {
- if (IsCodecRED(i) || IsCodecCN(i)) {
- uint8_t pl_type = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
- int fs = ACMCodecDB::database_[i].plfreq;
- if (receiver_.AddCodec(i, pl_type, 1, fs, NULL) < 0) {
+ auto db = RentACodec::Database();
+ for (size_t i = 0; i < db.size(); i++) {
+ if (IsCodecRED(db[i]) || IsCodecCN(db[i])) {
+ if (receiver_.AddCodec(static_cast<int>(i),
+ static_cast<uint8_t>(db[i].pltype), 1,
+ db[i].plfreq, nullptr) < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
"Cannot register master codec.");
return -1;
@@ -561,11 +554,14 @@
return -1;
}
- int codec_id = ACMCodecDB::ReceiverCodecNumber(codec);
- if (codec_id < 0 || codec_id >= ACMCodecDB::kNumCodecs) {
+ auto codec_id =
+ RentACodec::CodecIdByParams(codec.plname, codec.plfreq, codec.channels);
+ if (!codec_id) {
LOG_F(LS_ERROR) << "Wrong codec params to be registered as receive codec";
return -1;
}
+ auto codec_index = RentACodec::CodecIndexFromId(*codec_id);
+ RTC_CHECK(codec_index) << "Invalid codec ID: " << static_cast<int>(*codec_id);
// Check if the payload-type is valid.
if (!ACMCodecDB::ValidPayloadType(codec.pltype)) {
@@ -576,7 +572,7 @@
// Get |decoder| associated with |codec|. |decoder| is NULL if |codec| does
// not own its decoder.
- return receiver_.AddCodec(codec_id, codec.pltype, codec.channels,
+ return receiver_.AddCodec(*codec_index, codec.pltype, codec.channels,
codec.plfreq,
codec_manager_.GetAudioDecoder(codec));
}
diff --git a/webrtc/modules/audio_coding/main/acm2/codec_manager.cc b/webrtc/modules/audio_coding/main/acm2/codec_manager.cc
index 862feaa..7f31749 100644
--- a/webrtc/modules/audio_coding/main/acm2/codec_manager.cc
+++ b/webrtc/modules/audio_coding/main/acm2/codec_manager.cc
@@ -23,18 +23,10 @@
return (STR_CASE_CMP(codec.plname, "RED") == 0);
}
-bool IsCodecRED(int index) {
- return (IsCodecRED(ACMCodecDB::database_[index]));
-}
-
bool IsCodecCN(const CodecInst& codec) {
return (STR_CASE_CMP(codec.plname, "CN") == 0);
}
-bool IsCodecCN(int index) {
- return (IsCodecCN(ACMCodecDB::database_[index]));
-}
-
// Check if the given codec is a valid to be registered as send codec.
int IsValidSendCodec(const CodecInst& send_codec, bool is_primary_encoder) {
int dummy_id = 0;
@@ -164,18 +156,18 @@
encoder_is_opus_(false) {
// Register the default payload type for RED and for CNG at sampling rates of
// 8, 16, 32 and 48 kHz.
- for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) {
- if (IsCodecRED(i) && ACMCodecDB::database_[i].plfreq == 8000) {
- red_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
- } else if (IsCodecCN(i)) {
- if (ACMCodecDB::database_[i].plfreq == 8000) {
- cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
- } else if (ACMCodecDB::database_[i].plfreq == 16000) {
- cng_wb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
- } else if (ACMCodecDB::database_[i].plfreq == 32000) {
- cng_swb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
- } else if (ACMCodecDB::database_[i].plfreq == 48000) {
- cng_fb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+ for (const CodecInst& ci : RentACodec::Database()) {
+ if (IsCodecRED(ci) && ci.plfreq == 8000) {
+ red_nb_pltype_ = static_cast<uint8_t>(ci.pltype);
+ } else if (IsCodecCN(ci)) {
+ if (ci.plfreq == 8000) {
+ cng_nb_pltype_ = static_cast<uint8_t>(ci.pltype);
+ } else if (ci.plfreq == 16000) {
+ cng_wb_pltype_ = static_cast<uint8_t>(ci.pltype);
+ } else if (ci.plfreq == 32000) {
+ cng_swb_pltype_ = static_cast<uint8_t>(ci.pltype);
+ } else if (ci.plfreq == 48000) {
+ cng_fb_pltype_ = static_cast<uint8_t>(ci.pltype);
}
}
}
diff --git a/webrtc/modules/audio_coding/main/acm2/rent_a_codec.cc b/webrtc/modules/audio_coding/main/acm2/rent_a_codec.cc
new file mode 100644
index 0000000..4554209
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/rent_a_codec.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_coding/main/acm2/rent_a_codec.h"
+
+#include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
+
+namespace webrtc {
+namespace acm2 {
+
+rtc::Maybe<RentACodec::CodecId> RentACodec::CodecIdByParams(
+ const char* payload_name,
+ int sampling_freq_hz,
+ int channels) {
+ return CodecIdFromIndex(
+ ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels));
+}
+
+rtc::Maybe<CodecInst> RentACodec::CodecInstById(CodecId codec_id) {
+ rtc::Maybe<int> mi = CodecIndexFromId(codec_id);
+ return mi ? rtc::Maybe<CodecInst>(Database()[*mi]) : rtc::Maybe<CodecInst>();
+}
+
+rtc::Maybe<CodecInst> RentACodec::CodecInstByParams(const char* payload_name,
+ int sampling_freq_hz,
+ int channels) {
+ rtc::Maybe<CodecId> codec_id =
+ CodecIdByParams(payload_name, sampling_freq_hz, channels);
+ if (!codec_id)
+ return rtc::Maybe<CodecInst>();
+ rtc::Maybe<CodecInst> ci = CodecInstById(*codec_id);
+ RTC_DCHECK(ci);
+
+ // Keep the number of channels from the function call. For most codecs it
+ // will be the same value as in default codec settings, but not for all.
+ ci->channels = channels;
+
+ return ci;
+}
+
+bool RentACodec::IsCodecValid(const CodecInst& codec_inst) {
+ return ACMCodecDB::CodecNumber(codec_inst) >= 0;
+}
+
+rtc::ArrayView<const CodecInst> RentACodec::Database() {
+ return rtc::ArrayView<const CodecInst>(ACMCodecDB::database_,
+ NumberOfCodecs());
+}
+
+} // namespace acm2
+} // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/rent_a_codec.h b/webrtc/modules/audio_coding/main/acm2/rent_a_codec.h
new file mode 100644
index 0000000..8482d8f
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/rent_a_codec.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_RENT_A_CODEC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_RENT_A_CODEC_H_
+
+#include <stddef.h>
+
+#include "webrtc/base/array_view.h"
+#include "webrtc/base/maybe.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+struct CodecInst;
+
+namespace acm2 {
+
+class RentACodec {
+ public:
+ enum class CodecId {
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
+ kISAC,
+#endif
+#ifdef WEBRTC_CODEC_ISAC
+ kISACSWB,
+#endif
+ // Mono
+ kPCM16B,
+ kPCM16Bwb,
+ kPCM16Bswb32kHz,
+ // Stereo
+ kPCM16B_2ch,
+ kPCM16Bwb_2ch,
+ kPCM16Bswb32kHz_2ch,
+ // Mono
+ kPCMU,
+ kPCMA,
+ // Stereo
+ kPCMU_2ch,
+ kPCMA_2ch,
+#ifdef WEBRTC_CODEC_ILBC
+ kILBC,
+#endif
+#ifdef WEBRTC_CODEC_G722
+ kG722, // Mono
+ kG722_2ch, // Stereo
+#endif
+#ifdef WEBRTC_CODEC_OPUS
+ kOpus, // Mono and stereo
+#endif
+ kCNNB,
+ kCNWB,
+ kCNSWB,
+#ifdef ENABLE_48000_HZ
+ kCNFB,
+#endif
+ kAVT,
+#ifdef WEBRTC_CODEC_RED
+ kRED,
+#endif
+ kNumCodecs, // Implementation detail. Don't use.
+
+// Set unsupported codecs to -1.
+#if !defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX)
+ kISAC = -1,
+#endif
+#ifndef WEBRTC_CODEC_ISAC
+ kISACSWB = -1,
+#endif
+ // 48 kHz not supported, always set to -1.
+ kPCM16Bswb48kHz = -1,
+#ifndef WEBRTC_CODEC_ILBC
+ kILBC = -1,
+#endif
+#ifndef WEBRTC_CODEC_G722
+ kG722 = -1, // Mono
+ kG722_2ch = -1, // Stereo
+#endif
+#ifndef WEBRTC_CODEC_OPUS
+ kOpus = -1, // Mono and stereo
+#endif
+#ifndef WEBRTC_CODEC_RED
+ kRED = -1,
+#endif
+#ifndef ENABLE_48000_HZ
+ kCNFB = -1,
+#endif
+
+ kNone = -1
+ };
+
+ static inline size_t NumberOfCodecs() {
+ return static_cast<size_t>(CodecId::kNumCodecs);
+ }
+
+ static inline rtc::Maybe<int> CodecIndexFromId(CodecId codec_id) {
+ const int i = static_cast<int>(codec_id);
+ return i < static_cast<int>(NumberOfCodecs()) ? i : rtc::Maybe<int>();
+ }
+
+ static inline rtc::Maybe<CodecId> CodecIdFromIndex(int codec_index) {
+ return static_cast<size_t>(codec_index) < NumberOfCodecs()
+ ? static_cast<RentACodec::CodecId>(codec_index)
+ : rtc::Maybe<RentACodec::CodecId>();
+ }
+
+ static rtc::Maybe<CodecId> CodecIdByParams(const char* payload_name,
+ int sampling_freq_hz,
+ int channels);
+ static rtc::Maybe<CodecInst> CodecInstById(CodecId codec_id);
+ static rtc::Maybe<CodecInst> CodecInstByParams(const char* payload_name,
+ int sampling_freq_hz,
+ int channels);
+ static bool IsCodecValid(const CodecInst& codec_inst);
+ static rtc::ArrayView<const CodecInst> Database();
+};
+
+} // namespace acm2
+} // namespace webrtc
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_RENT_A_CODEC_H_
diff --git a/webrtc/modules/audio_coding/main/audio_coding_module.gypi b/webrtc/modules/audio_coding/main/audio_coding_module.gypi
index 295bccf..17b3c42 100644
--- a/webrtc/modules/audio_coding/main/audio_coding_module.gypi
+++ b/webrtc/modules/audio_coding/main/audio_coding_module.gypi
@@ -43,6 +43,30 @@
},
'targets': [
{
+ 'target_name': 'rent_a_codec',
+ 'type': 'static_library',
+ 'defines': [
+ '<@(audio_coding_defines)',
+ ],
+ 'dependencies': [
+ '<(webrtc_root)/common.gyp:webrtc_common',
+ ],
+ 'include_dirs': [
+ '<(webrtc_root)',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(webrtc_root)',
+ ],
+ },
+ 'sources': [
+ 'acm2/acm_codec_database.cc',
+ 'acm2/acm_codec_database.h',
+ 'acm2/rent_a_codec.cc',
+ 'acm2/rent_a_codec.h',
+ ],
+ },
+ {
'target_name': 'audio_coding_module',
'type': 'static_library',
'defines': [
@@ -53,6 +77,7 @@
'<(webrtc_root)/common.gyp:webrtc_common',
'<(webrtc_root)/webrtc.gyp:rtc_event_log',
'neteq',
+ 'rent_a_codec',
],
'include_dirs': [
'interface',
@@ -67,8 +92,6 @@
],
},
'sources': [
- 'acm2/acm_codec_database.cc',
- 'acm2/acm_codec_database.h',
'acm2/acm_common_defs.h',
'acm2/acm_receiver.cc',
'acm2/acm_receiver.h',