910e62b5创建于 1月15日历史提交
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/codec/video_encoder_active_map.h"

#include <algorithm>
#include <utility>

#include "base/containers/heap_array.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"

using DesktopRegionIterator = webrtc::DesktopRegion::Iterator;

namespace {
// Defines the dimension of a macro block. This is used to compute the active
// map for an encoder. This size is the same for VP8, VP9, and AV1 encoders.
constexpr int kMacroBlockSize = 16;
}  // namespace

namespace remoting {

VideoEncoderActiveMap::VideoEncoderActiveMap() = default;

VideoEncoderActiveMap::~VideoEncoderActiveMap() = default;

void VideoEncoderActiveMap::Initialize(const webrtc::DesktopSize& size) {
  active_map_size_.set((size.width() + kMacroBlockSize - 1) / kMacroBlockSize,
                       (size.height() + kMacroBlockSize - 1) / kMacroBlockSize);
  active_map_ = base::HeapArray<uint8_t>::Uninit(active_map_size_.width() *
                                                 active_map_size_.height());
  Clear();
}

void VideoEncoderActiveMap::Clear() {
  std::ranges::fill(active_map_, 0);
}

void VideoEncoderActiveMap::Update(
    const webrtc::DesktopRegion& updated_region) {
  if (active_map_.empty()) {
    return;
  }
  const int map_width = active_map_size_.width();
  const int map_height = active_map_size_.height();
  for (DesktopRegionIterator r(updated_region); !r.IsAtEnd(); r.Advance()) {
    const webrtc::DesktopRect& rect = r.rect();
    const int left =
        std::clamp(rect.left() / kMacroBlockSize, 0, map_width - 1);
    const int right =
        std::clamp((rect.right() - 1) / kMacroBlockSize, 0, map_width - 1);
    const int top = std::clamp(rect.top() / kMacroBlockSize, 0, map_height - 1);
    const int bottom =
        std::clamp((rect.bottom() - 1) / kMacroBlockSize, 0, map_height - 1);
    for (int y = top; y <= bottom; ++y) {
      const size_t row_offset = static_cast<size_t>(y) * map_width;
      for (int x = left; x <= right; ++x) {
        active_map_[row_offset + x] = 1;
      }
    }
  }
}

}  // namespace remoting