kwiberg 6030a129c0 Pass ownership of external encoders to the ACM
We want this because otherwise the ACM uses its mutex to protect an
encoder that's owned by someone else. That someone else may easily
slip up and delete or otherwise touch the encoder before making sure
that the ACM has stopped using it, bypassing the lock.

BUG=webrtc:5028

Review URL: https://codereview.webrtc.org/1702943002

Cr-Commit-Position: refs/heads/master@{#11909}
2016-03-08 14:01:37 +00:00

244 lines
7.0 KiB
C++

/*
* 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_ACM2_RENT_A_CODEC_H_
#define WEBRTC_MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
#include <stddef.h>
#include <map>
#include <memory>
#include "webrtc/base/array_view.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/optional.h"
#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
#include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h"
#include "webrtc/typedefs.h"
#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
#include "webrtc/modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
#else
// Dummy implementation, for when we don't have iSAC.
namespace webrtc {
class LockedIsacBandwidthInfo {};
}
#endif
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
};
enum class NetEqDecoder {
kDecoderPCMu,
kDecoderPCMa,
kDecoderPCMu_2ch,
kDecoderPCMa_2ch,
kDecoderILBC,
kDecoderISAC,
kDecoderISACswb,
kDecoderPCM16B,
kDecoderPCM16Bwb,
kDecoderPCM16Bswb32kHz,
kDecoderPCM16Bswb48kHz,
kDecoderPCM16B_2ch,
kDecoderPCM16Bwb_2ch,
kDecoderPCM16Bswb32kHz_2ch,
kDecoderPCM16Bswb48kHz_2ch,
kDecoderPCM16B_5ch,
kDecoderG722,
kDecoderG722_2ch,
kDecoderRED,
kDecoderAVT,
kDecoderCNGnb,
kDecoderCNGwb,
kDecoderCNGswb32kHz,
kDecoderCNGswb48kHz,
kDecoderArbitrary,
kDecoderOpus,
kDecoderOpus_2ch,
};
static inline size_t NumberOfCodecs() {
return static_cast<size_t>(CodecId::kNumCodecs);
}
static inline rtc::Optional<int> CodecIndexFromId(CodecId codec_id) {
const int i = static_cast<int>(codec_id);
return i >= 0 && i < static_cast<int>(NumberOfCodecs())
? rtc::Optional<int>(i)
: rtc::Optional<int>();
}
static inline rtc::Optional<CodecId> CodecIdFromIndex(int codec_index) {
return static_cast<size_t>(codec_index) < NumberOfCodecs()
? rtc::Optional<RentACodec::CodecId>(
static_cast<RentACodec::CodecId>(codec_index))
: rtc::Optional<RentACodec::CodecId>();
}
static rtc::Optional<CodecId> CodecIdByParams(const char* payload_name,
int sampling_freq_hz,
size_t channels);
static rtc::Optional<CodecInst> CodecInstById(CodecId codec_id);
static rtc::Optional<CodecId> CodecIdByInst(const CodecInst& codec_inst);
static rtc::Optional<CodecInst> CodecInstByParams(const char* payload_name,
int sampling_freq_hz,
size_t channels);
static bool IsCodecValid(const CodecInst& codec_inst);
static inline bool IsPayloadTypeValid(int payload_type) {
return payload_type >= 0 && payload_type <= 127;
}
static rtc::ArrayView<const CodecInst> Database();
static rtc::Optional<bool> IsSupportedNumChannels(CodecId codec_id,
size_t num_channels);
static rtc::Optional<NetEqDecoder> NetEqDecoderFromCodecId(
CodecId codec_id,
size_t num_channels);
// Parse codec_inst and extract payload types. If the given CodecInst was for
// the wrong sort of codec, return kSkip; otherwise, if the rate was illegal,
// return kBadFreq; otherwise, update the given RTP timestamp rate (Hz) ->
// payload type map and return kOk.
enum class RegistrationResult { kOk, kSkip, kBadFreq };
static RegistrationResult RegisterCngPayloadType(std::map<int, int>* pt_map,
const CodecInst& codec_inst);
static RegistrationResult RegisterRedPayloadType(std::map<int, int>* pt_map,
const CodecInst& codec_inst);
RentACodec();
~RentACodec();
// Creates and returns an audio encoder built to the given specification.
// Returns null in case of error.
std::unique_ptr<AudioEncoder> RentEncoder(const CodecInst& codec_inst);
struct StackParameters {
StackParameters();
~StackParameters();
std::unique_ptr<AudioEncoder> speech_encoder;
bool use_codec_fec = false;
bool use_red = false;
bool use_cng = false;
ACMVADMode vad_mode = VADNormal;
// Maps from RTP timestamp rate (in Hz) to payload type.
std::map<int, int> cng_payload_types;
std::map<int, int> red_payload_types;
};
// Creates and returns an audio encoder stack constructed to the given
// specification. If the specification isn't compatible with the encoder, it
// will be changed to match (things will be switched off). The speech encoder
// will be stolen.
std::unique_ptr<AudioEncoder> RentEncoderStack(StackParameters* param);
// Creates and returns an iSAC decoder, which will remain live until the
// Rent-A-Codec is destroyed. Subsequent calls will simply return the same
// object.
AudioDecoder* RentIsacDecoder();
private:
std::unique_ptr<AudioEncoder> speech_encoder_;
std::unique_ptr<AudioEncoder> cng_encoder_;
std::unique_ptr<AudioEncoder> red_encoder_;
std::unique_ptr<AudioDecoder> isac_decoder_;
LockedIsacBandwidthInfo isac_bandwidth_info_;
RTC_DISALLOW_COPY_AND_ASSIGN(RentACodec);
};
} // namespace acm2
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_