blob: 3543806b51df45b1001c2720bbe44842f73759e2 [file] [log] [blame]
Niels Möllerbe682d42018-03-27 08:31:45 +02001/*
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 19:08:33 +020012
Johannes Kron20ee02c2021-04-20 15:53:52 +020013#include "absl/strings/match.h"
Joe Downing87bcc1c2022-06-09 15:56:08 -070014#include "api/video_codecs/av1_profile.h"
Johannes Kron20ee02c2021-04-20 15:53:52 +020015#include "api/video_codecs/h264_profile_level_id.h"
16#include "api/video_codecs/video_codec.h"
17#include "api/video_codecs/vp9_profile.h"
18#include "rtc_base/checks.h"
philipele8ed8302019-07-03 11:53:48 +020019#include "rtc_base/strings/string_builder.h"
Niels Möllerbe682d42018-03-27 08:31:45 +020020
21namespace webrtc {
22
Johannes Kron20ee02c2021-04-20 15:53:52 +020023namespace {
24
25std::string H264GetPacketizationModeOrDefault(
26 const SdpVideoFormat::Parameters& params) {
27 constexpr char kH264FmtpPacketizationMode[] = "packetization-mode";
28 const auto it = params.find(kH264FmtpPacketizationMode);
29 if (it != params.end()) {
30 return it->second;
31 }
32 // If packetization-mode is not present, default to "0".
33 // https://tools.ietf.org/html/rfc6184#section-6.2
34 return "0";
35}
36
37bool H264IsSamePacketizationMode(const SdpVideoFormat::Parameters& left,
38 const SdpVideoFormat::Parameters& right) {
39 return H264GetPacketizationModeOrDefault(left) ==
40 H264GetPacketizationModeOrDefault(right);
41}
42
43// Some (video) codecs are actually families of codecs and rely on parameters
44// to distinguish different incompatible family members.
45bool IsSameCodecSpecific(const SdpVideoFormat& format1,
46 const SdpVideoFormat& format2) {
47 // The assumption when calling this function is that the two formats have the
48 // same name.
49 RTC_DCHECK(absl::EqualsIgnoreCase(format1.name, format2.name));
50
51 VideoCodecType codec_type = PayloadStringToCodecType(format1.name);
52 switch (codec_type) {
53 case kVideoCodecH264:
54 return H264IsSameProfile(format1.parameters, format2.parameters) &&
55 H264IsSamePacketizationMode(format1.parameters,
56 format2.parameters);
57 case kVideoCodecVP9:
58 return VP9IsSameProfile(format1.parameters, format2.parameters);
Joe Downing87bcc1c2022-06-09 15:56:08 -070059 case kVideoCodecAV1:
60 return AV1IsSameProfile(format1.parameters, format2.parameters);
Johannes Kron20ee02c2021-04-20 15:53:52 +020061 default:
62 return true;
63 }
64}
65} // namespace
66
Niels Möllerbe682d42018-03-27 08:31:45 +020067SdpVideoFormat::SdpVideoFormat(const std::string& name) : name(name) {}
68
69SdpVideoFormat::SdpVideoFormat(const std::string& name,
70 const Parameters& parameters)
71 : name(name), parameters(parameters) {}
72
Byoungchan Leea1a7c632022-07-05 21:06:28 +090073SdpVideoFormat::SdpVideoFormat(
74 const std::string& name,
75 const Parameters& parameters,
76 const absl::InlinedVector<ScalabilityMode, kScalabilityModeCount>&
77 scalability_modes)
78 : name(name),
79 parameters(parameters),
80 scalability_modes(scalability_modes) {}
81
Niels Möllerbe682d42018-03-27 08:31:45 +020082SdpVideoFormat::SdpVideoFormat(const SdpVideoFormat&) = default;
83SdpVideoFormat::SdpVideoFormat(SdpVideoFormat&&) = default;
Niels Möllerc5d44612018-03-28 09:02:09 +020084SdpVideoFormat& SdpVideoFormat::operator=(const SdpVideoFormat&) = default;
85SdpVideoFormat& SdpVideoFormat::operator=(SdpVideoFormat&&) = default;
Niels Möllerbe682d42018-03-27 08:31:45 +020086
87SdpVideoFormat::~SdpVideoFormat() = default;
88
philipele8ed8302019-07-03 11:53:48 +020089std::string SdpVideoFormat::ToString() const {
90 rtc::StringBuilder builder;
91 builder << "Codec name: " << name << ", parameters: {";
Byoungchan Leea1a7c632022-07-05 21:06:28 +090092 for (const auto& kv : parameters) {
philipele8ed8302019-07-03 11:53:48 +020093 builder << " " << kv.first << "=" << kv.second;
Byoungchan Leea1a7c632022-07-05 21:06:28 +090094 }
95
philipele8ed8302019-07-03 11:53:48 +020096 builder << " }";
Byoungchan Leea1a7c632022-07-05 21:06:28 +090097 if (!scalability_modes.empty()) {
98 builder << ", scalability_modes: [";
99 bool first = true;
100 for (const auto scalability_mode : scalability_modes) {
101 if (first) {
102 first = false;
103 } else {
104 builder << ", ";
105 }
106 builder << ScalabilityModeToString(scalability_mode);
107 }
108 builder << "]";
109 }
philipele8ed8302019-07-03 11:53:48 +0200110
111 return builder.str();
112}
113
Johannes Kron20ee02c2021-04-20 15:53:52 +0200114bool SdpVideoFormat::IsSameCodec(const SdpVideoFormat& other) const {
115 // Two codecs are considered the same if the name matches (case insensitive)
116 // and certain codec-specific parameters match.
117 return absl::EqualsIgnoreCase(name, other.name) &&
118 IsSameCodecSpecific(*this, other);
119}
120
121bool SdpVideoFormat::IsCodecInList(
122 rtc::ArrayView<const webrtc::SdpVideoFormat> formats) const {
123 for (const auto& format : formats) {
124 if (IsSameCodec(format)) {
125 return true;
126 }
127 }
128 return false;
129}
130
Niels Möllerbe682d42018-03-27 08:31:45 +0200131bool operator==(const SdpVideoFormat& a, const SdpVideoFormat& b) {
Byoungchan Leea1a7c632022-07-05 21:06:28 +0900132 return a.name == b.name && a.parameters == b.parameters &&
133 a.scalability_modes == b.scalability_modes;
Niels Möllerbe682d42018-03-27 08:31:45 +0200134}
135
136} // namespace webrtc