blob: 5ab4ed400a4995500ff4491856dc8324707ab37f [file] [log] [blame] [edit]
/*
* Copyright 2025 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 "pc/typed_codec_vendor.h"
#include <functional>
#include <map>
#include <vector>
#include "absl/strings/string_view.h"
#include "api/audio_codecs/audio_format.h"
#include "api/field_trials_view.h"
#include "api/media_types.h"
#include "media/base/codec.h"
#include "media/base/codec_list.h"
#include "media/base/media_constants.h"
#include "media/base/media_engine.h"
#include "rtc_base/checks.h"
namespace webrtc {
namespace {
// Create the voice codecs. Do not allocate payload types at this time.
std::vector<Codec> CollectAudioCodecs(
const std::vector<AudioCodecSpec>& specs) {
std::vector<Codec> out;
// Only generate CN payload types for these clockrates:
std::map<int, bool, std::greater<int>> generate_cn = {{8000, false}};
// Only generate telephone-event payload types for these clockrates:
std::map<int, bool, std::greater<int>> generate_dtmf = {{8000, false},
{48000, false}};
for (const auto& spec : specs) {
Codec codec = CreateAudioCodec(spec.format);
if (spec.info.supports_network_adaption) {
codec.AddFeedbackParam(
FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
}
if (spec.info.allow_comfort_noise) {
// Generate a CN entry if the decoder allows it and we support the
// clockrate.
auto cn = generate_cn.find(spec.format.clockrate_hz);
if (cn != generate_cn.end()) {
cn->second = true;
}
}
// Generate a telephone-event entry if we support the clockrate.
auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
if (dtmf != generate_dtmf.end()) {
dtmf->second = true;
}
out.push_back(codec);
// TODO(hta): Don't assign RED codecs until we know that the PT for Opus
// is final
if (codec.name == kOpusCodecName) {
// We don't know the PT to put into the RED fmtp parameter yet.
// Leave it out.
Codec red_codec = CreateAudioCodec({kRedCodecName, 48000, 2});
out.push_back(red_codec);
}
}
// Add CN codecs after "proper" audio codecs.
for (const auto& cn : generate_cn) {
if (cn.second) {
Codec cn_codec = CreateAudioCodec({kCnCodecName, cn.first, 1});
out.push_back(cn_codec);
}
}
// Add telephone-event codecs last.
for (const auto& dtmf : generate_dtmf) {
if (dtmf.second) {
Codec dtmf_codec = CreateAudioCodec({kDtmfCodecName, dtmf.first, 1});
out.push_back(dtmf_codec);
}
}
return out;
}
Codecs AudioCodecsFromFactory(const VoiceEngineInterface& voice,
bool is_sender) {
RTC_DCHECK(!is_sender || voice.encoder_factory()) << "No encoder factory";
RTC_DCHECK(is_sender || voice.decoder_factory()) << "No decoder factory";
return CollectAudioCodecs(
is_sender ? voice.encoder_factory()->GetSupportedEncoders()
: voice.decoder_factory()->GetSupportedDecoders());
}
Codecs GetLegacyVideoCodecs(const VideoEngineInterface& video,
bool is_sender,
bool rtx_enabled) {
return is_sender ? video.LegacySendCodecs(rtx_enabled)
: video.LegacyRecvCodecs(rtx_enabled);
}
Codecs GetCodecs(const MediaEngineInterface* media_engine,
MediaType type,
bool is_sender,
bool rtx_enabled,
const FieldTrialsView& trials) {
const VoiceEngineInterface& voice = media_engine->voice();
const VideoEngineInterface& video = media_engine->video();
if (trials.IsEnabled("WebRTC-PayloadTypesInTransport")) {
// Use legacy mechanisms for getting codecs from video engine.
// TODO: https://issues.webrtc.org/360058654 - apply late assign to video.
return (type == MediaType::AUDIO)
? AudioCodecsFromFactory(voice, is_sender)
: GetLegacyVideoCodecs(video, is_sender, rtx_enabled);
}
// Use current mechanisms for getting codecs from media engine.
return (type == MediaType::AUDIO)
? (is_sender ? voice.LegacySendCodecs() : voice.LegacyRecvCodecs())
: GetLegacyVideoCodecs(video, is_sender, rtx_enabled);
}
} // namespace
TypedCodecVendor::TypedCodecVendor(const MediaEngineInterface* media_engine,
MediaType type,
bool is_sender,
bool rtx_enabled,
const FieldTrialsView& trials)
: codecs_(CodecList::CreateFromTrustedData(
GetCodecs(media_engine, type, is_sender, rtx_enabled, trials))) {}
} // namespace webrtc