WebRTC Audio Encoder/Decoder Factory 的实现
Audio encoder factory 用于創(chuàng)建完成各種 audio codec 編碼的 encoder 對象,audio decoder factory 則用于創(chuàng)建完成各種 audio codec 解碼的 decoder 對象。
WebRTC 的 Audio Encoder Factory 接口的定義(位于 webrtc/src/api/audio_codecs/audio_encoder_factory.h)如下:
namespace webrtc {// A factory that creates AudioEncoders. class AudioEncoderFactory : public rtc::RefCountInterface {public:// Returns a prioritized list of audio codecs, to use for signaling etc.virtual std::vector<AudioCodecSpec> GetSupportedEncoders() = 0;// Returns information about how this format would be encoded, provided it's// supported. More format and format variations may be supported than those// returned by GetSupportedEncoders().virtual absl::optional<AudioCodecInfo> QueryAudioEncoder(const SdpAudioFormat& format) = 0;// Creates an AudioEncoder for the specified format. The encoder will tags its// payloads with the specified payload type. The `codec_pair_id` argument is// used to link encoders and decoders that talk to the same remote entity: if// a AudioEncoderFactory::MakeAudioEncoder() and a// AudioDecoderFactory::MakeAudioDecoder() call receive non-null IDs that// compare equal, the factory implementations may assume that the encoder and// decoder form a pair. (The intended use case for this is to set up// communication between the AudioEncoder and AudioDecoder instances, which is// needed for some codecs with built-in bandwidth adaptation.)//// Note: Implementations need to be robust against combinations other than// one encoder, one decoder getting the same ID; such encoders must still// work.//// TODO(ossu): Try to avoid audio encoders having to know their payload type.virtual std::unique_ptr<AudioEncoder> MakeAudioEncoder(int payload_type,const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) = 0; };} // namespace webrtc直覺上,AudioEncoderFactory 應(yīng)該使用類似于組合模式的方式實(shí)現(xiàn):
- 首先為每個 audio codec 實(shí)現(xiàn)一個 AudioEncoderFactory 的子類實(shí)現(xiàn),比如定義一個 AudioEncoderFactory 的子類實(shí)現(xiàn)用于創(chuàng)建 OPUS 的 encoder,定義一個 AudioEncoderFactory 的子類實(shí)現(xiàn)用于創(chuàng)建 AAC 的 encoder 等;
- 然后創(chuàng)建一個組合的 AudioEncoderFactory 子類實(shí)現(xiàn),作為所有要支持的 audio codec 的 encoder factory 的容器,并借助于各個 audio codec 的 encoder factory 實(shí)現(xiàn)來實(shí)現(xiàn)其接口功能;
- 最后創(chuàng)建一個 AudioEncoderFactory 的工廠方法,該方法中創(chuàng)建組合的 AudioEncoderFactory 子類對象,且創(chuàng)建每個要支持的 audio codec 的 encoder factory 對象并注冊給組合的 AudioEncoderFactory 子類對象,然后返回組合的 AudioEncoderFactory 子類對象。
一個可能的實(shí)現(xiàn)如下。首先是 audio encoder factory 的工廠方法聲明:
#ifndef API_AUDIO_CODECS_FAKE_AUDIO_ENCODER_FACTORY_H_ #define API_AUDIO_CODECS_FAKE_AUDIO_ENCODER_FACTORY_H_#include "api/audio_codecs/audio_encoder_factory.h" #include "rtc_base/scoped_ref_ptr.h"namespace webrtc {class CodecAudioEncoderFactory: public AudioEncoderFactory { public:virtual bool IsSupported(const SdpAudioFormat &format) = 0; };// Creates a new factory that can create the built-in types of audio encoders. // NOTE: This function is still under development and may change without notice. rtc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory();} // namespace webrtc#endif /* API_AUDIO_CODECS_FAKE_AUDIO_ENCODER_FACTORY_H_ */除了 audio encoder factory 的工廠方法聲明外,還創(chuàng)建了一個新的 AudioEncoderFactory 子類,用于描述具體的 audio codec 的 encoder factory 的接口 CodecAudioEncoderFactory, 并為該接口類添加了一個接口函數(shù) IsSupported(),用于判斷一個 encoder factory 對于特定 SdpFormat 的支持情況,以輔助組合的 AudioEncoderFactory 子類對象的實(shí)現(xiàn)。
然后是相關(guān)幾個類的實(shí)現(xiàn):
#include "fake_audio_encoder_factory.h" #include <vector> #include "rtc_base/refcountedobject.h"namespace webrtc {class OpusEncoderFactory : public CodecAudioEncoderFactory { public:std::vector<AudioCodecSpec> GetSupportedEncoders() override {std::vector<AudioCodecSpec> specs;return specs;}absl::optional<AudioCodecInfo> QueryAudioEncoder(const SdpAudioFormat &format)override {return absl::nullopt;}std::unique_ptr<AudioEncoder> MakeAudioEncoder(int payload_type,const SdpAudioFormat &format,absl::optional<AudioCodecPairId> codec_pair_id) override {return nullptr;}bool IsSupported(const SdpAudioFormat &format) override {return true;} };class FakeAudioEncoderFactory: public AudioEncoderFactory { public:std::vector<AudioCodecSpec> GetSupportedEncoders() override {std::vector<AudioCodecSpec> specs;for (auto &factory : audio_encoder_factories) {specs.insert(specs.end(), factory->GetSupportedEncoders().begin(), factory->GetSupportedEncoders().end());}return specs;}absl::optional<AudioCodecInfo> QueryAudioEncoder(const SdpAudioFormat &format)override {for (auto &factory : audio_encoder_factories) {if (factory->IsSupported(format)) {return factory->QueryAudioEncoder(format);}}return absl::nullopt;}std::unique_ptr<AudioEncoder> MakeAudioEncoder(int payload_type,const SdpAudioFormat &format,absl::optional<AudioCodecPairId> codec_pair_id) override {for (auto &factory : audio_encoder_factories) {if (factory->IsSupported(format)) {return factory->MakeAudioEncoder(payload_type, format, codec_pair_id);}}return nullptr;}void AddAudioEncoderFactory(rtc::scoped_refptr<CodecAudioEncoderFactory> factory) {audio_encoder_factories.push_back(factory);}private:std::vector<rtc::scoped_refptr<CodecAudioEncoderFactory>> audio_encoder_factories; };rtc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory() {rtc::scoped_refptr<FakeAudioEncoderFactory> factory(new rtc::RefCountedObject<FakeAudioEncoderFactory>);rtc::scoped_refptr<OpusEncoderFactory> opus_factory(new rtc::RefCountedObject<OpusEncoderFactory>);factory->AddAudioEncoderFactory(opus_factory);return factory; }然而,WebRTC 的 builtin audio encoder factory 沒有以類似的這種方式實(shí)現(xiàn)。
在 webrtc/src/api/audio_codecs/builtin_audio_encoder_factory.h 文件中聲明了用于創(chuàng)建 AudioEncoderFactory 的工廠方法:
namespace webrtc {// Creates a new factory that can create the built-in types of audio encoders. // NOTE: This function is still under development and may change without notice. rtc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory();} // namespace webrtc在 webrtc/src/api/audio_codecs/builtin_audio_encoder_factory.cc 文件中,CreateBuiltinAudioEncoderFactory() 函數(shù)的實(shí)現(xiàn)如下:
namespace webrtc {namespace {// Modify an audio encoder to not advertise support for anything. template <typename T> struct NotAdvertised {using Config = typename T::Config;static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format) {return T::SdpToConfig(audio_format);}static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {// Don't advertise support for anything.}static AudioCodecInfo QueryAudioEncoder(const Config& config) {return T::QueryAudioEncoder(config);}static std::unique_ptr<AudioEncoder> MakeAudioEncoder(const Config& config,int payload_type,absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt) {return T::MakeAudioEncoder(config, payload_type, codec_pair_id);} };} // namespacertc::scoped_refptr<AudioEncoderFactory> CreateBuiltinAudioEncoderFactory() {return CreateAudioEncoderFactory<#if WEBRTC_USE_BUILTIN_OPUSAudioEncoderOpus, #endifAudioEncoderIsac, AudioEncoderG722,#if WEBRTC_USE_BUILTIN_ILBCAudioEncoderIlbc, #endifAudioEncoderG711, NotAdvertised<AudioEncoderL16>>(); }} // namespace webrtcCreateBuiltinAudioEncoderFactory() 函數(shù)的實(shí)現(xiàn)中規(guī)中矩,它調(diào)用了一個模板函數(shù) CreateAudioEncoderFactory() 創(chuàng)建 audio encoder factory,多個帶有 Encoder 字眼的 class 作為模板函數(shù)的類型參數(shù)。
模板函數(shù) CreateAudioEncoderFactory() 的定義位于 webrtc/src/api/audio_codecs/audio_encoder_factory_template.h 文件中:
namespace webrtc {namespace audio_encoder_factory_template_impl {template <typename... Ts> struct Helper;// Base case: 0 template parameters. template <> struct Helper<> {static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {}static absl::optional<AudioCodecInfo> QueryAudioEncoder(const SdpAudioFormat& format) {return absl::nullopt;}static std::unique_ptr<AudioEncoder> MakeAudioEncoder(int payload_type,const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) {return nullptr;} };// Inductive case: Called with n + 1 template parameters; calls subroutines // with n template parameters. template <typename T, typename... Ts> struct Helper<T, Ts...> {static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {T::AppendSupportedEncoders(specs);Helper<Ts...>::AppendSupportedEncoders(specs);}static absl::optional<AudioCodecInfo> QueryAudioEncoder(const SdpAudioFormat& format) {auto opt_config = T::SdpToConfig(format);static_assert(std::is_same<decltype(opt_config),absl::optional<typename T::Config>>::value,"T::SdpToConfig() must return a value of type ""absl::optional<T::Config>");return opt_config ? absl::optional<AudioCodecInfo>(T::QueryAudioEncoder(*opt_config)): Helper<Ts...>::QueryAudioEncoder(format);}static std::unique_ptr<AudioEncoder> MakeAudioEncoder(int payload_type,const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) {auto opt_config = T::SdpToConfig(format);if (opt_config) {return T::MakeAudioEncoder(*opt_config, payload_type, codec_pair_id);} else {return Helper<Ts...>::MakeAudioEncoder(payload_type, format,codec_pair_id);}} };template <typename... Ts> class AudioEncoderFactoryT : public AudioEncoderFactory {public:std::vector<AudioCodecSpec> GetSupportedEncoders() override {std::vector<AudioCodecSpec> specs;Helper<Ts...>::AppendSupportedEncoders(&specs);return specs;}absl::optional<AudioCodecInfo> QueryAudioEncoder(const SdpAudioFormat& format) override {return Helper<Ts...>::QueryAudioEncoder(format);}std::unique_ptr<AudioEncoder> MakeAudioEncoder(int payload_type,const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) override {return Helper<Ts...>::MakeAudioEncoder(payload_type, format, codec_pair_id);} };} // namespace audio_encoder_factory_template_impl// Make an AudioEncoderFactory that can create instances of the given encoders. // // Each encoder type is given as a template argument to the function; it should // be a struct with the following static member functions: // // // Converts |audio_format| to a ConfigType instance. Returns an empty // // optional if |audio_format| doesn't correctly specify an encoder of our // // type. // absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format); // // // Appends zero or more AudioCodecSpecs to the list that will be returned // // by AudioEncoderFactory::GetSupportedEncoders(). // void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs); // // // Returns information about how this format would be encoded. Used to // // implement AudioEncoderFactory::QueryAudioEncoder(). // AudioCodecInfo QueryAudioEncoder(const ConfigType& config); // // // Creates an AudioEncoder for the specified format. Used to implement // // AudioEncoderFactory::MakeAudioEncoder(). // std::unique_ptr<AudioDecoder> MakeAudioEncoder( // const ConfigType& config, // int payload_type, // absl::optional<AudioCodecPairId> codec_pair_id); // // ConfigType should be a type that encapsulates all the settings needed to // create an AudioEncoder. T::Config (where T is the encoder struct) should // either be the config type, or an alias for it. // // Whenever it tries to do something, the new factory will try each of the // encoders in the order they were specified in the template argument list, // stopping at the first one that claims to be able to do the job. // // NOTE: This function is still under development and may change without notice. // // TODO(kwiberg): Point at CreateBuiltinAudioEncoderFactory() for an example of // how it is used. template <typename... Ts> rtc::scoped_refptr<AudioEncoderFactory> CreateAudioEncoderFactory() {// There's no technical reason we couldn't allow zero template parameters,// but such a factory couldn't create any encoders, and callers can do this// by mistake by simply forgetting the <> altogether. So we forbid it in// order to prevent caller foot-shooting.static_assert(sizeof...(Ts) >= 1,"Caller must give at least one template parameter");return rtc::scoped_refptr<AudioEncoderFactory>(new rtc::RefCountedObject<audio_encoder_factory_template_impl::AudioEncoderFactoryT<Ts...>>()); }} // namespace webrtc對照我們前面實(shí)現(xiàn)的 FakeAudioEncoderFactory 來理解 WebRTC 的實(shí)現(xiàn):
- Audio codec encoder 的 factory 的列表不是一個動態(tài)的列表,而是借助于模板機(jī)制構(gòu)建的靜態(tài)的列表;
- 模板類 Helper 充當(dāng)了 audio codec encoder 的 factory 列表的遍歷者和訪問者的角色;
可以具體看一個 Encoder 的實(shí)現(xiàn),如 AudioEncoderOpus 的聲明如下 (位于 webrtc/src/api/audio_codecs/opus/audio_encoder_opus.h):
namespace webrtc {// Opus encoder API for use as a template parameter to // CreateAudioEncoderFactory<...>(). // // NOTE: This struct is still under development and may change without notice. struct AudioEncoderOpus {using Config = AudioEncoderOpusConfig;static absl::optional<AudioEncoderOpusConfig> SdpToConfig(const SdpAudioFormat& audio_format);static void AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs);static AudioCodecInfo QueryAudioEncoder(const AudioEncoderOpusConfig& config);static std::unique_ptr<AudioEncoder> MakeAudioEncoder(const AudioEncoderOpusConfig& config,int payload_type,absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt); };} // namespace webrtcAudioEncoderOpus 的實(shí)現(xiàn)如下 (位于 webrtc/src/api/audio_codecs/opus/audio_encoder_opus.cc):
namespace webrtc {absl::optional<AudioEncoderOpusConfig> AudioEncoderOpus::SdpToConfig(const SdpAudioFormat& format) {return AudioEncoderOpusImpl::SdpToConfig(format); }void AudioEncoderOpus::AppendSupportedEncoders(std::vector<AudioCodecSpec>* specs) {AudioEncoderOpusImpl::AppendSupportedEncoders(specs); }AudioCodecInfo AudioEncoderOpus::QueryAudioEncoder(const AudioEncoderOpusConfig& config) {return AudioEncoderOpusImpl::QueryAudioEncoder(config); }std::unique_ptr<AudioEncoder> AudioEncoderOpus::MakeAudioEncoder(const AudioEncoderOpusConfig& config,int payload_type,absl::optional<AudioCodecPairId> /*codec_pair_id*/) {return AudioEncoderOpusImpl::MakeAudioEncoder(config, payload_type); }} // namespace webrtc盡管 AudioEncoderOpus 名字中只有 encoder 字眼,沒有 factory 字眼,但它卻是個貨真價實(shí)的 encoder factory。
WebRTC 的 decoder factory 的實(shí)現(xiàn)與其 encoder factory 的實(shí)現(xiàn)非常相似。
在 webrtc/src/api/audio_codecs/audio_decoder_factory.h 文件中定義了 AudioDecoderFactory 接口:
namespace webrtc {// A factory that creates AudioDecoders. // NOTE: This class is still under development and may change without notice. class AudioDecoderFactory : public rtc::RefCountInterface {public:virtual std::vector<AudioCodecSpec> GetSupportedDecoders() = 0;virtual bool IsSupportedDecoder(const SdpAudioFormat& format) = 0;// Create a new decoder instance. The `codec_pair_id` argument is used to// link encoders and decoders that talk to the same remote entity; if a// MakeAudioEncoder() and a MakeAudioDecoder() call receive non-null IDs that// compare equal, the factory implementations may assume that the encoder and// decoder form a pair.//// Note: Implementations need to be robust against combinations other than// one encoder, one decoder getting the same ID; such decoders must still// work.virtual std::unique_ptr<AudioDecoder> MakeAudioDecoder(const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) = 0; };} // namespace webrtc文件 webrtc/src/api/audio_codecs/builtin_audio_decoder_factory.h 中聲明了 CreateBuiltinAudioDecoderFactory() 工廠方法:
namespace webrtc {// Creates a new factory that can create the built-in types of audio decoders. // NOTE: This function is still under development and may change without notice. rtc::scoped_refptr<AudioDecoderFactory> CreateBuiltinAudioDecoderFactory();} // namespace webrtc文件 webrtc/src/api/audio_codecs/builtin_audio_decoder_factory.cc 中 CreateBuiltinAudioDecoderFactory() 工廠方法的定義如下:
namespace webrtc {namespace {// Modify an audio decoder to not advertise support for anything. template <typename T> struct NotAdvertised {using Config = typename T::Config;static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format) {return T::SdpToConfig(audio_format);}static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {// Don't advertise support for anything.}static std::unique_ptr<AudioDecoder> MakeAudioDecoder(const Config& config,absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt) {return T::MakeAudioDecoder(config, codec_pair_id);} };} // namespacertc::scoped_refptr<AudioDecoderFactory> CreateBuiltinAudioDecoderFactory() {return CreateAudioDecoderFactory<#if WEBRTC_USE_BUILTIN_OPUSAudioDecoderOpus, #endifAudioDecoderIsac, AudioDecoderG722,#if WEBRTC_USE_BUILTIN_ILBCAudioDecoderIlbc, #endifAudioDecoderG711, NotAdvertised<AudioDecoderL16>>(); }} // namespace webrtc其中的 CreateAudioDecoderFactory() 模板函數(shù)的定義位于 webrtc/src/api/audio_codecs/audio_decoder_factory_template.h:
namespace webrtc {namespace audio_decoder_factory_template_impl {template <typename... Ts> struct Helper;// Base case: 0 template parameters. template <> struct Helper<> {static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {}static bool IsSupportedDecoder(const SdpAudioFormat& format) { return false; }static std::unique_ptr<AudioDecoder> MakeAudioDecoder(const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) {return nullptr;} };// Inductive case: Called with n + 1 template parameters; calls subroutines // with n template parameters. template <typename T, typename... Ts> struct Helper<T, Ts...> {static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {T::AppendSupportedDecoders(specs);Helper<Ts...>::AppendSupportedDecoders(specs);}static bool IsSupportedDecoder(const SdpAudioFormat& format) {auto opt_config = T::SdpToConfig(format);static_assert(std::is_same<decltype(opt_config),absl::optional<typename T::Config>>::value,"T::SdpToConfig() must return a value of type ""absl::optional<T::Config>");return opt_config ? true : Helper<Ts...>::IsSupportedDecoder(format);}static std::unique_ptr<AudioDecoder> MakeAudioDecoder(const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) {auto opt_config = T::SdpToConfig(format);return opt_config ? T::MakeAudioDecoder(*opt_config, codec_pair_id): Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id);} };template <typename... Ts> class AudioDecoderFactoryT : public AudioDecoderFactory {public:std::vector<AudioCodecSpec> GetSupportedDecoders() override {std::vector<AudioCodecSpec> specs;Helper<Ts...>::AppendSupportedDecoders(&specs);return specs;}bool IsSupportedDecoder(const SdpAudioFormat& format) override {return Helper<Ts...>::IsSupportedDecoder(format);}std::unique_ptr<AudioDecoder> MakeAudioDecoder(const SdpAudioFormat& format,absl::optional<AudioCodecPairId> codec_pair_id) override {return Helper<Ts...>::MakeAudioDecoder(format, codec_pair_id);} };} // namespace audio_decoder_factory_template_impl// Make an AudioDecoderFactory that can create instances of the given decoders. // // Each decoder type is given as a template argument to the function; it should // be a struct with the following static member functions: // // // Converts |audio_format| to a ConfigType instance. Returns an empty // // optional if |audio_format| doesn't correctly specify an decoder of our // // type. // absl::optional<ConfigType> SdpToConfig(const SdpAudioFormat& audio_format); // // // Appends zero or more AudioCodecSpecs to the list that will be returned // // by AudioDecoderFactory::GetSupportedDecoders(). // void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs); // // // Creates an AudioDecoder for the specified format. Used to implement // // AudioDecoderFactory::MakeAudioDecoder(). // std::unique_ptr<AudioDecoder> MakeAudioDecoder( // const ConfigType& config, // absl::optional<AudioCodecPairId> codec_pair_id); // // ConfigType should be a type that encapsulates all the settings needed to // create an AudioDecoder. T::Config (where T is the decoder struct) should // either be the config type, or an alias for it. // // Whenever it tries to do something, the new factory will try each of the // decoder types in the order they were specified in the template argument // list, stopping at the first one that claims to be able to do the job. // // NOTE: This function is still under development and may change without notice. // // TODO(kwiberg): Point at CreateBuiltinAudioDecoderFactory() for an example of // how it is used. template <typename... Ts> rtc::scoped_refptr<AudioDecoderFactory> CreateAudioDecoderFactory() {// There's no technical reason we couldn't allow zero template parameters,// but such a factory couldn't create any decoders, and callers can do this// by mistake by simply forgetting the <> altogether. So we forbid it in// order to prevent caller foot-shooting.static_assert(sizeof...(Ts) >= 1,"Caller must give at least one template parameter");return rtc::scoped_refptr<AudioDecoderFactory>(new rtc::RefCountedObject<audio_decoder_factory_template_impl::AudioDecoderFactoryT<Ts...>>()); }} // namespace webrtc一個 audio codec decoder factory 的實(shí)現(xiàn) AudioDecoderOpus 聲明位于 webrtc/src/api/audio_codecs/opus/audio_decoder_opus.h:
namespace webrtc {// Opus decoder API for use as a template parameter to // CreateAudioDecoderFactory<...>(). // // NOTE: This struct is still under development and may change without notice. struct AudioDecoderOpus {struct Config {int num_channels;};static absl::optional<Config> SdpToConfig(const SdpAudioFormat& audio_format);static void AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs);static std::unique_ptr<AudioDecoder> MakeAudioDecoder(Config config,absl::optional<AudioCodecPairId> codec_pair_id = absl::nullopt); };} // namespace webrtcAudioDecoderOpus 的定義位于 webrtc/src/api/audio_codecs/opus/audio_decoder_opus.cc:
namespace webrtc {absl::optional<AudioDecoderOpus::Config> AudioDecoderOpus::SdpToConfig(const SdpAudioFormat& format) {const auto num_channels = [&]() -> absl::optional<int> {auto stereo = format.parameters.find("stereo");if (stereo != format.parameters.end()) {if (stereo->second == "0") {return 1;} else if (stereo->second == "1") {return 2;} else {return absl::nullopt; // Bad stereo parameter.}}return 1; // Default to mono.}();if (STR_CASE_CMP(format.name.c_str(), "opus") == 0 &&format.clockrate_hz == 16000 && format.num_channels == 1 &&num_channels) {return Config{static_cast<int>(format.num_channels)};} else if (STR_CASE_CMP(format.name.c_str(), "opusswb") == 0 &&format.clockrate_hz == 32000 && format.num_channels == 1 &&num_channels) {return Config{static_cast<int>(format.num_channels)};} else if (STR_CASE_CMP(format.name.c_str(), "opusfb") == 0 &&format.clockrate_hz == 48000 && format.num_channels == 2 &&num_channels) {return Config{static_cast<int>(format.num_channels)};} else if (STR_CASE_CMP(format.name.c_str(), "opusfb") == 0 &&format.clockrate_hz == 48000 && format.num_channels == 1 &&num_channels) {return Config{static_cast<int>(format.num_channels)};} else {return absl::nullopt;} }void AudioDecoderOpus::AppendSupportedDecoders(std::vector<AudioCodecSpec>* specs) {AudioCodecInfo opus_info{48000, 1, 64000, 6000, 510000};opus_info.allow_comfort_noise = false;opus_info.supports_network_adaption = true;SdpAudioFormat opus_format({"opus", 48000, 2, {{"minptime", "10"}, {"useinbandfec", "1"}}});specs->push_back({std::move(opus_format), std::move(opus_info)}); }std::unique_ptr<AudioDecoder> AudioDecoderOpus::MakeAudioDecoder(Config config,absl::optional<AudioCodecPairId> /*codec_pair_id*/) {return absl::make_unique<AudioDecoderOpusImpl>(config.num_channels); }} // namespace webrtcWebRTC builtin audio decoder factory 和 builtin audio encoder factory 的實(shí)現(xiàn)套路幾乎完全一樣,此處不再贅述。
Done.
總結(jié)
以上是生活随笔為你收集整理的WebRTC Audio Encoder/Decoder Factory 的实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebRTC 的 log 系统实现分析
- 下一篇: Android OpenSL ES 对象