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}
This commit is contained in:
kwiberg
2015-10-27 11:40:24 -07:00
committed by Commit bot
parent 77d0d6e858
commit fce4a945b8
11 changed files with 418 additions and 267 deletions

View File

@ -9,6 +9,39 @@
import("//build/config/arm.gni") import("//build/config/arm.gni")
import("../../build/webrtc.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") { config("audio_coding_config") {
include_dirs = [ include_dirs = [
"main/interface", "main/interface",
@ -18,8 +51,6 @@ config("audio_coding_config") {
source_set("audio_coding") { source_set("audio_coding") {
sources = [ sources = [
"main/acm2/acm_codec_database.cc",
"main/acm2/acm_codec_database.h",
"main/acm2/acm_common_defs.h", "main/acm2/acm_common_defs.h",
"main/acm2/acm_receiver.cc", "main/acm2/acm_receiver.cc",
"main/acm2/acm_receiver.h", "main/acm2/acm_receiver.h",
@ -69,6 +100,7 @@ source_set("audio_coding") {
":g711", ":g711",
":neteq", ":neteq",
":pcm16b", ":pcm16b",
":rent_a_codec",
"../..:rtc_event_log", "../..:rtc_event_log",
"../..:webrtc_common", "../..:webrtc_common",
"../../common_audio", "../../common_audio",

View File

@ -223,7 +223,7 @@ const NetEqDecoder ACMCodecDB::neteq_decoders_[] = {
// TODO(tlegrand): replace memcpy with a pointer to the data base memory. // TODO(tlegrand): replace memcpy with a pointer to the data base memory.
int ACMCodecDB::Codec(int codec_id, CodecInst* codec_inst) { int ACMCodecDB::Codec(int codec_id, CodecInst* codec_inst) {
// Error check to see that codec_id is not out of bounds. // 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; return -1;
} }
@ -318,7 +318,7 @@ int ACMCodecDB::CodecId(const CodecInst& codec_inst) {
} }
int ACMCodecDB::CodecId(const char* payload_name, int frequency, int channels) { 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 name_match = false;
bool frequency_match = false; bool frequency_match = false;
bool channels_match = false; bool channels_match = false;
@ -326,11 +326,11 @@ int ACMCodecDB::CodecId(const char* payload_name, int frequency, int channels) {
// Payload name, sampling frequency and number of channels need to match. // Payload name, sampling frequency and number of channels need to match.
// NOTE! If |frequency| is -1, the frequency is not applicable, and is // NOTE! If |frequency| is -1, the frequency is not applicable, and is
// always treated as true, like for RED. // always treated as true, like for RED.
name_match = (STR_CASE_CMP(database_[id].plname, payload_name) == 0); name_match = (STR_CASE_CMP(ci.plname, payload_name) == 0);
frequency_match = (frequency == database_[id].plfreq) || (frequency == -1); frequency_match = (frequency == ci.plfreq) || (frequency == -1);
// The number of channels must match for all codecs but Opus. // The number of channels must match for all codecs but Opus.
if (STR_CASE_CMP(payload_name, "opus") != 0) { if (STR_CASE_CMP(payload_name, "opus") != 0) {
channels_match = (channels == database_[id].channels); channels_match = (channels == ci.channels);
} else { } else {
// For opus we just check that number of channels is valid. // For opus we just check that number of channels is valid.
channels_match = (channels == 1 || channels == 2); channels_match = (channels == 1 || channels == 2);
@ -338,7 +338,7 @@ int ACMCodecDB::CodecId(const char* payload_name, int frequency, int channels) {
if (name_match && frequency_match && channels_match) { if (name_match && frequency_match && channels_match) {
// We have found a matching codec in the list. // We have found a matching codec in the list.
return id; return &ci - RentACodec::Database().data();
} }
} }
@ -354,12 +354,9 @@ int ACMCodecDB::ReceiverCodecNumber(const CodecInst& codec_inst) {
// Returns the codec sampling frequency for codec with id = "codec_id" in // Returns the codec sampling frequency for codec with id = "codec_id" in
// database. // database.
int ACMCodecDB::CodecFreq(int codec_id) { int ACMCodecDB::CodecFreq(int codec_id) {
// Error check to see that codec_id is not out of bounds. const size_t i = static_cast<size_t>(codec_id);
if (codec_id < 0 || codec_id >= kNumCodecs) { const auto db = RentACodec::Database();
return -1; return i < db.size() ? db[i].plfreq : -1;
}
return database_[codec_id].plfreq;
} }
// Checks if the payload type is in the valid range. // Checks if the payload type is in the valid range.

View File

@ -18,6 +18,7 @@
#include "webrtc/common_types.h" #include "webrtc/common_types.h"
#include "webrtc/engine_configurations.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" #include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
namespace webrtc { namespace webrtc {
@ -27,85 +28,6 @@ namespace acm2 {
// TODO(tlegrand): replace class ACMCodecDB with a namespace. // TODO(tlegrand): replace class ACMCodecDB with a namespace.
class ACMCodecDB { class ACMCodecDB {
public: 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 // kMaxNumCodecs - Maximum number of codecs that can be activated in one
// build. // build.
// kMaxNumPacketSize - Maximum number of allowed packet sizes for one codec. // kMaxNumPacketSize - Maximum number of allowed packet sizes for one codec.

View File

@ -111,9 +111,13 @@ void SetAudioFrameActivityAndType(bool vad_enabled,
} }
// Is the given codec a CNG codec? // Is the given codec a CNG codec?
// TODO(kwiberg): Move to RentACodec.
bool IsCng(int codec_id) { bool IsCng(int codec_id) {
return (codec_id == ACMCodecDB::kCNNB || codec_id == ACMCodecDB::kCNWB || auto i = RentACodec::CodecIdFromIndex(codec_id);
codec_id == ACMCodecDB::kCNSWB || codec_id == ACMCodecDB::kCNFB); return (i && (*i == RentACodec::CodecId::kCNNB ||
*i == RentACodec::CodecId::kCNWB ||
*i == RentACodec::CodecId::kCNSWB ||
*i == RentACodec::CodecId::kCNFB));
} }
} // namespace } // namespace
@ -241,7 +245,8 @@ int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
if (last_audio_decoder_ && last_audio_decoder_->channels > 1) if (last_audio_decoder_ && last_audio_decoder_->channels > 1)
return 0; return 0;
packet_type = InitialDelayManager::kCngPacket; 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; packet_type = InitialDelayManager::kAvtPacket;
} else { } else {
if (decoder != last_audio_decoder_) { if (decoder != last_audio_decoder_) {
@ -566,11 +571,13 @@ int AcmReceiver::last_audio_codec_id() const {
} }
int AcmReceiver::RedPayloadType() const { 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()); CriticalSectionScoped lock(crit_sect_.get());
for (const auto& decoder_pair : decoders_) { for (const auto& decoder_pair : decoders_) {
const Decoder& decoder = decoder_pair.second; const Decoder& decoder = decoder_pair.second;
if (decoder.acm_codec_id == ACMCodecDB::kRED) if (decoder.acm_codec_id == *red_index)
return decoder.payload_type; return decoder.payload_type;
} }
} }
@ -737,8 +744,10 @@ const AcmReceiver::Decoder* AcmReceiver::RtpHeaderToDecoder(
const RTPHeader& rtp_header, const RTPHeader& rtp_header,
const uint8_t* payload) const { const uint8_t* payload) const {
auto it = decoders_.find(rtp_header.payloadType); auto it = decoders_.find(rtp_header.payloadType);
if (ACMCodecDB::kRED >= 0 && // This ensures that RED is defined in WebRTC. const auto red_index =
it != decoders_.end() && ACMCodecDB::kRED == it->second.acm_codec_id) { 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. // This is a RED packet, get the payload of the audio codec.
it = decoders_.find(payload[0] & 0x7F); it = decoders_.find(payload[0] & 0x7F);
} }

View File

@ -37,6 +37,19 @@ bool CodecsEqual(const CodecInst& codec_a, const CodecInst& codec_b) {
return true; 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 } // namespace
class AcmReceiverTestOldApi : public AudioPacketizationCallback, class AcmReceiverTestOldApi : public AudioPacketizationCallback,
@ -57,9 +70,7 @@ class AcmReceiverTestOldApi : public AudioPacketizationCallback,
void SetUp() override { void SetUp() override {
ASSERT_TRUE(receiver_.get() != NULL); ASSERT_TRUE(receiver_.get() != NULL);
ASSERT_TRUE(acm_.get() != NULL); ASSERT_TRUE(acm_.get() != NULL);
for (int n = 0; n < ACMCodecDB::kNumCodecs; n++) { codecs_ = RentACodec::Database();
ASSERT_EQ(0, ACMCodecDB::Codec(n, &codecs_[n]));
}
acm_->InitializeReceiver(); acm_->InitializeReceiver();
acm_->RegisterTransportCallback(this); acm_->RegisterTransportCallback(this);
@ -103,14 +114,14 @@ class AcmReceiverTestOldApi : public AudioPacketizationCallback,
} }
} }
// Last element of id should be negative. template <size_t N>
void AddSetOfCodecs(const int* id) { void AddSetOfCodecs(const RentACodec::CodecId(&ids)[N]) {
int n = 0; for (auto id : ids) {
while (id[n] >= 0) { const auto i = RentACodec::CodecIndexFromId(id);
ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype, ASSERT_TRUE(i);
codecs_[id[n]].channels, ASSERT_EQ(
codecs_[id[n]].plfreq, NULL)); 0, receiver_->AddCodec(*i, codecs_[*i].pltype, codecs_[*i].channels,
++n; codecs_[*i].plfreq, nullptr));
} }
} }
@ -144,7 +155,7 @@ class AcmReceiverTestOldApi : public AudioPacketizationCallback,
} }
rtc::scoped_ptr<AcmReceiver> receiver_; rtc::scoped_ptr<AcmReceiver> receiver_;
CodecInst codecs_[ACMCodecDB::kMaxNumCodecs]; rtc::ArrayView<const CodecInst> codecs_;
rtc::scoped_ptr<AudioCodingModule> acm_; rtc::scoped_ptr<AudioCodingModule> acm_;
WebRtcRTPHeader rtp_header_; WebRtcRTPHeader rtp_header_;
uint32_t timestamp_; uint32_t timestamp_;
@ -155,14 +166,14 @@ class AcmReceiverTestOldApi : public AudioPacketizationCallback,
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecGetCodec)) { TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecGetCodec)) {
// Add codec. // 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. if (n & 0x1) // Just add codecs with odd index.
EXPECT_EQ(0, EXPECT_EQ(0,
receiver_->AddCodec(n, codecs_[n].pltype, codecs_[n].channels, receiver_->AddCodec(n, codecs_[n].pltype, codecs_[n].channels,
codecs_[n].plfreq, NULL)); codecs_[n].plfreq, NULL));
} }
// Get codec and compare. // Get codec and compare.
for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) { for (size_t n = 0; n < codecs_.size(); ++n) {
CodecInst my_codec; CodecInst my_codec;
if (n & 0x1) { if (n & 0x1) {
// Codecs with odd index should match the reference. // Codecs with odd index should match the reference.
@ -178,58 +189,52 @@ TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecGetCodec)) {
} }
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) { TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) {
const int codec_id = ACMCodecDB::kPCMA; const CodecIdInst codec1(RentACodec::CodecId::kPCMA);
CodecInst ref_codec1; CodecInst codec2 = codec1.inst;
EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &ref_codec1)); ++codec2.pltype;
CodecInst ref_codec2 = ref_codec1;
++ref_codec2.pltype;
CodecInst test_codec; CodecInst test_codec;
// Register the same codec with different payloads. // Register the same codec with different payloads.
EXPECT_EQ( EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec1.inst.pltype,
0, receiver_->AddCodec(codec_id, ref_codec1.pltype, ref_codec1.channels, codec1.inst.channels, codec1.inst.plfreq,
ref_codec1.plfreq, NULL)); nullptr));
EXPECT_EQ( EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec2.pltype, codec2.channels,
0, receiver_->AddCodec(codec_id, ref_codec2.pltype, ref_codec2.channels, codec2.plfreq, NULL));
ref_codec2.plfreq, NULL));
// Both payload types should exist. // Both payload types should exist.
EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec1.pltype, &test_codec)); EXPECT_EQ(0,
EXPECT_EQ(true, CodecsEqual(ref_codec1, test_codec)); receiver_->DecoderByPayloadType(codec1.inst.pltype, &test_codec));
EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec2.pltype, &test_codec)); EXPECT_EQ(true, CodecsEqual(codec1.inst, test_codec));
EXPECT_EQ(true, CodecsEqual(ref_codec2, 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)) { TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecChangeCodecId)) {
const int codec_id1 = ACMCodecDB::kPCMU; const CodecIdInst codec1(RentACodec::CodecId::kPCMU);
CodecInst ref_codec1; CodecIdInst codec2(RentACodec::CodecId::kPCMA);
EXPECT_EQ(0, ACMCodecDB::Codec(codec_id1, &ref_codec1)); codec2.inst.pltype = codec1.inst.pltype;
const int codec_id2 = ACMCodecDB::kPCMA;
CodecInst ref_codec2;
EXPECT_EQ(0, ACMCodecDB::Codec(codec_id2, &ref_codec2));
ref_codec2.pltype = ref_codec1.pltype;
CodecInst test_codec; CodecInst test_codec;
// Register the same payload type with different codec ID. // Register the same payload type with different codec ID.
EXPECT_EQ( EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec1.inst.pltype,
0, receiver_->AddCodec(codec_id1, ref_codec1.pltype, ref_codec1.channels, codec1.inst.channels, codec1.inst.plfreq,
ref_codec1.plfreq, NULL)); nullptr));
EXPECT_EQ( EXPECT_EQ(0, receiver_->AddCodec(codec2.id, codec2.inst.pltype,
0, receiver_->AddCodec(codec_id2, ref_codec2.pltype, ref_codec2.channels, codec2.inst.channels, codec2.inst.plfreq,
ref_codec2.plfreq, NULL)); nullptr));
// Make sure that the last codec is used. // Make sure that the last codec is used.
EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec2.pltype, &test_codec)); EXPECT_EQ(0,
EXPECT_EQ(true, CodecsEqual(ref_codec2, test_codec)); receiver_->DecoderByPayloadType(codec2.inst.pltype, &test_codec));
EXPECT_EQ(true, CodecsEqual(codec2.inst, test_codec));
} }
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) { TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) {
CodecInst codec; const CodecIdInst codec(RentACodec::CodecId::kPCMA);
const int codec_id = ACMCodecDB::kPCMA; const int payload_type = codec.inst.pltype;
EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &codec)); EXPECT_EQ(
const int payload_type = codec.pltype; 0, receiver_->AddCodec(codec.id, codec.inst.pltype, codec.inst.channels,
EXPECT_EQ(0, receiver_->AddCodec(codec_id, codec.pltype, codec.channels, codec.inst.plfreq, nullptr));
codec.plfreq, NULL));
// Remove non-existing codec should not fail. ACM1 legacy. // Remove non-existing codec should not fail. ACM1 legacy.
EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1)); EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1));
@ -238,46 +243,43 @@ TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) {
EXPECT_EQ(0, receiver_->RemoveCodec(payload_type)); EXPECT_EQ(0, receiver_->RemoveCodec(payload_type));
// Ask for the removed codec, must fail. // 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)) { TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(SampleRate)) {
const int kCodecId[] = { const RentACodec::CodecId kCodecId[] = {RentACodec::CodecId::kISAC,
ACMCodecDB::kISAC, ACMCodecDB::kISACSWB, RentACodec::CodecId::kISACSWB};
-1 // Terminator.
};
AddSetOfCodecs(kCodecId); AddSetOfCodecs(kCodecId);
AudioFrame frame; AudioFrame frame;
const int kOutSampleRateHz = 8000; // Different than codec sample rate. const int kOutSampleRateHz = 8000; // Different than codec sample rate.
int n = 0; for (const auto codec_id : kCodecId) {
while (kCodecId[n] >= 0) { const CodecIdInst codec(codec_id);
const int num_10ms_frames = codecs_[kCodecId[n]].pacsize / const int num_10ms_frames = codec.inst.pacsize / (codec.inst.plfreq / 100);
(codecs_[kCodecId[n]].plfreq / 100); InsertOnePacketOfSilence(codec.id);
InsertOnePacketOfSilence(kCodecId[n]);
for (int k = 0; k < num_10ms_frames; ++k) { for (int k = 0; k < num_10ms_frames; ++k) {
EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame)); 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()); receiver_->current_sample_rate_hz());
++n;
} }
} }
TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PostdecodingVad)) { TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PostdecodingVad)) {
receiver_->EnableVad(); receiver_->EnableVad();
EXPECT_TRUE(receiver_->vad_enabled()); EXPECT_TRUE(receiver_->vad_enabled());
const CodecIdInst codec(RentACodec::CodecId::kPCM16Bwb);
const int id = ACMCodecDB::kPCM16Bwb; ASSERT_EQ(
ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels, 0, receiver_->AddCodec(codec.id, codec.inst.pltype, codec.inst.channels,
codecs_[id].plfreq, NULL)); codec.inst.plfreq, nullptr));
const int kNumPackets = 5; 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; AudioFrame frame;
for (int n = 0; n < kNumPackets; ++n) { for (int n = 0; n < kNumPackets; ++n) {
InsertOnePacketOfSilence(id); InsertOnePacketOfSilence(codec.id);
for (int k = 0; k < num_10ms_frames; ++k) 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_); EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
@ -285,9 +287,9 @@ TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PostdecodingVad)) {
EXPECT_FALSE(receiver_->vad_enabled()); EXPECT_FALSE(receiver_->vad_enabled());
for (int n = 0; n < kNumPackets; ++n) { for (int n = 0; n < kNumPackets; ++n) {
InsertOnePacketOfSilence(id); InsertOnePacketOfSilence(codec.id);
for (int k = 0; k < num_10ms_frames; ++k) 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_); EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
} }
@ -300,25 +302,20 @@ TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PostdecodingVad)) {
TEST_F(AcmReceiverTestOldApi, TEST_F(AcmReceiverTestOldApi,
DISABLED_ON_ANDROID(IF_ISAC_FLOAT(LastAudioCodec))) { DISABLED_ON_ANDROID(IF_ISAC_FLOAT(LastAudioCodec))) {
const int kCodecId[] = { const RentACodec::CodecId kCodecId[] = {
ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB, RentACodec::CodecId::kISAC, RentACodec::CodecId::kPCMA,
ACMCodecDB::kPCM16Bswb32kHz, RentACodec::CodecId::kISACSWB, RentACodec::CodecId::kPCM16Bswb32kHz};
-1 // Terminator.
};
AddSetOfCodecs(kCodecId); AddSetOfCodecs(kCodecId);
const int kCngId[] = { // Not including full-band. const RentACodec::CodecId kCngId[] = {
ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB, // Not including full-band.
-1 // Terminator. RentACodec::CodecId::kCNNB, RentACodec::CodecId::kCNWB,
}; RentACodec::CodecId::kCNSWB};
AddSetOfCodecs(kCngId); AddSetOfCodecs(kCngId);
// Register CNG at sender side. // Register CNG at sender side.
int n = 0; for (auto id : kCngId)
while (kCngId[n] > 0) { ASSERT_EQ(0, acm_->RegisterSendCodec(CodecIdInst(id).inst));
ASSERT_EQ(0, acm_->RegisterSendCodec(codecs_[kCngId[n]]));
++n;
}
CodecInst codec; CodecInst codec;
// No audio payload is received. // No audio payload is received.
@ -327,7 +324,8 @@ TEST_F(AcmReceiverTestOldApi,
// Start with sending DTX. // Start with sending DTX.
ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr)); ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr));
packet_sent_ = false; 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_); ASSERT_TRUE(packet_sent_);
EXPECT_EQ(kAudioFrameCN, last_frame_type_); EXPECT_EQ(kAudioFrameCN, last_frame_type_);
@ -335,18 +333,19 @@ TEST_F(AcmReceiverTestOldApi,
EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec)); EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
EXPECT_EQ(-1, receiver_->last_audio_codec_id()); EXPECT_EQ(-1, receiver_->last_audio_codec_id());
n = 0; for (auto id : kCodecId) {
while (kCodecId[n] >= 0) { // Loop over codecs. const CodecIdInst c(id);
// Set DTX off to send audio payload. // Set DTX off to send audio payload.
acm_->SetVAD(false, false, VADAggr); acm_->SetVAD(false, false, VADAggr);
packet_sent_ = false; packet_sent_ = false;
InsertOnePacketOfSilence(kCodecId[n]); InsertOnePacketOfSilence(c.id);
// Sanity check if Actually an audio payload received, and it should be // Sanity check if Actually an audio payload received, and it should be
// of type "speech." // of type "speech."
ASSERT_TRUE(packet_sent_); ASSERT_TRUE(packet_sent_);
ASSERT_EQ(kAudioFrameSpeech, last_frame_type_); 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 // Set VAD on to send DTX. Then check if the "Last Audio codec" returns
// the expected codec. // the expected codec.
@ -355,13 +354,12 @@ TEST_F(AcmReceiverTestOldApi,
// Do as many encoding until a DTX is sent. // Do as many encoding until a DTX is sent.
while (last_frame_type_ != kAudioFrameCN) { while (last_frame_type_ != kAudioFrameCN) {
packet_sent_ = false; packet_sent_ = false;
InsertOnePacketOfSilence(kCodecId[n]); InsertOnePacketOfSilence(c.id);
ASSERT_TRUE(packet_sent_); 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_EQ(0, receiver_->LastAudioCodec(&codec));
EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec)); EXPECT_TRUE(CodecsEqual(c.inst, codec));
++n;
} }
} }

View File

@ -12,8 +12,8 @@
#include "webrtc/base/checks.h" #include "webrtc/base/checks.h"
#include "webrtc/common_types.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/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/clock.h"
#include "webrtc/system_wrappers/interface/trace.h" #include "webrtc/system_wrappers/interface/trace.h"
@ -38,29 +38,32 @@ AudioCodingModule* AudioCodingModule::Create(const Config& config) {
return new acm2::AudioCodingModuleImpl(config); return new acm2::AudioCodingModuleImpl(config);
} }
// Get number of supported codecs
int AudioCodingModule::NumberOfCodecs() { 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) { int AudioCodingModule::Codec(int list_id, CodecInst* codec) {
// Get the codec settings for the codec with the given list ID auto codec_id = acm2::RentACodec::CodecIdFromIndex(list_id);
return acm2::ACMCodecDB::Codec(list_id, codec); 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, int AudioCodingModule::Codec(const char* payload_name,
CodecInst* codec, CodecInst* codec,
int sampling_freq_hz, int sampling_freq_hz,
int channels) { int channels) {
int codec_id; rtc::Maybe<CodecInst> ci = acm2::RentACodec::CodecInstByParams(
// Get the id of the codec from the database.
codec_id = acm2::ACMCodecDB::CodecId(
payload_name, sampling_freq_hz, channels); payload_name, sampling_freq_hz, channels);
if (codec_id < 0) { if (ci) {
// We couldn't find a matching codec, set the parameters to unacceptable *codec = *ci;
return 0;
} else {
// We couldn't find a matching codec, so set the parameters to unacceptable
// values and return. // values and return.
codec->plname[0] = '\0'; codec->plname[0] = '\0';
codec->pltype = -1; codec->pltype = -1;
@ -69,35 +72,26 @@ int AudioCodingModule::Codec(const char* payload_name,
codec->plfreq = 0; codec->plfreq = 0;
return -1; 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 AudioCodingModule::Codec(const char* payload_name,
int sampling_freq_hz, int sampling_freq_hz,
int channels) { 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 // Checks the validity of the parameters of the given codec
bool AudioCodingModule::IsCodecValid(const CodecInst& codec) { bool AudioCodingModule::IsCodecValid(const CodecInst& codec) {
int codec_number = acm2::ACMCodecDB::CodecNumber(codec); bool valid = acm2::RentACodec::IsCodecValid(codec);
if (!valid)
if (codec_number < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, -1, WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, -1,
"Invalid codec setting"); "Invalid codec setting");
return false; return valid;
} else {
return true;
}
} }
} // namespace webrtc } // namespace webrtc

View File

@ -36,20 +36,12 @@ namespace {
// TODO(turajs): the same functionality is used in NetEq. If both classes // TODO(turajs): the same functionality is used in NetEq. If both classes
// need them, make it a static function in ACMCodecDB. // need them, make it a static function in ACMCodecDB.
bool IsCodecRED(const CodecInst* codec) { bool IsCodecRED(const CodecInst& codec) {
return (STR_CASE_CMP(codec->plname, "RED") == 0); return (STR_CASE_CMP(codec.plname, "RED") == 0);
} }
bool IsCodecRED(int index) { bool IsCodecCN(const CodecInst& codec) {
return (IsCodecRED(&ACMCodecDB::database_[index])); return (STR_CASE_CMP(codec.plname, "CN") == 0);
}
bool IsCodecCN(const CodecInst* codec) {
return (STR_CASE_CMP(codec->plname, "CN") == 0);
}
bool IsCodecCN(int index) {
return (IsCodecCN(&ACMCodecDB::database_[index]));
} }
// Stereo-to-mono can be used as in-place. // Stereo-to-mono can be used as in-place.
@ -513,11 +505,12 @@ int AudioCodingModuleImpl::InitializeReceiverSafe() {
receiver_.FlushBuffers(); receiver_.FlushBuffers();
// Register RED and CN. // Register RED and CN.
for (int i = 0; i < ACMCodecDB::kNumCodecs; i++) { auto db = RentACodec::Database();
if (IsCodecRED(i) || IsCodecCN(i)) { for (size_t i = 0; i < db.size(); i++) {
uint8_t pl_type = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype); if (IsCodecRED(db[i]) || IsCodecCN(db[i])) {
int fs = ACMCodecDB::database_[i].plfreq; if (receiver_.AddCodec(static_cast<int>(i),
if (receiver_.AddCodec(i, pl_type, 1, fs, NULL) < 0) { static_cast<uint8_t>(db[i].pltype), 1,
db[i].plfreq, nullptr) < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_, WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
"Cannot register master codec."); "Cannot register master codec.");
return -1; return -1;
@ -561,11 +554,14 @@ int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
return -1; return -1;
} }
int codec_id = ACMCodecDB::ReceiverCodecNumber(codec); auto codec_id =
if (codec_id < 0 || codec_id >= ACMCodecDB::kNumCodecs) { RentACodec::CodecIdByParams(codec.plname, codec.plfreq, codec.channels);
if (!codec_id) {
LOG_F(LS_ERROR) << "Wrong codec params to be registered as receive codec"; LOG_F(LS_ERROR) << "Wrong codec params to be registered as receive codec";
return -1; 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. // Check if the payload-type is valid.
if (!ACMCodecDB::ValidPayloadType(codec.pltype)) { if (!ACMCodecDB::ValidPayloadType(codec.pltype)) {
@ -576,7 +572,7 @@ int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
// Get |decoder| associated with |codec|. |decoder| is NULL if |codec| does // Get |decoder| associated with |codec|. |decoder| is NULL if |codec| does
// not own its decoder. // 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.plfreq,
codec_manager_.GetAudioDecoder(codec)); codec_manager_.GetAudioDecoder(codec));
} }

View File

@ -23,18 +23,10 @@ bool IsCodecRED(const CodecInst& codec) {
return (STR_CASE_CMP(codec.plname, "RED") == 0); return (STR_CASE_CMP(codec.plname, "RED") == 0);
} }
bool IsCodecRED(int index) {
return (IsCodecRED(ACMCodecDB::database_[index]));
}
bool IsCodecCN(const CodecInst& codec) { bool IsCodecCN(const CodecInst& codec) {
return (STR_CASE_CMP(codec.plname, "CN") == 0); 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. // 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 IsValidSendCodec(const CodecInst& send_codec, bool is_primary_encoder) {
int dummy_id = 0; int dummy_id = 0;
@ -164,18 +156,18 @@ CodecManager::CodecManager()
encoder_is_opus_(false) { encoder_is_opus_(false) {
// Register the default payload type for RED and for CNG at sampling rates of // Register the default payload type for RED and for CNG at sampling rates of
// 8, 16, 32 and 48 kHz. // 8, 16, 32 and 48 kHz.
for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) { for (const CodecInst& ci : RentACodec::Database()) {
if (IsCodecRED(i) && ACMCodecDB::database_[i].plfreq == 8000) { if (IsCodecRED(ci) && ci.plfreq == 8000) {
red_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype); red_nb_pltype_ = static_cast<uint8_t>(ci.pltype);
} else if (IsCodecCN(i)) { } else if (IsCodecCN(ci)) {
if (ACMCodecDB::database_[i].plfreq == 8000) { if (ci.plfreq == 8000) {
cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype); cng_nb_pltype_ = static_cast<uint8_t>(ci.pltype);
} else if (ACMCodecDB::database_[i].plfreq == 16000) { } else if (ci.plfreq == 16000) {
cng_wb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype); cng_wb_pltype_ = static_cast<uint8_t>(ci.pltype);
} else if (ACMCodecDB::database_[i].plfreq == 32000) { } else if (ci.plfreq == 32000) {
cng_swb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype); cng_swb_pltype_ = static_cast<uint8_t>(ci.pltype);
} else if (ACMCodecDB::database_[i].plfreq == 48000) { } else if (ci.plfreq == 48000) {
cng_fb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype); cng_fb_pltype_ = static_cast<uint8_t>(ci.pltype);
} }
} }
} }

View File

@ -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

View File

@ -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_

View File

@ -42,6 +42,30 @@
], ],
}, },
'targets': [ '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', 'target_name': 'audio_coding_module',
'type': 'static_library', 'type': 'static_library',
@ -53,6 +77,7 @@
'<(webrtc_root)/common.gyp:webrtc_common', '<(webrtc_root)/common.gyp:webrtc_common',
'<(webrtc_root)/webrtc.gyp:rtc_event_log', '<(webrtc_root)/webrtc.gyp:rtc_event_log',
'neteq', 'neteq',
'rent_a_codec',
], ],
'include_dirs': [ 'include_dirs': [
'interface', 'interface',
@ -67,8 +92,6 @@
], ],
}, },
'sources': [ 'sources': [
'acm2/acm_codec_database.cc',
'acm2/acm_codec_database.h',
'acm2/acm_common_defs.h', 'acm2/acm_common_defs.h',
'acm2/acm_receiver.cc', 'acm2/acm_receiver.cc',
'acm2/acm_receiver.h', 'acm2/acm_receiver.h',