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
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204

media / mojo / clients / mojo_codec_factory.h [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.

#ifndef MEDIA_MOJO_CLIENTS_MOJO_CODEC_FACTORY_H_
#define MEDIA_MOJO_CLIENTS_MOJO_CODEC_FACTORY_H_

#include <memory>

#include "base/functional/callback_forward.h"
#include "base/task/sequenced_task_runner.h"
#include "media/base/decoder.h"
#include "media/base/media_log.h"
#include "media/base/overlay_info.h"
#include "media/base/supported_video_decoder_config.h"
#include "media/base/video_decoder.h"
#include "media/mojo/mojom/video_encode_accelerator.mojom.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"

namespace media {

// Assists the MojoGpuVideoAcceleratorFactories class with hardware decoder and
// encoder functionalities.
//
// It is a base class that handles the encoder resources
// via media::mojom::VideoEncodeAcceleratorProvider. Its derived classes
// implement how to connect to hardware decoder resources.
class MojoCodecFactory {
 public:
  // `media_task_runner` - task runner for running multi-media operations.
  // `context_provider` - context provider for creating a video decoder.
  // `video_decode_accelerator_enabled` - whether the video decode accelerator
  //    is enabled.
  // `video_encode_accelerator_enabled` - whether the video encode accelerator
  //    is enabled.
  // `pending_vea_provider_remote` - bound pending
  //    media::mojom::VideoEncodeAcceleratorProvider remote.
  MojoCodecFactory(
      scoped_refptr<base::SequencedTaskRunner> media_task_runner,
      scoped_refptr<viz::ContextProviderCommandBuffer> context_provider,
      bool video_decode_accelerator_enabled,
      bool video_encode_accelerator_enabled,
      mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
          pending_vea_provider_remote);

  MojoCodecFactory(const MojoCodecFactory&) = delete;
  MojoCodecFactory& operator=(const MojoCodecFactory&) = delete;
  virtual ~MojoCodecFactory();

  // `gpu_factories` - pointer to the GpuVideoAcceleratorFactories that
  //    owns |this|.
  // `media_log` - process-wide pointer to log to chrome://media-internals log.
  // `request_overlay_info_cb` - callback that gets the overlay information.
  // `rendering_color_space` - color space for the purpose of color conversion.
  //
  // Derived class should construct its own type of video decoder.
  virtual std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
      media::GpuVideoAcceleratorFactories* gpu_factories,
      media::MediaLog* media_log,
      media::RequestOverlayInfoCB request_overlay_info_cb,
      const gfx::ColorSpace& rendering_color_space) = 0;

  std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator();

  // Returns VideoDecoderType::kUnknown in cases where IsDecoderSupportKnown()
  // is false.
  // Otherwise, it returns the type of decoder that provided the
  // configs for the config support check.
  media::VideoDecoderType GetVideoDecoderType();

  // Returns a nullopt if we have not yet gotten the configs.
  // Returns an optional that contains an empty vector if we have gotten the
  // result and there are no supported configs.
  std::optional<media::SupportedVideoDecoderConfigs>
  GetSupportedVideoDecoderConfigs();

  // Returns a nullopt if we have not yet gotten the profiles.
  // Returns an optional that contains an empty vector if we have gotten the
  // result and there are no supported profiles.
  std::optional<media::VideoEncodeAccelerator::SupportedProfiles>
  GetVideoEncodeAcceleratorSupportedProfiles();

  // Returns true if media::SupportedVideoDecoderConfigs are populated.
  bool IsDecoderSupportKnown();

  // Returns true if media::VideoEncodeAccelerator::SupportedProfiles are
  // populated.
  bool IsEncoderSupportKnown();

  // If the current decoder support is not yet known, use this to register a
  // callback that is notified once the support is known. At that point, calling
  // GetSupportedVideoDecoderConfigs will give the set of supported decoder
  // configs.
  //
  // There is no way to unsubscribe a callback, it is recommended to use a
  // WeakPtr if you need this feature.
  void NotifyDecoderSupportKnown(base::OnceClosure callback);

  // If the current encoder support is not yet known, use this to register a
  // callback that is notified once the support is known. At that point, calling
  // GetVideoEncodeAcceleratorSupportedProfiles will give the set of supported
  // encoder profiles.
  //
  // There is no way to unsubscribe a callback, it is recommended to use a
  // WeakPtr if you need this feature.
  void NotifyEncoderSupportKnown(base::OnceClosure callback);

  // Provides this instance with the gpu channel token for the
  // associated gpu channel.
  void OnChannelTokenReady(const base::UnguessableToken& token,
                           int32_t route_id);

 protected:
  class Notifier {
   public:
    Notifier();
    ~Notifier();

    void Register(base::OnceClosure callback);
    void Notify();

    bool is_notified() { return is_notified_; }

   private:
    bool is_notified_ = false;
    std::vector<base::OnceClosure> callbacks_;
  };

  void OnDecoderSupportFailed();
  void OnGetSupportedDecoderConfigs();

  void OnEncoderSupportFailed();
  void OnGetVideoEncodeAcceleratorSupportedProfiles(
      const media::VideoEncodeAccelerator::SupportedProfiles&
          supported_profiles);
  bool IsEncoderReady() EXCLUSIVE_LOCKS_REQUIRED(supported_profiles_lock_);

  // Task runner on the Media thread for running multi-media operations
  // (e.g., creating a video decoder).
  // In Fuchsia, it needs to be started with the IO message pump for FIDL calls.
  scoped_refptr<base::SequencedTaskRunner> media_task_runner_;

  // Shared pointer to a shared context provider. All access should happen only
  // on the media thread.
  const scoped_refptr<viz::ContextProviderCommandBuffer> context_provider_;

  // Whether video acceleration encoding/decoding should be enabled.
  const bool video_decode_accelerator_enabled_;
  const bool video_encode_accelerator_enabled_;

  base::Lock supported_profiles_lock_;

  // If the Optional is empty, then we have not yet gotten the configs.
  // If the Optional contains an empty vector, then we have gotten the result
  // and there are no supported configs.
  std::optional<media::SupportedVideoDecoderConfigs> supported_decoder_configs_
      GUARDED_BY(supported_profiles_lock_);
  std::optional<media::VideoEncodeAccelerator::SupportedProfiles>
      supported_vea_profiles_ GUARDED_BY(supported_profiles_lock_);

  media::VideoDecoderType video_decoder_type_
      GUARDED_BY(supported_profiles_lock_) = media::VideoDecoderType::kUnknown;

  Notifier decoder_support_notifier_ GUARDED_BY(supported_profiles_lock_);
  Notifier encoder_support_notifier_ GUARDED_BY(supported_profiles_lock_);

 private:
  void BindOnTaskRunner(
      mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
          pending_vea_provider_remote);

  mojo::Remote<media::mojom::VideoEncodeAcceleratorProvider> vea_provider_;
  base::UnguessableToken channel_token_;
  int32_t route_id_;
};

// MojoCodecFactoryDefault is the default derived class, which has no
// decoder provider. It does not have any supported video decoder configs and
// returns a null pointer when creating a hardware video decoder.
class MojoCodecFactoryDefault final : public MojoCodecFactory {
 public:
  MojoCodecFactoryDefault(
      scoped_refptr<base::SequencedTaskRunner> task_runner,
      scoped_refptr<viz::ContextProviderCommandBuffer> context_provider,
      bool video_decode_accelerator_enabled,
      bool video_encode_accelerator_enabled,
      mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
          pending_vea_provider_remote);
  ~MojoCodecFactoryDefault() override;

  // Returns nullptr since there is no decoder provider.
  std::unique_ptr<media::VideoDecoder> CreateVideoDecoder(
      media::GpuVideoAcceleratorFactories* gpu_factories,
      media::MediaLog* media_log,
      media::RequestOverlayInfoCB request_overlay_info_cb,
      const gfx::ColorSpace& rendering_color_space) override;
};

}  // namespace media

#endif  // MEDIA_MOJO_CLIENTS_MOJO_CODEC_FACTORY_H_