tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

codec_comparators_unittest.cc (27584B)


      1 /*
      2 *  Copyright (c) 2024 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 #include "media/base/codec_comparators.h"
     11 
     12 #include <string>
     13 
     14 #include "api/audio_codecs/audio_format.h"
     15 #include "api/rtp_parameters.h"
     16 #include "api/video_codecs/scalability_mode.h"
     17 #include "api/video_codecs/sdp_video_format.h"
     18 #include "api/video_codecs/vp9_profile.h"
     19 #include "media/base/codec.h"
     20 #include "media/base/media_constants.h"
     21 #include "test/gtest.h"
     22 
     23 namespace webrtc {
     24 
     25 using ::testing::TestWithParam;
     26 using ::testing::ValuesIn;
     27 
     28 TEST(CodecComparatorsTest, CodecMatchesItself) {
     29  Codec codec = CreateVideoCodec("custom");
     30  EXPECT_TRUE(MatchesWithCodecRules(codec, codec));
     31 }
     32 
     33 TEST(CodecComparatorsTest, MismatchedBasicParameters) {
     34  Codec codec = CreateAudioCodec(SdpAudioFormat("opus", 48000, 2));
     35  Codec nonmatch_codec = codec;
     36  nonmatch_codec.name = "g711";
     37  EXPECT_FALSE(MatchesWithCodecRules(nonmatch_codec, codec));
     38  nonmatch_codec = codec;
     39  nonmatch_codec.clockrate = 8000;
     40  EXPECT_FALSE(MatchesWithCodecRules(nonmatch_codec, codec));
     41  nonmatch_codec = codec;
     42  nonmatch_codec.channels = 1;
     43  EXPECT_FALSE(MatchesWithCodecRules(nonmatch_codec, codec));
     44 }
     45 
     46 TEST(CodecComparatorsTest, H264PacketizationModeMismatch) {
     47  Codec pt_mode_1 = CreateVideoCodec(kH264CodecName);
     48  Codec pt_mode_0 = pt_mode_1;
     49  pt_mode_0.SetParam(kH264FmtpPacketizationMode, "0");
     50  EXPECT_FALSE(MatchesWithCodecRules(pt_mode_1, pt_mode_0));
     51  EXPECT_FALSE(MatchesWithCodecRules(pt_mode_0, pt_mode_1));
     52  Codec no_pt_mode = pt_mode_1;
     53  no_pt_mode.RemoveParam(kH264FmtpPacketizationMode);
     54  EXPECT_TRUE(MatchesWithCodecRules(pt_mode_0, no_pt_mode));
     55  EXPECT_TRUE(MatchesWithCodecRules(no_pt_mode, pt_mode_0));
     56  EXPECT_FALSE(MatchesWithCodecRules(no_pt_mode, pt_mode_1));
     57 }
     58 
     59 TEST(CodecComparatorsTest, AudioParametersIgnored) {
     60  // Currently, all parameters on audio codecs are ignored for matching.
     61  Codec basic_opus = CreateAudioCodec(SdpAudioFormat("opus", 48000, 2));
     62  Codec opus_with_parameters = basic_opus;
     63  opus_with_parameters.SetParam("stereo", "0");
     64  EXPECT_TRUE(MatchesWithCodecRules(basic_opus, opus_with_parameters));
     65  EXPECT_TRUE(MatchesWithCodecRules(opus_with_parameters, basic_opus));
     66  opus_with_parameters.SetParam("nonsense", "stuff");
     67  EXPECT_TRUE(MatchesWithCodecRules(basic_opus, opus_with_parameters));
     68  EXPECT_TRUE(MatchesWithCodecRules(opus_with_parameters, basic_opus));
     69 }
     70 
     71 TEST(CodecComparatorsTest, StaticPayloadTypesIgnoreName) {
     72  // This is the IANA registered format for PT 8
     73  Codec codec_1 = CreateAudioCodec(8, "pcma", 8000, 1);
     74  Codec codec_2 = CreateAudioCodec(8, "nonsense", 8000, 1);
     75  EXPECT_TRUE(MatchesWithCodecRules(codec_1, codec_2));
     76 }
     77 
     78 TEST(CodecComparatorsTest, MatchesWithReferenceAttributesRed) {
     79  // Test that RED codecs' reference attributes get parsed correctly.
     80  Codec codec_1 = CreateAudioCodec(101, kRedCodecName, 48000, 2);
     81  codec_1.SetParam(kCodecParamNotInNameValueFormat, "100/100");
     82  Codec codec_2 = CreateAudioCodec(102, kRedCodecName, 48000, 2);
     83  codec_2.SetParam(kCodecParamNotInNameValueFormat, "101/101");
     84  // Mixed codecs in RED
     85  Codec codec_3 = CreateAudioCodec(103, kRedCodecName, 48000, 2);
     86  codec_3.SetParam(kCodecParamNotInNameValueFormat, "100/101");
     87  // Identical codecs always match.
     88  EXPECT_TRUE(MatchesWithReferenceAttributes(codec_1, codec_1));
     89  EXPECT_TRUE(MatchesWithReferenceAttributes(codec_2, codec_2));
     90  EXPECT_TRUE(MatchesWithReferenceAttributes(codec_3, codec_3));
     91  // Mismatched reference codec lists.
     92  EXPECT_FALSE(MatchesWithReferenceAttributes(codec_1, codec_2));
     93  EXPECT_FALSE(MatchesWithReferenceAttributes(codec_1, codec_3));
     94  EXPECT_FALSE(MatchesWithReferenceAttributes(codec_2, codec_3));
     95  // Overflow of longer lists are ignored.
     96  // Overlong list - overflow should be ignored.
     97  Codec codec_4 = CreateAudioCodec(103, kRedCodecName, 48000, 2);
     98  codec_4.SetParam(kCodecParamNotInNameValueFormat, "100/100/101/102");
     99  EXPECT_TRUE(MatchesWithReferenceAttributes(codec_4, codec_4));
    100  EXPECT_TRUE(MatchesWithReferenceAttributes(codec_1, codec_4));
    101  // Broken syntax will cause a non-match with anything except itself.
    102  Codec codec_5 = CreateAudioCodec(103, kRedCodecName, 48000, 2);
    103  codec_5.SetParam(kCodecParamNotInNameValueFormat, "");
    104  EXPECT_TRUE(MatchesWithReferenceAttributes(codec_5, codec_5));
    105  EXPECT_FALSE(MatchesWithReferenceAttributes(codec_1, codec_5));
    106 }
    107 
    108 struct TestParams {
    109  std::string name;
    110  SdpVideoFormat codec1;
    111  SdpVideoFormat codec2;
    112  bool expected_result;
    113 };
    114 
    115 using IsSameRtpCodecTest = TestWithParam<TestParams>;
    116 
    117 TEST_P(IsSameRtpCodecTest, IsSameRtpCodec) {
    118  TestParams param = GetParam();
    119  Codec codec1 = CreateVideoCodec(param.codec1);
    120  Codec codec2 = CreateVideoCodec(param.codec2);
    121 
    122  EXPECT_EQ(IsSameRtpCodec(codec1, codec2.ToCodecParameters()),
    123            param.expected_result);
    124 }
    125 
    126 INSTANTIATE_TEST_SUITE_P(
    127    CodecTest,
    128    IsSameRtpCodecTest,
    129    ValuesIn<TestParams>({
    130        {.name = "CodecWithDifferentName",
    131         .codec1 = {"VP9", {}},
    132         .codec2 = {"VP8", {}},
    133         .expected_result = false},
    134        {.name = "Vp8WithoutParameters",
    135         .codec1 = {"vp8", {}},
    136         .codec2 = {"VP8", {}},
    137         .expected_result = true},
    138        {.name = "Vp8WithSameParameters",
    139         .codec1 = {"VP8", {{"x", "1"}}},
    140         .codec2 = {"VP8", {{"x", "1"}}},
    141         .expected_result = true},
    142        {.name = "Vp8WithDifferentParameters",
    143         .codec1 = {"VP8", {}},
    144         .codec2 = {"VP8", {{"x", "1"}}},
    145         .expected_result = false},
    146        {.name = "Av1WithoutParameters",
    147         .codec1 = {"AV1", {}},
    148         .codec2 = {"AV1", {}},
    149         .expected_result = true},
    150        {.name = "Av1WithSameProfile",
    151         .codec1 = {"AV1", SdpVideoFormat::AV1Profile0().parameters},
    152         .codec2 = {"AV1", SdpVideoFormat::AV1Profile0().parameters},
    153         .expected_result = true},
    154        {.name = "Av1WithoutParametersTreatedAsProfile0",
    155         .codec1 = {"AV1", SdpVideoFormat::AV1Profile0().parameters},
    156         .codec2 = {"AV1", {}},
    157         .expected_result = true},
    158        {.name = "Av1WithoutProfileTreatedAsProfile0",
    159         .codec1 = {"AV1", {{kAv1FmtpProfile, "0"}, {"x", "1"}}},
    160         .codec2 = {"AV1", {{"x", "1"}}},
    161         .expected_result = true},
    162        {.name = "Av1WithDifferentProfile",
    163         .codec1 = {"AV1", SdpVideoFormat::AV1Profile0().parameters},
    164         .codec2 = {"AV1", SdpVideoFormat::AV1Profile1().parameters},
    165         .expected_result = false},
    166        {.name = "Av1WithDifferentParameters",
    167         .codec1 = {"AV1", {{kAv1FmtpProfile, "0"}, {"x", "1"}}},
    168         .codec2 = {"AV1", {{kAv1FmtpProfile, "0"}, {"x", "2"}}},
    169         .expected_result = false},
    170        {.name = "Vp9WithSameProfile",
    171         .codec1 = {"VP9", SdpVideoFormat::VP9Profile0().parameters},
    172         .codec2 = {"VP9", SdpVideoFormat::VP9Profile0().parameters},
    173         .expected_result = true},
    174        {.name = "Vp9WithoutProfileTreatedAsProfile0",
    175         .codec1 = {"VP9", {{kVP9FmtpProfileId, "0"}, {"x", "1"}}},
    176         .codec2 = {"VP9", {{"x", "1"}}},
    177         .expected_result = true},
    178        {.name = "Vp9WithDifferentProfile",
    179         .codec1 = {"VP9", SdpVideoFormat::VP9Profile0().parameters},
    180         .codec2 = {"VP9", SdpVideoFormat::VP9Profile1().parameters},
    181         .expected_result = false},
    182        {.name = "H264WithSamePacketizationMode",
    183         .codec1 = {"H264", {{kH264FmtpPacketizationMode, "0"}}},
    184         .codec2 = {"H264", {{kH264FmtpPacketizationMode, "0"}}},
    185         .expected_result = true},
    186        {.name = "H264WithoutPacketizationModeTreatedAsMode0",
    187         .codec1 = {"H264", {{kH264FmtpPacketizationMode, "0"}, {"x", "1"}}},
    188         .codec2 = {"H264", {{"x", "1"}}},
    189         .expected_result = true},
    190        {.name = "H264WithDifferentPacketizationMode",
    191         .codec1 = {"H264", {{kH264FmtpPacketizationMode, "0"}}},
    192         .codec2 = {"H264", {{kH264FmtpPacketizationMode, "1"}}},
    193         .expected_result = false},
    194 #ifdef RTC_ENABLE_H265
    195        {.name = "H265WithSameProfile",
    196         .codec1 = {"H265",
    197                    {{kH265FmtpProfileId, "1"},
    198                     {kH265FmtpTierFlag, "0"},
    199                     {kH265FmtpLevelId, "93"},
    200                     {kH265FmtpTxMode, "SRST"}}},
    201         .codec2 = {"H265",
    202                    {{kH265FmtpProfileId, "1"},
    203                     {kH265FmtpTierFlag, "0"},
    204                     {kH265FmtpLevelId, "93"},
    205                     {kH265FmtpTxMode, "SRST"}}},
    206         .expected_result = true},
    207        {.name = "H265WithoutParametersTreatedAsDefault",
    208         .codec1 = {"H265",
    209                    {{kH265FmtpProfileId, "1"},
    210                     {kH265FmtpTierFlag, "0"},
    211                     {kH265FmtpLevelId, "93"},
    212                     {kH265FmtpTxMode, "SRST"}}},
    213         .codec2 = {"H265", {}},
    214         .expected_result = true},
    215        {.name = "H265WithDifferentProfile",
    216         .codec1 = {"H265",
    217                    {{kH265FmtpProfileId, "1"},
    218                     {kH265FmtpTierFlag, "0"},
    219                     {kH265FmtpLevelId, "93"},
    220                     {kH265FmtpTxMode, "SRST"}}},
    221         .codec2 = {"H265",
    222                    {{kH265FmtpProfileId, "1"},
    223                     {kH265FmtpTierFlag, "1"},
    224                     {kH265FmtpLevelId, "93"},
    225                     {kH265FmtpTxMode, "SRST"}}},
    226         .expected_result = false},
    227 #endif
    228    }),
    229    [](const testing::TestParamInfo<IsSameRtpCodecTest::ParamType>& info) {
    230      return info.param.name;
    231    });
    232 
    233 // For H264, the profile and level IDs are entangled into a single
    234 // "profile-level-id" attribute, so let's test many different versions.
    235 // See https://cconcolato.github.io/media-mime-support/ for inspiration.
    236 TEST(IsSameRtpCodecIgnoringLevelTest, IgnoresH264Levels) {
    237  // AVC Baseline Level 3.1
    238  Codec baseline_3_1 =
    239      CreateVideoCodec(SdpVideoFormat("H264",
    240                                      {{kH264FmtpLevelAsymmetryAllowed, "1"},
    241                                       {kH264FmtpPacketizationMode, "1"},
    242                                       {kH264FmtpProfileLevelId, "42001f"}},
    243                                      {ScalabilityMode::kL1T1}));
    244  // AVC Baseline Level 5.2
    245  Codec baseline_5_2 =
    246      CreateVideoCodec(SdpVideoFormat("H264",
    247                                      {{kH264FmtpLevelAsymmetryAllowed, "1"},
    248                                       {kH264FmtpPacketizationMode, "1"},
    249                                       {kH264FmtpProfileLevelId, "420034"}},
    250                                      {ScalabilityMode::kL1T1}));
    251  // AVC High Level 3.1
    252  Codec high_3_1 =
    253      CreateVideoCodec(SdpVideoFormat("H264",
    254                                      {{kH264FmtpLevelAsymmetryAllowed, "1"},
    255                                       {kH264FmtpPacketizationMode, "1"},
    256                                       {kH264FmtpProfileLevelId, "64001f"}},
    257                                      {ScalabilityMode::kL1T1}));
    258  // AVC High Level 5.2
    259  Codec high_5_2 =
    260      CreateVideoCodec(SdpVideoFormat("H264",
    261                                      {{kH264FmtpLevelAsymmetryAllowed, "1"},
    262                                       {kH264FmtpPacketizationMode, "1"},
    263                                       {kH264FmtpProfileLevelId, "640034"}},
    264                                      {ScalabilityMode::kL1T1}));
    265  // AVC High 4:4:4 Predictive Level 3.1
    266  Codec high_444_predictive_3_1 =
    267      CreateVideoCodec(SdpVideoFormat("H264",
    268                                      {{kH264FmtpLevelAsymmetryAllowed, "1"},
    269                                       {kH264FmtpPacketizationMode, "1"},
    270                                       {kH264FmtpProfileLevelId, "f4001f"}},
    271                                      {ScalabilityMode::kL1T1}));
    272 
    273  // AVC Baseline Level 5.2 is compatible with AVC Baseline Level 3.1.
    274  EXPECT_TRUE(IsSameRtpCodecIgnoringLevel(baseline_5_2,
    275                                          baseline_3_1.ToCodecParameters()));
    276  // AVC High is NOT compatible with AVC Baseline.
    277  EXPECT_FALSE(
    278      IsSameRtpCodecIgnoringLevel(baseline_3_1, high_3_1.ToCodecParameters()));
    279  EXPECT_FALSE(
    280      IsSameRtpCodecIgnoringLevel(baseline_3_1, high_5_2.ToCodecParameters()));
    281  EXPECT_FALSE(
    282      IsSameRtpCodecIgnoringLevel(baseline_5_2, high_3_1.ToCodecParameters()));
    283  EXPECT_FALSE(
    284      IsSameRtpCodecIgnoringLevel(baseline_5_2, high_5_2.ToCodecParameters()));
    285  // AVC High 5.2 is compatible with AVC High 3.1
    286  EXPECT_TRUE(
    287      IsSameRtpCodecIgnoringLevel(high_5_2, high_3_1.ToCodecParameters()));
    288  // 4:4:4 Predictive is NOT compatible with either High or Baseline.
    289  EXPECT_FALSE(IsSameRtpCodecIgnoringLevel(high_444_predictive_3_1,
    290                                           high_3_1.ToCodecParameters()));
    291  EXPECT_FALSE(IsSameRtpCodecIgnoringLevel(high_444_predictive_3_1,
    292                                           high_5_2.ToCodecParameters()));
    293  EXPECT_FALSE(IsSameRtpCodecIgnoringLevel(high_444_predictive_3_1,
    294                                           baseline_3_1.ToCodecParameters()));
    295  EXPECT_FALSE(IsSameRtpCodecIgnoringLevel(high_444_predictive_3_1,
    296                                           baseline_3_1.ToCodecParameters()));
    297 }
    298 
    299 #ifdef RTC_ENABLE_H265
    300 // For H265, the "profile-id" and "level-id" are separate so test can be simple.
    301 // The level-id value for Level X.Y is calculated as (X * 10 + Y) * 3.
    302 // The lowest Level, 1.0, is thus (1 * 10 + 0) * 3 = 30.
    303 TEST(IsSameRtpCodecIgnoringLevelTest, IgnoresH265Levels) {
    304  // Profile 1, Level 5.2
    305  Codec profile_1_level_5_2 =
    306      CreateVideoCodec(SdpVideoFormat("H265",
    307                                      {{kH265FmtpProfileId, "1"},
    308                                       {kH265FmtpTierFlag, "0"},
    309                                       {kH265FmtpLevelId, "156"},
    310                                       {kH265FmtpTxMode, "SRST"}},
    311                                      {ScalabilityMode::kL1T1}));
    312  // Profile 1, Level 6.0
    313  Codec profile_1_level_6_0 =
    314      CreateVideoCodec(SdpVideoFormat("H265",
    315                                      {{kH265FmtpProfileId, "1"},
    316                                       {kH265FmtpTierFlag, "0"},
    317                                       {kH265FmtpLevelId, "180"},
    318                                       {kH265FmtpTxMode, "SRST"}},
    319                                      {ScalabilityMode::kL1T1}));
    320  // Profile 2, Level 6.0
    321  Codec profile_2_level_6_0 =
    322      CreateVideoCodec(SdpVideoFormat("H265",
    323                                      {{kH265FmtpProfileId, "2"},
    324                                       {kH265FmtpTierFlag, "0"},
    325                                       {kH265FmtpLevelId, "180"},
    326                                       {kH265FmtpTxMode, "SRST"}},
    327                                      {ScalabilityMode::kL1T1}));
    328  // Profile 1 codecs are compatible with each other.
    329  EXPECT_TRUE(IsSameRtpCodecIgnoringLevel(
    330      profile_1_level_5_2, profile_1_level_6_0.ToCodecParameters()));
    331  // Profile 2 codecs are NOT compatible with profile 1 codecs.
    332  EXPECT_FALSE(IsSameRtpCodecIgnoringLevel(
    333      profile_2_level_6_0, profile_1_level_5_2.ToCodecParameters()));
    334  EXPECT_FALSE(IsSameRtpCodecIgnoringLevel(
    335      profile_2_level_6_0, profile_1_level_6_0.ToCodecParameters()));
    336 }
    337 #endif  // RTC_ENABLE_H265
    338 
    339 TEST(CodecTest, TestCodecMatches) {
    340  // Test a codec with a static payload type.
    341  Codec c0 = CreateAudioCodec(34, "A", 44100, 1);
    342  EXPECT_TRUE(c0.Matches(CreateAudioCodec(34, "", 44100, 1)));
    343  EXPECT_TRUE(c0.Matches(CreateAudioCodec(34, "", 44100, 0)));
    344  EXPECT_TRUE(c0.Matches(CreateAudioCodec(34, "", 44100, 0)));
    345  EXPECT_FALSE(c0.Matches(CreateAudioCodec(96, "A", 44100, 1)));
    346  EXPECT_FALSE(c0.Matches(CreateAudioCodec(96, "", 44100, 1)));
    347  EXPECT_FALSE(c0.Matches(CreateAudioCodec(95, "", 55100, 1)));
    348  EXPECT_FALSE(c0.Matches(CreateAudioCodec(95, "", 44100, 1)));
    349  EXPECT_FALSE(c0.Matches(CreateAudioCodec(95, "", 44100, 2)));
    350  EXPECT_FALSE(c0.Matches(CreateAudioCodec(95, "", 55100, 2)));
    351 
    352  // Test a codec with a dynamic payload type.
    353  Codec c1 = CreateAudioCodec(96, "A", 44100, 1);
    354  EXPECT_TRUE(c1.Matches(CreateAudioCodec(96, "A", 44100, 0)));
    355  EXPECT_TRUE(c1.Matches(CreateAudioCodec(97, "A", 44100, 0)));
    356  EXPECT_TRUE(c1.Matches(CreateAudioCodec(96, "a", 44100, 0)));
    357  EXPECT_TRUE(c1.Matches(CreateAudioCodec(97, "a", 44100, 0)));
    358  EXPECT_TRUE(c1.Matches(CreateAudioCodec(35, "a", 44100, 0)));
    359  EXPECT_TRUE(c1.Matches(CreateAudioCodec(42, "a", 44100, 0)));
    360  EXPECT_TRUE(c1.Matches(CreateAudioCodec(65, "a", 44100, 0)));
    361  EXPECT_FALSE(c1.Matches(CreateAudioCodec(95, "A", 44100, 0)));
    362  EXPECT_FALSE(c1.Matches(CreateAudioCodec(34, "A", 44100, 0)));
    363  EXPECT_FALSE(c1.Matches(CreateAudioCodec(96, "", 44100, 2)));
    364  EXPECT_FALSE(c1.Matches(CreateAudioCodec(96, "A", 55100, 1)));
    365 
    366  // Test a codec with a dynamic payload type, and auto bitrate.
    367  Codec c2 = CreateAudioCodec(97, "A", 16000, 1);
    368  // Use default bitrate.
    369  EXPECT_TRUE(c2.Matches(CreateAudioCodec(97, "A", 16000, 1)));
    370  EXPECT_TRUE(c2.Matches(CreateAudioCodec(97, "A", 16000, 0)));
    371  // Use explicit bitrate.
    372  EXPECT_TRUE(c2.Matches(CreateAudioCodec(97, "A", 16000, 1)));
    373  // Backward compatibility with clients that might send "-1" (for default).
    374  EXPECT_TRUE(c2.Matches(CreateAudioCodec(97, "A", 16000, 1)));
    375 
    376  // Stereo doesn't match channels = 0.
    377  Codec c3 = CreateAudioCodec(96, "A", 44100, 2);
    378  EXPECT_TRUE(c3.Matches(CreateAudioCodec(96, "A", 44100, 2)));
    379  EXPECT_FALSE(c3.Matches(CreateAudioCodec(96, "A", 44100, 1)));
    380  EXPECT_FALSE(c3.Matches(CreateAudioCodec(96, "A", 44100, 0)));
    381 }
    382 
    383 TEST(CodecTest, TestOpusAudioCodecWithDifferentParameters) {
    384  Codec opus_with_fec = CreateAudioCodec(96, "opus", 48000, 2);
    385  opus_with_fec.params["useinbandfec"] = "1";
    386  Codec opus_without_fec = CreateAudioCodec(96, "opus", 48000, 2);
    387 
    388  EXPECT_TRUE(opus_with_fec != opus_without_fec);
    389  // Matches does not compare parameters for audio.
    390  EXPECT_TRUE(opus_with_fec.Matches(opus_without_fec));
    391 
    392  RtpCodecParameters rtp_opus_with_fec = opus_with_fec.ToCodecParameters();
    393  // MatchesRtpCodec takes parameters into account.
    394  EXPECT_TRUE(opus_with_fec.MatchesRtpCodec(rtp_opus_with_fec));
    395  EXPECT_FALSE(opus_without_fec.MatchesRtpCodec(rtp_opus_with_fec));
    396 }
    397 
    398 TEST(CodecTest, TestVideoCodecMatches) {
    399  // Test a codec with a static payload type.
    400  Codec c0 = CreateVideoCodec(34, "V");
    401  EXPECT_TRUE(c0.Matches(CreateVideoCodec(34, "")));
    402  EXPECT_FALSE(c0.Matches(CreateVideoCodec(96, "")));
    403  EXPECT_FALSE(c0.Matches(CreateVideoCodec(96, "V")));
    404 
    405  // Test a codec with a dynamic payload type.
    406  Codec c1 = CreateVideoCodec(96, "V");
    407  EXPECT_TRUE(c1.Matches(CreateVideoCodec(96, "V")));
    408  EXPECT_TRUE(c1.Matches(CreateVideoCodec(97, "V")));
    409  EXPECT_TRUE(c1.Matches(CreateVideoCodec(96, "v")));
    410  EXPECT_TRUE(c1.Matches(CreateVideoCodec(97, "v")));
    411  EXPECT_TRUE(c1.Matches(CreateVideoCodec(35, "v")));
    412  EXPECT_TRUE(c1.Matches(CreateVideoCodec(42, "v")));
    413  EXPECT_TRUE(c1.Matches(CreateVideoCodec(65, "v")));
    414  EXPECT_FALSE(c1.Matches(CreateVideoCodec(96, "")));
    415  EXPECT_FALSE(c1.Matches(CreateVideoCodec(95, "V")));
    416  EXPECT_FALSE(c1.Matches(CreateVideoCodec(34, "V")));
    417 }
    418 
    419 TEST(CodecTest, TestVideoCodecMatchesWithDifferentPacketization) {
    420  Codec c0 = CreateVideoCodec(100, kVp8CodecName);
    421  Codec c1 = CreateVideoCodec(101, kVp8CodecName);
    422  c1.packetization = "raw";
    423 
    424  EXPECT_TRUE(c0.Matches(c1));
    425  EXPECT_TRUE(c1.Matches(c0));
    426 }
    427 
    428 // AV1 codecs do not compare profile information.
    429 TEST(CodecTest, TestAV1CodecMatches) {
    430  const char kProfile0[] = "0";
    431  const char kProfile1[] = "1";
    432  const char kProfile2[] = "2";
    433 
    434  Codec c_no_profile = CreateVideoCodec(95, kAv1CodecName);
    435  Codec c_profile0 = CreateVideoCodec(95, kAv1CodecName);
    436  c_profile0.params[kAv1FmtpProfile] = kProfile0;
    437  Codec c_profile1 = CreateVideoCodec(95, kAv1CodecName);
    438  c_profile1.params[kAv1FmtpProfile] = kProfile1;
    439  Codec c_profile2 = CreateVideoCodec(95, kAv1CodecName);
    440  c_profile2.params[kAv1FmtpProfile] = kProfile2;
    441 
    442  // An AV1 entry with no profile specified should be treated as profile-0.
    443  EXPECT_TRUE(c_profile0.Matches(c_no_profile));
    444 
    445  {
    446    // Two AV1 entries without a profile specified are treated as duplicates.
    447    Codec c_no_profile_eq = CreateVideoCodec(95, kAv1CodecName);
    448    EXPECT_TRUE(c_no_profile.Matches(c_no_profile_eq));
    449  }
    450 
    451  {
    452    // Two AV1 entries with profile 0 specified are treated as duplicates.
    453    Codec c_profile0_eq = CreateVideoCodec(95, kAv1CodecName);
    454    c_profile0_eq.params[kAv1FmtpProfile] = kProfile0;
    455    EXPECT_TRUE(c_profile0.Matches(c_profile0_eq));
    456  }
    457 
    458  {
    459    // Two AV1 entries with profile 1 specified are treated as duplicates.
    460    Codec c_profile1_eq = CreateVideoCodec(95, kAv1CodecName);
    461    c_profile1_eq.params[kAv1FmtpProfile] = kProfile1;
    462    EXPECT_TRUE(c_profile1.Matches(c_profile1_eq));
    463  }
    464 
    465  // AV1 entries with different profiles (0 and 1) are seen as distinct.
    466  EXPECT_FALSE(c_profile0.Matches(c_profile1));
    467  EXPECT_FALSE(c_no_profile.Matches(c_profile1));
    468 
    469  // AV1 entries with different profiles (0 and 2) are seen as distinct.
    470  EXPECT_FALSE(c_profile0.Matches(c_profile2));
    471  EXPECT_FALSE(c_no_profile.Matches(c_profile2));
    472 
    473  // AV1 entries with same profile and different tier are seen as equal.
    474  Codec c_tier0 = CreateVideoCodec(95, kAv1CodecName);
    475  c_tier0.params[kAv1FmtpProfile] = kProfile0;
    476  c_tier0.params[kAv1FmtpTier] = "0";
    477  Codec c_tier1 = CreateVideoCodec(95, kAv1CodecName);
    478  c_tier1.params[kAv1FmtpProfile] = kProfile0;
    479  c_tier1.params[kAv1FmtpTier] = "1";
    480  EXPECT_TRUE(c_tier0.Matches(c_tier1));
    481 
    482  // AV1 entries with profile and different level are seen as equal.
    483  Codec c_level0 = CreateVideoCodec(95, kAv1CodecName);
    484  c_level0.params[kAv1FmtpProfile] = kProfile0;
    485  c_level0.params[kAv1FmtpLevelIdx] = "0";
    486  Codec c_level1 = CreateVideoCodec(95, kAv1CodecName);
    487  c_level1.params[kAv1FmtpProfile] = kProfile0;
    488  c_level1.params[kAv1FmtpLevelIdx] = "1";
    489  EXPECT_TRUE(c_level0.Matches(c_level1));
    490 }
    491 
    492 // VP9 codecs compare profile information.
    493 TEST(CodecTest, TestVP9CodecMatches) {
    494  const char kProfile0[] = "0";
    495  const char kProfile2[] = "2";
    496 
    497  Codec c_no_profile = CreateVideoCodec(95, kVp9CodecName);
    498  Codec c_profile0 = CreateVideoCodec(95, kVp9CodecName);
    499  c_profile0.params[kVP9FmtpProfileId] = kProfile0;
    500 
    501  EXPECT_TRUE(c_profile0.Matches(c_no_profile));
    502 
    503  {
    504    Codec c_profile0_eq = CreateVideoCodec(95, kVp9CodecName);
    505    c_profile0_eq.params[kVP9FmtpProfileId] = kProfile0;
    506    EXPECT_TRUE(c_profile0.Matches(c_profile0_eq));
    507  }
    508 
    509  {
    510    Codec c_profile2 = CreateVideoCodec(95, kVp9CodecName);
    511    c_profile2.params[kVP9FmtpProfileId] = kProfile2;
    512    EXPECT_FALSE(c_profile0.Matches(c_profile2));
    513    EXPECT_FALSE(c_no_profile.Matches(c_profile2));
    514  }
    515 
    516  {
    517    Codec c_no_profile_eq = CreateVideoCodec(95, kVp9CodecName);
    518    EXPECT_TRUE(c_no_profile.Matches(c_no_profile_eq));
    519  }
    520 }
    521 
    522 // Matching H264 codecs also need to have matching profile-level-id and
    523 // packetization-mode.
    524 TEST(CodecTest, TestH264CodecMatches) {
    525  const char kProfileLevelId1[] = "42e01f";
    526  const char kProfileLevelId2[] = "42a01e";
    527  const char kProfileLevelId3[] = "42e01e";
    528 
    529  Codec pli_1_pm_0 = CreateVideoCodec(95, "H264");
    530  pli_1_pm_0.params[kH264FmtpProfileLevelId] = kProfileLevelId1;
    531  pli_1_pm_0.params[kH264FmtpPacketizationMode] = "0";
    532 
    533  {
    534    Codec pli_1_pm_blank = CreateVideoCodec(95, "H264");
    535    pli_1_pm_blank.params[kH264FmtpProfileLevelId] = kProfileLevelId1;
    536    pli_1_pm_blank.params.erase(
    537        pli_1_pm_blank.params.find(kH264FmtpPacketizationMode));
    538 
    539    // Matches since if packetization-mode is not specified it defaults to "0".
    540    EXPECT_TRUE(pli_1_pm_0.Matches(pli_1_pm_blank));
    541 
    542    // MatchesRtpCodec does exact comparison of parameters.
    543    EXPECT_FALSE(
    544        pli_1_pm_0.MatchesRtpCodec(pli_1_pm_blank.ToCodecParameters()));
    545  }
    546 
    547  {
    548    Codec pli_1_pm_1 = CreateVideoCodec(95, "H264");
    549    pli_1_pm_1.params[kH264FmtpProfileLevelId] = kProfileLevelId1;
    550    pli_1_pm_1.params[kH264FmtpPacketizationMode] = "1";
    551 
    552    // Does not match since packetization-mode is different.
    553    EXPECT_FALSE(pli_1_pm_0.Matches(pli_1_pm_1));
    554 
    555    EXPECT_FALSE(pli_1_pm_0.MatchesRtpCodec(pli_1_pm_1.ToCodecParameters()));
    556  }
    557 
    558  {
    559    Codec pli_2_pm_0 = CreateVideoCodec(95, "H264");
    560    pli_2_pm_0.params[kH264FmtpProfileLevelId] = kProfileLevelId2;
    561    pli_2_pm_0.params[kH264FmtpPacketizationMode] = "0";
    562 
    563    // Does not match since profile-level-id is different.
    564    EXPECT_FALSE(pli_1_pm_0.Matches(pli_2_pm_0));
    565 
    566    EXPECT_FALSE(pli_1_pm_0.MatchesRtpCodec(pli_2_pm_0.ToCodecParameters()));
    567  }
    568 
    569  {
    570    Codec pli_3_pm_0_asym = CreateVideoCodec(95, "H264");
    571    pli_3_pm_0_asym.params[kH264FmtpProfileLevelId] = kProfileLevelId3;
    572    pli_3_pm_0_asym.params[kH264FmtpPacketizationMode] = "0";
    573 
    574    // Does match, profile-level-id is different but the level is not compared.
    575    // and the profile matches.
    576    EXPECT_TRUE(pli_1_pm_0.Matches(pli_3_pm_0_asym));
    577 
    578    EXPECT_FALSE(
    579        pli_1_pm_0.MatchesRtpCodec(pli_3_pm_0_asym.ToCodecParameters()));
    580 
    581    //
    582  }
    583 }
    584 
    585 #ifdef RTC_ENABLE_H265
    586 // Matching H.265 codecs should have matching profile/tier/level and tx-mode.
    587 TEST(CodecTest, TestH265CodecMatches) {
    588  constexpr char kProfile1[] = "1";
    589  constexpr char kTier1[] = "1";
    590  constexpr char kLevel3_1[] = "93";
    591  constexpr char kLevel4[] = "120";
    592  constexpr char kTxMrst[] = "MRST";
    593 
    594  Codec c_ptl_blank = CreateVideoCodec(95, kH265CodecName);
    595 
    596  {
    597    Codec c_profile_1 = CreateVideoCodec(95, kH265CodecName);
    598    c_profile_1.params[kH265FmtpProfileId] = kProfile1;
    599 
    600    // Matches since profile-id unspecified defaults to "1".
    601    EXPECT_TRUE(c_ptl_blank.Matches(c_profile_1));
    602  }
    603 
    604  {
    605    Codec c_tier_flag_1 = CreateVideoCodec(95, kH265CodecName);
    606    c_tier_flag_1.params[kH265FmtpTierFlag] = kTier1;
    607 
    608    // Does not match since profile-space unspecified defaults to "0".
    609    EXPECT_FALSE(c_ptl_blank.Matches(c_tier_flag_1));
    610  }
    611 
    612  {
    613    Codec c_level_id_3_1 = CreateVideoCodec(95, kH265CodecName);
    614    c_level_id_3_1.params[kH265FmtpLevelId] = kLevel3_1;
    615 
    616    // Matches since level-id unspecified defaults to "93".
    617    EXPECT_TRUE(c_ptl_blank.Matches(c_level_id_3_1));
    618  }
    619 
    620  {
    621    Codec c_level_id_4 = CreateVideoCodec(95, kH265CodecName);
    622    c_level_id_4.params[kH265FmtpLevelId] = kLevel4;
    623 
    624    // Matches since we ignore level-id when matching H.265 codecs.
    625    EXPECT_TRUE(c_ptl_blank.Matches(c_level_id_4));
    626  }
    627 
    628  {
    629    Codec c_tx_mode_mrst = CreateVideoCodec(95, kH265CodecName);
    630    c_tx_mode_mrst.params[kH265FmtpTxMode] = kTxMrst;
    631 
    632    // Does not match since tx-mode implies to "SRST" and must be not specified
    633    // when it is the only mode supported:
    634    // https://datatracker.ietf.org/doc/html/draft-ietf-avtcore-hevc-webrtc
    635    EXPECT_FALSE(c_ptl_blank.Matches(c_tx_mode_mrst));
    636  }
    637 }
    638 #endif
    639 
    640 TEST(CodecTest, TestMatchesRtpCodecRtx) {
    641  const Codec rtx_codec_1 = CreateVideoRtxCodec(96, 120);
    642  const Codec rtx_codec_2 = CreateVideoRtxCodec(96, 121);
    643  EXPECT_TRUE(rtx_codec_1.Matches(rtx_codec_2));
    644  // MatchesRtpCodec ignores the different associated payload type (apt) for
    645  // RTX.
    646  EXPECT_TRUE(rtx_codec_1.MatchesRtpCodec(rtx_codec_2.ToCodecParameters()));
    647 }
    648 
    649 }  // namespace webrtc