blob: 51ae18cd78640d5eba94ef007a76194cef9790ee [file] [log] [blame]
Niels Möllerbe682d42018-03-27 06:31:451/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "api/video_codecs/sdp_video_format.h"
Jonas Olssona4d87372019-07-05 17:08:3312
Johannes Kron20ee02c2021-04-20 13:53:5213#include "absl/strings/match.h"
philipel99c4c732022-10-18 14:05:3814#include "absl/types/optional.h"
15#include "api/array_view.h"
Joe Downing87bcc1c2022-06-09 22:56:0816#include "api/video_codecs/av1_profile.h"
Johannes Kron20ee02c2021-04-20 13:53:5217#include "api/video_codecs/h264_profile_level_id.h"
qwu16ae82df72023-09-20 05:10:3118#ifdef RTC_ENABLE_H265
19#include "api/video_codecs/h265_profile_tier_level.h"
20#endif
Johannes Kron20ee02c2021-04-20 13:53:5221#include "api/video_codecs/video_codec.h"
22#include "api/video_codecs/vp9_profile.h"
23#include "rtc_base/checks.h"
philipel99c4c732022-10-18 14:05:3824#include "rtc_base/logging.h"
philipele8ed8302019-07-03 09:53:4825#include "rtc_base/strings/string_builder.h"
Niels Möllerbe682d42018-03-27 06:31:4526
27namespace webrtc {
28
Johannes Kron20ee02c2021-04-20 13:53:5229namespace {
30
Mirko Bonadei6c9c9582023-12-13 16:26:5731std::string H264GetPacketizationModeOrDefault(
32 const SdpVideoFormat::Parameters& params) {
Johannes Kron20ee02c2021-04-20 13:53:5233 constexpr char kH264FmtpPacketizationMode[] = "packetization-mode";
34 const auto it = params.find(kH264FmtpPacketizationMode);
35 if (it != params.end()) {
36 return it->second;
37 }
38 // If packetization-mode is not present, default to "0".
39 // https://tools.ietf.org/html/rfc6184#section-6.2
40 return "0";
41}
42
Mirko Bonadei6c9c9582023-12-13 16:26:5743bool H264IsSamePacketizationMode(const SdpVideoFormat::Parameters& left,
44 const SdpVideoFormat::Parameters& right) {
Johannes Kron20ee02c2021-04-20 13:53:5245 return H264GetPacketizationModeOrDefault(left) ==
46 H264GetPacketizationModeOrDefault(right);
47}
48
49// Some (video) codecs are actually families of codecs and rely on parameters
50// to distinguish different incompatible family members.
51bool IsSameCodecSpecific(const SdpVideoFormat& format1,
52 const SdpVideoFormat& format2) {
53 // The assumption when calling this function is that the two formats have the
54 // same name.
55 RTC_DCHECK(absl::EqualsIgnoreCase(format1.name, format2.name));
56
57 VideoCodecType codec_type = PayloadStringToCodecType(format1.name);
58 switch (codec_type) {
59 case kVideoCodecH264:
60 return H264IsSameProfile(format1.parameters, format2.parameters) &&
61 H264IsSamePacketizationMode(format1.parameters,
62 format2.parameters);
63 case kVideoCodecVP9:
64 return VP9IsSameProfile(format1.parameters, format2.parameters);
Joe Downing87bcc1c2022-06-09 22:56:0865 case kVideoCodecAV1:
66 return AV1IsSameProfile(format1.parameters, format2.parameters);
qwu16ae82df72023-09-20 05:10:3167#ifdef RTC_ENABLE_H265
68 case kVideoCodecH265:
69 return H265IsSameProfileTierLevel(format1.parameters, format2.parameters);
70#endif
Johannes Kron20ee02c2021-04-20 13:53:5271 default:
72 return true;
73 }
74}
75} // namespace
76
Niels Möllerbe682d42018-03-27 06:31:4577SdpVideoFormat::SdpVideoFormat(const std::string& name) : name(name) {}
78
79SdpVideoFormat::SdpVideoFormat(const std::string& name,
Mirko Bonadei6c9c9582023-12-13 16:26:5780 const Parameters& parameters)
Niels Möllerbe682d42018-03-27 06:31:4581 : name(name), parameters(parameters) {}
82
Byoungchan Leea1a7c632022-07-05 12:06:2883SdpVideoFormat::SdpVideoFormat(
84 const std::string& name,
Mirko Bonadei6c9c9582023-12-13 16:26:5785 const Parameters& parameters,
Byoungchan Leea1a7c632022-07-05 12:06:2886 const absl::InlinedVector<ScalabilityMode, kScalabilityModeCount>&
87 scalability_modes)
88 : name(name),
89 parameters(parameters),
90 scalability_modes(scalability_modes) {}
91
Niels Möllerbe682d42018-03-27 06:31:4592SdpVideoFormat::SdpVideoFormat(const SdpVideoFormat&) = default;
93SdpVideoFormat::SdpVideoFormat(SdpVideoFormat&&) = default;
Niels Möllerc5d44612018-03-28 07:02:0994SdpVideoFormat& SdpVideoFormat::operator=(const SdpVideoFormat&) = default;
95SdpVideoFormat& SdpVideoFormat::operator=(SdpVideoFormat&&) = default;
Niels Möllerbe682d42018-03-27 06:31:4596
97SdpVideoFormat::~SdpVideoFormat() = default;
98
philipele8ed8302019-07-03 09:53:4899std::string SdpVideoFormat::ToString() const {
100 rtc::StringBuilder builder;
101 builder << "Codec name: " << name << ", parameters: {";
Byoungchan Leea1a7c632022-07-05 12:06:28102 for (const auto& kv : parameters) {
philipele8ed8302019-07-03 09:53:48103 builder << " " << kv.first << "=" << kv.second;
Byoungchan Leea1a7c632022-07-05 12:06:28104 }
105
philipele8ed8302019-07-03 09:53:48106 builder << " }";
Byoungchan Leea1a7c632022-07-05 12:06:28107 if (!scalability_modes.empty()) {
108 builder << ", scalability_modes: [";
109 bool first = true;
110 for (const auto scalability_mode : scalability_modes) {
111 if (first) {
112 first = false;
113 } else {
114 builder << ", ";
115 }
116 builder << ScalabilityModeToString(scalability_mode);
117 }
118 builder << "]";
119 }
philipele8ed8302019-07-03 09:53:48120
121 return builder.str();
122}
123
Johannes Kron20ee02c2021-04-20 13:53:52124bool SdpVideoFormat::IsSameCodec(const SdpVideoFormat& other) const {
125 // Two codecs are considered the same if the name matches (case insensitive)
126 // and certain codec-specific parameters match.
127 return absl::EqualsIgnoreCase(name, other.name) &&
128 IsSameCodecSpecific(*this, other);
129}
130
131bool SdpVideoFormat::IsCodecInList(
132 rtc::ArrayView<const webrtc::SdpVideoFormat> formats) const {
133 for (const auto& format : formats) {
134 if (IsSameCodec(format)) {
135 return true;
136 }
137 }
138 return false;
139}
140
Niels Möllerbe682d42018-03-27 06:31:45141bool operator==(const SdpVideoFormat& a, const SdpVideoFormat& b) {
Byoungchan Leea1a7c632022-07-05 12:06:28142 return a.name == b.name && a.parameters == b.parameters &&
143 a.scalability_modes == b.scalability_modes;
Niels Möllerbe682d42018-03-27 06:31:45144}
145
philipel99c4c732022-10-18 14:05:38146absl::optional<SdpVideoFormat> FuzzyMatchSdpVideoFormat(
147 rtc::ArrayView<const SdpVideoFormat> supported_formats,
148 const SdpVideoFormat& format) {
149 absl::optional<SdpVideoFormat> res;
150 int best_parameter_match = 0;
151 for (const auto& supported_format : supported_formats) {
152 if (absl::EqualsIgnoreCase(supported_format.name, format.name)) {
153 int matching_parameters = 0;
154 for (const auto& kv : supported_format.parameters) {
155 auto it = format.parameters.find(kv.first);
156 if (it != format.parameters.end() && it->second == kv.second) {
157 matching_parameters += 1;
158 }
159 }
160
161 if (!res || matching_parameters > best_parameter_match) {
162 res = supported_format;
163 best_parameter_match = matching_parameters;
164 }
165 }
166 }
167
168 if (!res) {
169 RTC_LOG(LS_INFO) << "Failed to match SdpVideoFormat " << format.ToString();
170 } else if (*res != format) {
171 RTC_LOG(LS_INFO) << "Matched SdpVideoFormat " << format.ToString()
172 << " with " << res->ToString();
173 }
174
175 return res;
176}
177
Niels Möllerbe682d42018-03-27 06:31:45178} // namespace webrtc