|  | /* | 
|  | *  Copyright (c) 2012 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 MODULES_AUDIO_CODING_NETEQ_DECODER_DATABASE_H_ | 
|  | #define MODULES_AUDIO_CODING_NETEQ_DECODER_DATABASE_H_ | 
|  |  | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <string> | 
|  |  | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "api/audio_codecs/audio_decoder_factory.h" | 
|  | #include "api/audio_codecs/audio_format.h" | 
|  | #include "api/scoped_refptr.h" | 
|  | #include "modules/audio_coding/codecs/cng/webrtc_cng.h" | 
|  | #include "modules/audio_coding/neteq/packet.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | class DecoderDatabase { | 
|  | public: | 
|  | enum DatabaseReturnCodes { | 
|  | kOK = 0, | 
|  | kInvalidRtpPayloadType = -1, | 
|  | kCodecNotSupported = -2, | 
|  | kInvalidSampleRate = -3, | 
|  | kDecoderExists = -4, | 
|  | kDecoderNotFound = -5, | 
|  | kInvalidPointer = -6 | 
|  | }; | 
|  |  | 
|  | // Class that stores decoder info in the database. | 
|  | class DecoderInfo { | 
|  | public: | 
|  | DecoderInfo(const SdpAudioFormat& audio_format, | 
|  | absl::optional<AudioCodecPairId> codec_pair_id, | 
|  | AudioDecoderFactory* factory, | 
|  | absl::string_view codec_name); | 
|  | explicit DecoderInfo(const SdpAudioFormat& audio_format, | 
|  | absl::optional<AudioCodecPairId> codec_pair_id, | 
|  | AudioDecoderFactory* factory = nullptr); | 
|  | DecoderInfo(DecoderInfo&&); | 
|  | ~DecoderInfo(); | 
|  |  | 
|  | // Get the AudioDecoder object, creating it first if necessary. | 
|  | AudioDecoder* GetDecoder() const; | 
|  |  | 
|  | // Delete the AudioDecoder object, unless it's external. (This means we can | 
|  | // always recreate it later if we need it.) | 
|  | void DropDecoder() const { decoder_.reset(); } | 
|  |  | 
|  | int SampleRateHz() const { | 
|  | if (IsDtmf()) { | 
|  | // DTMF has a 1:1 mapping between clock rate and sample rate. | 
|  | return audio_format_.clockrate_hz; | 
|  | } | 
|  | const AudioDecoder* decoder = GetDecoder(); | 
|  | RTC_DCHECK_EQ(1, !!decoder + !!cng_decoder_); | 
|  | return decoder ? decoder->SampleRateHz() : cng_decoder_->sample_rate_hz; | 
|  | } | 
|  |  | 
|  | const SdpAudioFormat& GetFormat() const { return audio_format_; } | 
|  |  | 
|  | // Returns true if the decoder's format is comfort noise. | 
|  | bool IsComfortNoise() const { | 
|  | RTC_DCHECK_EQ(!!cng_decoder_, subtype_ == Subtype::kComfortNoise); | 
|  | return subtype_ == Subtype::kComfortNoise; | 
|  | } | 
|  |  | 
|  | // Returns true if the decoder's format is DTMF. | 
|  | bool IsDtmf() const { return subtype_ == Subtype::kDtmf; } | 
|  |  | 
|  | // Returns true if the decoder's format is RED. | 
|  | bool IsRed() const { return subtype_ == Subtype::kRed; } | 
|  |  | 
|  | // Returns true if the decoder's format is named `name`. | 
|  | bool IsType(absl::string_view name) const; | 
|  |  | 
|  | const std::string& get_name() const { return name_; } | 
|  |  | 
|  | private: | 
|  | // TODO(ossu): `name_` is kept here while we retain the old external | 
|  | //             decoder interface. Remove this once using an | 
|  | //             AudioDecoderFactory has supplanted the old functionality. | 
|  | const std::string name_; | 
|  |  | 
|  | const SdpAudioFormat audio_format_; | 
|  | const absl::optional<AudioCodecPairId> codec_pair_id_; | 
|  | AudioDecoderFactory* const factory_; | 
|  | mutable std::unique_ptr<AudioDecoder> decoder_; | 
|  |  | 
|  | // Set iff this is a comfort noise decoder. | 
|  | struct CngDecoder { | 
|  | static absl::optional<CngDecoder> Create(const SdpAudioFormat& format); | 
|  | int sample_rate_hz; | 
|  | }; | 
|  | const absl::optional<CngDecoder> cng_decoder_; | 
|  |  | 
|  | enum class Subtype : int8_t { kNormal, kComfortNoise, kDtmf, kRed }; | 
|  |  | 
|  | static Subtype SubtypeFromFormat(const SdpAudioFormat& format); | 
|  |  | 
|  | const Subtype subtype_; | 
|  | }; | 
|  |  | 
|  | // Maximum value for 8 bits, and an invalid RTP payload type (since it is | 
|  | // only 7 bits). | 
|  | static const uint8_t kRtpPayloadTypeError = 0xFF; | 
|  |  | 
|  | DecoderDatabase( | 
|  | const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory, | 
|  | absl::optional<AudioCodecPairId> codec_pair_id); | 
|  |  | 
|  | virtual ~DecoderDatabase(); | 
|  |  | 
|  | DecoderDatabase(const DecoderDatabase&) = delete; | 
|  | DecoderDatabase& operator=(const DecoderDatabase&) = delete; | 
|  |  | 
|  | // Returns true if the database is empty. | 
|  | virtual bool Empty() const; | 
|  |  | 
|  | // Returns the number of decoders registered in the database. | 
|  | virtual int Size() const; | 
|  |  | 
|  | // Replaces the existing set of decoders with the given set. Returns the | 
|  | // payload types that were reassigned or removed while doing so. | 
|  | virtual std::vector<int> SetCodecs( | 
|  | const std::map<int, SdpAudioFormat>& codecs); | 
|  |  | 
|  | // Registers a decoder for the given payload type. Returns kOK on success; | 
|  | // otherwise an error code. | 
|  | virtual int RegisterPayload(int rtp_payload_type, | 
|  | const SdpAudioFormat& audio_format); | 
|  |  | 
|  | // Removes the entry for `rtp_payload_type` from the database. | 
|  | // Returns kDecoderNotFound or kOK depending on the outcome of the operation. | 
|  | virtual int Remove(uint8_t rtp_payload_type); | 
|  |  | 
|  | // Remove all entries. | 
|  | virtual void RemoveAll(); | 
|  |  | 
|  | // Returns a pointer to the DecoderInfo struct for `rtp_payload_type`. If | 
|  | // no decoder is registered with that `rtp_payload_type`, NULL is returned. | 
|  | virtual const DecoderInfo* GetDecoderInfo(uint8_t rtp_payload_type) const; | 
|  |  | 
|  | // Sets the active decoder to be `rtp_payload_type`. If this call results in a | 
|  | // change of active decoder, `new_decoder` is set to true. The previous active | 
|  | // decoder's AudioDecoder object is deleted. | 
|  | virtual int SetActiveDecoder(uint8_t rtp_payload_type, bool* new_decoder); | 
|  |  | 
|  | // Returns the current active decoder, or NULL if no active decoder exists. | 
|  | virtual AudioDecoder* GetActiveDecoder() const; | 
|  |  | 
|  | // Sets the active comfort noise decoder to be `rtp_payload_type`. If this | 
|  | // call results in a change of active comfort noise decoder, the previous | 
|  | // active decoder's AudioDecoder object is deleted. | 
|  | virtual int SetActiveCngDecoder(uint8_t rtp_payload_type); | 
|  |  | 
|  | // Returns the current active comfort noise decoder, or NULL if no active | 
|  | // comfort noise decoder exists. | 
|  | virtual ComfortNoiseDecoder* GetActiveCngDecoder() const; | 
|  |  | 
|  | // The following are utility methods: they will look up DecoderInfo through | 
|  | // GetDecoderInfo and call the respective method on that info object, if it | 
|  | // exists. | 
|  |  | 
|  | // Returns a pointer to the AudioDecoder object associated with | 
|  | // `rtp_payload_type`, or NULL if none is registered. If the AudioDecoder | 
|  | // object does not exist for that decoder, the object is created. | 
|  | AudioDecoder* GetDecoder(uint8_t rtp_payload_type) const; | 
|  |  | 
|  | // Returns true if `rtp_payload_type` is registered as comfort noise. | 
|  | bool IsComfortNoise(uint8_t rtp_payload_type) const; | 
|  |  | 
|  | // Returns true if `rtp_payload_type` is registered as DTMF. | 
|  | bool IsDtmf(uint8_t rtp_payload_type) const; | 
|  |  | 
|  | // Returns true if `rtp_payload_type` is registered as RED. | 
|  | bool IsRed(uint8_t rtp_payload_type) const; | 
|  |  | 
|  | // Returns kOK if all packets in `packet_list` carry payload types that are | 
|  | // registered in the database. Otherwise, returns kDecoderNotFound. | 
|  | int CheckPayloadTypes(const PacketList& packet_list) const; | 
|  |  | 
|  | private: | 
|  | typedef std::map<uint8_t, DecoderInfo> DecoderMap; | 
|  |  | 
|  | DecoderMap decoders_; | 
|  | int active_decoder_type_; | 
|  | int active_cng_decoder_type_; | 
|  | mutable std::unique_ptr<ComfortNoiseDecoder> active_cng_decoder_; | 
|  | rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_; | 
|  | const absl::optional<AudioCodecPairId> codec_pair_id_; | 
|  | }; | 
|  |  | 
|  | }  // namespace webrtc | 
|  | #endif  // MODULES_AUDIO_CODING_NETEQ_DECODER_DATABASE_H_ |