tor-browser

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

scalability_structure_unittest.cc (16760B)


      1 /*
      2 *  Copyright (c) 2020 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 <cstddef>
     12 #include <cstdint>
     13 #include <memory>
     14 #include <optional>
     15 #include <ostream>
     16 #include <set>
     17 #include <string>
     18 #include <utility>
     19 #include <vector>
     20 
     21 #include "api/array_view.h"
     22 #include "api/transport/rtp/dependency_descriptor.h"
     23 #include "api/video/video_bitrate_allocation.h"
     24 #include "api/video_codecs/scalability_mode.h"
     25 #include "common_video/generic_frame_descriptor/generic_frame_info.h"
     26 #include "modules/video_coding/svc/create_scalability_structure.h"
     27 #include "modules/video_coding/svc/scalability_mode_util.h"
     28 #include "modules/video_coding/svc/scalability_structure_test_helpers.h"
     29 #include "modules/video_coding/svc/scalable_video_controller.h"
     30 #include "rtc_base/checks.h"
     31 #include "rtc_base/strings/string_builder.h"
     32 #include "test/gmock.h"
     33 #include "test/gtest.h"
     34 
     35 namespace webrtc {
     36 namespace {
     37 
     38 using ::testing::AllOf;
     39 using ::testing::Contains;
     40 using ::testing::Each;
     41 using ::testing::ElementsAreArray;
     42 using ::testing::Field;
     43 using ::testing::Ge;
     44 using ::testing::IsEmpty;
     45 using ::testing::Le;
     46 using ::testing::Lt;
     47 using ::testing::Not;
     48 using ::testing::NotNull;
     49 using ::testing::SizeIs;
     50 using ::testing::TestWithParam;
     51 using ::testing::Values;
     52 
     53 std::string FrameDependencyTemplateToString(const FrameDependencyTemplate& t) {
     54  StringBuilder sb;
     55  sb << "S" << t.spatial_id << "T" << t.temporal_id;
     56  sb << ": dtis = ";
     57  for (const auto dtis : t.decode_target_indications) {
     58    switch (dtis) {
     59      case DecodeTargetIndication::kNotPresent:
     60        sb << "-";
     61        break;
     62      case DecodeTargetIndication::kDiscardable:
     63        sb << "D";
     64        break;
     65      case DecodeTargetIndication::kSwitch:
     66        sb << "S";
     67        break;
     68      case DecodeTargetIndication::kRequired:
     69        sb << "R";
     70        break;
     71      default:
     72        sb << "?";
     73        break;
     74    }
     75  }
     76  sb << ", frame diffs = { ";
     77  for (int d : t.frame_diffs) {
     78    sb << d << ", ";
     79  }
     80  sb << "}, chain diffs = { ";
     81  for (int d : t.chain_diffs) {
     82    sb << d << ", ";
     83  }
     84  sb << "}";
     85  return sb.Release();
     86 }
     87 
     88 struct SvcTestParam {
     89  friend std::ostream& operator<<(std::ostream& os, const SvcTestParam& param) {
     90    return os << param.name;
     91  }
     92 
     93  ScalabilityMode GetScalabilityMode() const {
     94    std::optional<ScalabilityMode> scalability_mode =
     95        ScalabilityModeFromString(name);
     96    RTC_CHECK(scalability_mode.has_value());
     97    return *scalability_mode;
     98  }
     99 
    100  std::string name;
    101  int num_temporal_units;
    102 };
    103 
    104 class ScalabilityStructureTest : public TestWithParam<SvcTestParam> {};
    105 
    106 TEST_P(ScalabilityStructureTest,
    107       StaticConfigMatchesConfigReturnedByController) {
    108  std::unique_ptr<ScalableVideoController> controller =
    109      CreateScalabilityStructure(GetParam().GetScalabilityMode());
    110  std::optional<ScalableVideoController::StreamLayersConfig> static_config =
    111      ScalabilityStructureConfig(GetParam().GetScalabilityMode());
    112  ASSERT_THAT(controller, NotNull());
    113  ASSERT_NE(static_config, std::nullopt);
    114  ScalableVideoController::StreamLayersConfig config =
    115      controller->StreamConfig();
    116  EXPECT_EQ(config.num_spatial_layers, static_config->num_spatial_layers);
    117  EXPECT_EQ(config.num_temporal_layers, static_config->num_temporal_layers);
    118  EXPECT_THAT(
    119      MakeArrayView(config.scaling_factor_num, config.num_spatial_layers),
    120      ElementsAreArray(static_config->scaling_factor_num,
    121                       static_config->num_spatial_layers));
    122  EXPECT_THAT(
    123      MakeArrayView(config.scaling_factor_den, config.num_spatial_layers),
    124      ElementsAreArray(static_config->scaling_factor_den,
    125                       static_config->num_spatial_layers));
    126 }
    127 
    128 TEST_P(ScalabilityStructureTest,
    129       NumberOfDecodeTargetsAndChainsAreInRangeAndConsistent) {
    130  FrameDependencyStructure structure =
    131      CreateScalabilityStructure(GetParam().GetScalabilityMode())
    132          ->DependencyStructure();
    133  EXPECT_GT(structure.num_decode_targets, 0);
    134  EXPECT_LE(structure.num_decode_targets,
    135            DependencyDescriptor::kMaxDecodeTargets);
    136  EXPECT_GE(structure.num_chains, 0);
    137  EXPECT_LE(structure.num_chains, structure.num_decode_targets);
    138  if (structure.num_chains == 0) {
    139    EXPECT_THAT(structure.decode_target_protected_by_chain, IsEmpty());
    140  } else {
    141    EXPECT_THAT(structure.decode_target_protected_by_chain,
    142                AllOf(SizeIs(structure.num_decode_targets), Each(Ge(0)),
    143                      Each(Lt(structure.num_chains))));
    144  }
    145  EXPECT_THAT(structure.templates,
    146              SizeIs(Lt(size_t{DependencyDescriptor::kMaxTemplates})));
    147 }
    148 
    149 TEST_P(ScalabilityStructureTest, TemplatesAreSortedByLayerId) {
    150  FrameDependencyStructure structure =
    151      CreateScalabilityStructure(GetParam().GetScalabilityMode())
    152          ->DependencyStructure();
    153  ASSERT_THAT(structure.templates, Not(IsEmpty()));
    154  const auto& first_templates = structure.templates.front();
    155  EXPECT_EQ(first_templates.spatial_id, 0);
    156  EXPECT_EQ(first_templates.temporal_id, 0);
    157  for (size_t i = 1; i < structure.templates.size(); ++i) {
    158    const auto& prev_template = structure.templates[i - 1];
    159    const auto& next_template = structure.templates[i];
    160    if (next_template.spatial_id == prev_template.spatial_id &&
    161        next_template.temporal_id == prev_template.temporal_id) {
    162      // Same layer, next_layer_idc == 0
    163    } else if (next_template.spatial_id == prev_template.spatial_id &&
    164               next_template.temporal_id == prev_template.temporal_id + 1) {
    165      // Next temporal layer, next_layer_idc == 1
    166    } else if (next_template.spatial_id == prev_template.spatial_id + 1 &&
    167               next_template.temporal_id == 0) {
    168      // Next spatial layer, next_layer_idc == 2
    169    } else {
    170      // everything else is invalid.
    171      ADD_FAILURE() << "Invalid templates order. Template #" << i
    172                    << " with layer (" << next_template.spatial_id << ","
    173                    << next_template.temporal_id
    174                    << ") follows template with layer ("
    175                    << prev_template.spatial_id << ","
    176                    << prev_template.temporal_id << ").";
    177    }
    178  }
    179 }
    180 
    181 TEST_P(ScalabilityStructureTest, TemplatesMatchNumberOfDecodeTargetsAndChains) {
    182  FrameDependencyStructure structure =
    183      CreateScalabilityStructure(GetParam().GetScalabilityMode())
    184          ->DependencyStructure();
    185  EXPECT_THAT(
    186      structure.templates,
    187      Each(AllOf(Field(&FrameDependencyTemplate::decode_target_indications,
    188                       SizeIs(structure.num_decode_targets)),
    189                 Field(&FrameDependencyTemplate::chain_diffs,
    190                       SizeIs(structure.num_chains)))));
    191 }
    192 
    193 TEST_P(ScalabilityStructureTest, FrameInfoMatchesFrameDependencyStructure) {
    194  std::unique_ptr<ScalableVideoController> svc_controller =
    195      CreateScalabilityStructure(GetParam().GetScalabilityMode());
    196  FrameDependencyStructure structure = svc_controller->DependencyStructure();
    197  std::vector<GenericFrameInfo> frame_infos =
    198      ScalabilityStructureWrapper(*svc_controller)
    199          .GenerateFrames(GetParam().num_temporal_units);
    200  for (size_t frame_id = 0; frame_id < frame_infos.size(); ++frame_id) {
    201    const auto& frame = frame_infos[frame_id];
    202    EXPECT_GE(frame.spatial_id, 0) << " for frame " << frame_id;
    203    EXPECT_GE(frame.temporal_id, 0) << " for frame " << frame_id;
    204    EXPECT_THAT(frame.decode_target_indications,
    205                SizeIs(structure.num_decode_targets))
    206        << " for frame " << frame_id;
    207    EXPECT_THAT(frame.part_of_chain, SizeIs(structure.num_chains))
    208        << " for frame " << frame_id;
    209  }
    210 }
    211 
    212 TEST_P(ScalabilityStructureTest, ThereIsAPerfectTemplateForEachFrame) {
    213  std::unique_ptr<ScalableVideoController> svc_controller =
    214      CreateScalabilityStructure(GetParam().GetScalabilityMode());
    215  FrameDependencyStructure structure = svc_controller->DependencyStructure();
    216  std::vector<GenericFrameInfo> frame_infos =
    217      ScalabilityStructureWrapper(*svc_controller)
    218          .GenerateFrames(GetParam().num_temporal_units);
    219  for (size_t frame_id = 0; frame_id < frame_infos.size(); ++frame_id) {
    220    EXPECT_THAT(structure.templates, Contains(frame_infos[frame_id]))
    221        << " for frame " << frame_id << ", Expected "
    222        << FrameDependencyTemplateToString(frame_infos[frame_id]);
    223  }
    224 }
    225 
    226 TEST_P(ScalabilityStructureTest, FrameDependsOnSameOrLowerLayer) {
    227  std::unique_ptr<ScalableVideoController> svc_controller =
    228      CreateScalabilityStructure(GetParam().GetScalabilityMode());
    229  std::vector<GenericFrameInfo> frame_infos =
    230      ScalabilityStructureWrapper(*svc_controller)
    231          .GenerateFrames(GetParam().num_temporal_units);
    232  int64_t num_frames = frame_infos.size();
    233 
    234  for (int64_t frame_id = 0; frame_id < num_frames; ++frame_id) {
    235    const auto& frame = frame_infos[frame_id];
    236    for (int frame_diff : frame.frame_diffs) {
    237      int64_t base_frame_id = frame_id - frame_diff;
    238      const auto& base_frame = frame_infos[base_frame_id];
    239      EXPECT_GE(frame.spatial_id, base_frame.spatial_id)
    240          << "Frame " << frame_id << " depends on frame " << base_frame_id;
    241      EXPECT_GE(frame.temporal_id, base_frame.temporal_id)
    242          << "Frame " << frame_id << " depends on frame " << base_frame_id;
    243    }
    244  }
    245 }
    246 
    247 TEST_P(ScalabilityStructureTest, NoFrameDependsOnDiscardableOrNotPresent) {
    248  std::unique_ptr<ScalableVideoController> svc_controller =
    249      CreateScalabilityStructure(GetParam().GetScalabilityMode());
    250  std::vector<GenericFrameInfo> frame_infos =
    251      ScalabilityStructureWrapper(*svc_controller)
    252          .GenerateFrames(GetParam().num_temporal_units);
    253  int64_t num_frames = frame_infos.size();
    254  FrameDependencyStructure structure = svc_controller->DependencyStructure();
    255 
    256  for (int dt = 0; dt < structure.num_decode_targets; ++dt) {
    257    for (int64_t frame_id = 0; frame_id < num_frames; ++frame_id) {
    258      const auto& frame = frame_infos[frame_id];
    259      if (frame.decode_target_indications[dt] ==
    260          DecodeTargetIndication::kNotPresent) {
    261        continue;
    262      }
    263      for (int frame_diff : frame.frame_diffs) {
    264        int64_t base_frame_id = frame_id - frame_diff;
    265        const auto& base_frame = frame_infos[base_frame_id];
    266        EXPECT_NE(base_frame.decode_target_indications[dt],
    267                  DecodeTargetIndication::kNotPresent)
    268            << "Frame " << frame_id << " depends on frame " << base_frame_id
    269            << " that is not part of decode target#" << dt;
    270        EXPECT_NE(base_frame.decode_target_indications[dt],
    271                  DecodeTargetIndication::kDiscardable)
    272            << "Frame " << frame_id << " depends on frame " << base_frame_id
    273            << " that is discardable for decode target#" << dt;
    274      }
    275    }
    276  }
    277 }
    278 
    279 TEST_P(ScalabilityStructureTest, NoFrameDependsThroughSwitchIndication) {
    280  std::unique_ptr<ScalableVideoController> svc_controller =
    281      CreateScalabilityStructure(GetParam().GetScalabilityMode());
    282  FrameDependencyStructure structure = svc_controller->DependencyStructure();
    283  std::vector<GenericFrameInfo> frame_infos =
    284      ScalabilityStructureWrapper(*svc_controller)
    285          .GenerateFrames(GetParam().num_temporal_units);
    286  int64_t num_frames = frame_infos.size();
    287  std::vector<std::set<int64_t>> full_deps(num_frames);
    288 
    289  // For each frame calculate set of all frames it depends on, both directly and
    290  // indirectly.
    291  for (int64_t frame_id = 0; frame_id < num_frames; ++frame_id) {
    292    std::set<int64_t> all_base_frames;
    293    for (int frame_diff : frame_infos[frame_id].frame_diffs) {
    294      int64_t base_frame_id = frame_id - frame_diff;
    295      all_base_frames.insert(base_frame_id);
    296      const auto& indirect = full_deps[base_frame_id];
    297      all_base_frames.insert(indirect.begin(), indirect.end());
    298    }
    299    full_deps[frame_id] = std::move(all_base_frames);
    300  }
    301 
    302  // Now check the switch indication: frames after the switch indication mustn't
    303  // depend on any addition frames before the switch indications.
    304  for (int dt = 0; dt < structure.num_decode_targets; ++dt) {
    305    for (int64_t switch_frame_id = 0; switch_frame_id < num_frames;
    306         ++switch_frame_id) {
    307      if (frame_infos[switch_frame_id].decode_target_indications[dt] !=
    308          DecodeTargetIndication::kSwitch) {
    309        continue;
    310      }
    311      for (int64_t later_frame_id = switch_frame_id + 1;
    312           later_frame_id < num_frames; ++later_frame_id) {
    313        if (frame_infos[later_frame_id].decode_target_indications[dt] ==
    314            DecodeTargetIndication::kNotPresent) {
    315          continue;
    316        }
    317        for (int frame_diff : frame_infos[later_frame_id].frame_diffs) {
    318          int64_t early_frame_id = later_frame_id - frame_diff;
    319          if (early_frame_id < switch_frame_id) {
    320            EXPECT_THAT(full_deps[switch_frame_id], Contains(early_frame_id))
    321                << "For decode target #" << dt << " frame " << later_frame_id
    322                << " depends on the frame " << early_frame_id
    323                << " that switch indication frame " << switch_frame_id
    324                << " doesn't directly on indirectly depend on.";
    325          }
    326        }
    327      }
    328    }
    329  }
    330 }
    331 
    332 TEST_P(ScalabilityStructureTest, ProduceNoFrameForDisabledLayers) {
    333  std::unique_ptr<ScalableVideoController> svc_controller =
    334      CreateScalabilityStructure(GetParam().GetScalabilityMode());
    335  ScalableVideoController::StreamLayersConfig structure =
    336      svc_controller->StreamConfig();
    337 
    338  VideoBitrateAllocation all_bitrates;
    339  for (int sid = 0; sid < structure.num_spatial_layers; ++sid) {
    340    for (int tid = 0; tid < structure.num_temporal_layers; ++tid) {
    341      all_bitrates.SetBitrate(sid, tid, 100'000);
    342    }
    343  }
    344 
    345  svc_controller->OnRatesUpdated(all_bitrates);
    346  ScalabilityStructureWrapper wrapper(*svc_controller);
    347  std::vector<GenericFrameInfo> frames =
    348      wrapper.GenerateFrames(GetParam().num_temporal_units);
    349 
    350  for (int sid = 0; sid < structure.num_spatial_layers; ++sid) {
    351    for (int tid = 0; tid < structure.num_temporal_layers; ++tid) {
    352      // When all layers were enabled, expect there was a frame for each layer.
    353      EXPECT_THAT(frames,
    354                  Contains(AllOf(Field(&GenericFrameInfo::spatial_id, sid),
    355                                 Field(&GenericFrameInfo::temporal_id, tid))))
    356          << "For layer (" << sid << "," << tid << ")";
    357      // Restore bitrates for all layers before disabling single layer.
    358      VideoBitrateAllocation bitrates = all_bitrates;
    359      bitrates.SetBitrate(sid, tid, 0);
    360      svc_controller->OnRatesUpdated(bitrates);
    361      // With layer (sid, tid) disabled, expect no frames are produced for it.
    362      EXPECT_THAT(
    363          wrapper.GenerateFrames(GetParam().num_temporal_units),
    364          Not(Contains(AllOf(Field(&GenericFrameInfo::spatial_id, sid),
    365                             Field(&GenericFrameInfo::temporal_id, tid)))))
    366          << "For layer (" << sid << "," << tid << ")";
    367    }
    368  }
    369 }
    370 
    371 INSTANTIATE_TEST_SUITE_P(
    372    Svc,
    373    ScalabilityStructureTest,
    374    Values(SvcTestParam{"L1T1", /*num_temporal_units=*/3},
    375           SvcTestParam{"L1T2", /*num_temporal_units=*/4},
    376           SvcTestParam{"L1T3", /*num_temporal_units=*/8},
    377           SvcTestParam{"L2T1", /*num_temporal_units=*/3},
    378           SvcTestParam{"L2T1_KEY", /*num_temporal_units=*/3},
    379           SvcTestParam{"L3T1", /*num_temporal_units=*/3},
    380           SvcTestParam{"L3T1_KEY", /*num_temporal_units=*/3},
    381           SvcTestParam{"L3T3", /*num_temporal_units=*/8},
    382           SvcTestParam{"S2T1", /*num_temporal_units=*/3},
    383           SvcTestParam{"S2T2", /*num_temporal_units=*/4},
    384           SvcTestParam{"S2T3", /*num_temporal_units=*/8},
    385           SvcTestParam{"S3T1", /*num_temporal_units=*/3},
    386           SvcTestParam{"S3T2", /*num_temporal_units=*/4},
    387           SvcTestParam{"S3T3", /*num_temporal_units=*/8},
    388           SvcTestParam{"L2T2", /*num_temporal_units=*/4},
    389           SvcTestParam{"L2T2_KEY", /*num_temporal_units=*/4},
    390           SvcTestParam{"L2T2_KEY_SHIFT", /*num_temporal_units=*/4},
    391           SvcTestParam{"L2T3", /*num_temporal_units=*/8},
    392           SvcTestParam{"L2T3_KEY", /*num_temporal_units=*/8},
    393           SvcTestParam{"L3T2", /*num_temporal_units=*/4},
    394           SvcTestParam{"L3T2_KEY", /*num_temporal_units=*/4},
    395           SvcTestParam{"L3T3_KEY", /*num_temporal_units=*/8}),
    396    [](const testing::TestParamInfo<SvcTestParam>& info) {
    397      return info.param.name;
    398    });
    399 
    400 }  // namespace
    401 }  // namespace webrtc