1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131

media / mojo / clients / mojo_video_encoder_metrics_provider.cc [blame]

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/mojo/clients/mojo_video_encoder_metrics_provider.h"

#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "media/base/encoder_status.h"
#include "media/base/svc_scalability_mode.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "ui/gfx/geometry/size.h"

namespace media {
class MojoVideoEncoderMetricsProviderFactory::MojoVideoEncoderMetricsProvider
    : public VideoEncoderMetricsProvider {
 public:
  MojoVideoEncoderMetricsProvider(
      scoped_refptr<MojoVideoEncoderMetricsProviderFactory> factory,
      mojom::VideoEncoderUseCase use_case,
      uint64_t encoder_id)
      : factory_(std::move(factory)),
        use_case_(use_case),
        encoder_id_(encoder_id) {
    DETACH_FROM_SEQUENCE(sequence_checker_);
  }

  ~MojoVideoEncoderMetricsProvider() override {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    if (initialized_) {
      CHECK(remote_);
      (*remote_)->Complete(encoder_id_);
    }
  }

  void Initialize(VideoCodecProfile codec_profile,
                  const gfx::Size& encode_size,
                  bool is_hardware_encoder,
                  SVCScalabilityMode svc_mode) override {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    initialized_ = true;
    num_encoded_frames_ = 0;
    if (!remote_) {
      remote_ = factory_->GetRemote();
    }
    (*remote_)->Initialize(encoder_id_, use_case_, codec_profile, encode_size,
                           is_hardware_encoder, svc_mode);
  }

  void IncrementEncodedFrameCount() override {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    if (!remote_) {
      DLOG(WARNING) << __func__ << "is called before Initialize()";
      return;
    }

    ++num_encoded_frames_;
    constexpr size_t kEncodedFrameCountBucketSize = 100;
    // Basically update the number of encoded frames every 100 seconds to avoid
    // the frequent mojo call. The exception is the first encoded frames update
    // as it is important to represent whether the encoding actually starts.
    if (num_encoded_frames_ % kEncodedFrameCountBucketSize == 0 ||
        num_encoded_frames_ == 1u) {
      (*remote_)->SetEncodedFrameCount(encoder_id_, num_encoded_frames_);
    }
  }

  void SetError(const media::EncoderStatus& status) override {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    CHECK(!status.is_ok());
    if (!remote_) {
      DLOG(WARNING) << __func__ << "is called before Initialize()";
      return;
    }
    (*remote_)->SetError(encoder_id_, status);
  }

 private:
  // To guarantee |remote_| is valid as long as MojoVideoEncoderMetricsProvider
  // is alive.
  const scoped_refptr<MojoVideoEncoderMetricsProviderFactory> factory_;

  raw_ptr<mojo::Remote<mojom::VideoEncoderMetricsProvider>> remote_
      GUARDED_BY_CONTEXT(sequence_checker_){nullptr};

  const mojom::VideoEncoderUseCase use_case_
      GUARDED_BY_CONTEXT(sequence_checker_);
  const uint64_t encoder_id_ GUARDED_BY_CONTEXT(sequence_checker_);

  size_t num_encoded_frames_ GUARDED_BY_CONTEXT(sequence_checker_){0};
  bool initialized_ GUARDED_BY_CONTEXT(sequence_checker_){false};

  SEQUENCE_CHECKER(sequence_checker_);
};

MojoVideoEncoderMetricsProviderFactory::MojoVideoEncoderMetricsProviderFactory(
    mojom::VideoEncoderUseCase use_case,
    mojo::PendingRemote<mojom::VideoEncoderMetricsProvider> pending_remote)
    : use_case_(use_case), pending_remote_(std::move(pending_remote)) {
  DETACH_FROM_SEQUENCE(remote_sequence_checker_);
  DETACH_FROM_SEQUENCE(create_provider_sequence_checker_);
}

MojoVideoEncoderMetricsProviderFactory::
    ~MojoVideoEncoderMetricsProviderFactory() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(remote_sequence_checker_);
}

MojoVideoEncoderMetricsProviderFactory::MojoVideoEncoderMetricsProviderFactory(
    mojom::VideoEncoderUseCase use_case)
    : use_case_(use_case) {
  DETACH_FROM_SEQUENCE(remote_sequence_checker_);
  DETACH_FROM_SEQUENCE(create_provider_sequence_checker_);
}

mojo::Remote<mojom::VideoEncoderMetricsProvider>*
MojoVideoEncoderMetricsProviderFactory::GetRemote() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(remote_sequence_checker_);
  if (pending_remote_.is_valid()) {
    remote_.Bind(std::move(pending_remote_));
  }
  return &remote_;
}

std::unique_ptr<VideoEncoderMetricsProvider>
MojoVideoEncoderMetricsProviderFactory::CreateVideoEncoderMetricsProvider() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(create_provider_sequence_checker_);
  return std::make_unique<MojoVideoEncoderMetricsProvider>(this, use_case_,
                                                           encoder_id_++);
}
}  // namespace media