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

ash / components / arc / video_accelerator / gpu_arc_video_decoder.h [blame]

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

#ifndef ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_

#include <map>
#include <memory>
#include <optional>
#include <queue>

#include "ash/components/arc/mojom/video_decoder.mojom.h"
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder.h"
#include "media/gpu/chromeos/vda_video_frame_pool.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace arc {

class GpuArcVideoFramePool;
class ProtectedBufferManager;

// The GpuArcVideoDecoder listens to mojo IPC requests and forwards these to an
// instance of media::VideoDecoder. Decoded frames are passed back to the mojo
// client.
class GpuArcVideoDecoder : public mojom::VideoDecoder {
 public:
  GpuArcVideoDecoder(
      scoped_refptr<ProtectedBufferManager> protected_buffer_manager);
  ~GpuArcVideoDecoder() override;

  GpuArcVideoDecoder(const GpuArcVideoDecoder&) = delete;
  GpuArcVideoDecoder& operator=(const GpuArcVideoDecoder&) = delete;
  GpuArcVideoDecoder(GpuArcVideoDecoder&&) = delete;
  GpuArcVideoDecoder& operator=(GpuArcVideoDecoder&&) = delete;

  // Implementation of mojom::VideoDecoder.
  void Initialize(
      arc::mojom::VideoDecoderConfigPtr config,
      mojo::PendingRemote<mojom::VideoDecoderClient> client,
      mojo::PendingAssociatedReceiver<mojom::VideoFramePool> video_frame_pool,
      InitializeCallback callback) override;
  void Decode(arc::mojom::DecoderBufferPtr buffer,
              DecodeCallback callback) override;
  void Reset(ResetCallback callback) override;
  void ReleaseVideoFrame(int32_t video_frame_id) override;

 private:
  using Request = base::OnceClosure;

  // Called by the decoder when initialization is done.
  void OnInitializeDone(media::DecoderStatus status);
  // Called by the decoder when the specified buffer has been decoded.
  void OnDecodeDone(DecodeCallback callback, media::DecoderStatus status);
  // Called by the decoder when a decoded frame is ready.
  void OnFrameReady(scoped_refptr<media::VideoFrame> frame);
  // Called by the decoder when a reset has been completed.
  void OnResetDone();
  // Called by the video frame pool to notify us that the pool won't be tracking
  // the current set of the video frames so we should release references to
  // them. This can indicate that new frames will be soon added to the pool
  // using the same IDs.
  void ReleaseClientVideoFrames();
  // Called when an error occurred.
  void OnError(media::DecoderStatus status);

  // Handle all requests that are currently in the |requests_| queue.
  void HandleRequests();
  // Handle the specified request. If the decoder is currently resetting the
  // request will be queued and handled once OnResetDone() is called.
  void HandleRequest(Request request);
  // Handle a decode request of the specified |buffer|.
  void HandleDecodeRequest(scoped_refptr<media::DecoderBuffer> buffer,
                           DecodeCallback callback);
  // Handle a reset request with specified |callback|. All ongoing flush
  // operations will be reported as canceled.
  void HandleResetRequest(ResetCallback callback);

  // Create a decoder buffer from the specified |fd|.
  scoped_refptr<media::DecoderBuffer> CreateDecoderBuffer(base::ScopedFD fd,
                                                          uint32_t offset,
                                                          uint32_t bytes_used);

  // The number of currently active instances. Always accessed on the same
  // thread, so we don't need to use a lock.
  static size_t num_instances_;

  // Whether the video decoder encountered an error and is aborting.
  bool error_state_ = false;

  // The remote mojo client.
  mojo::Remote<mojom::VideoDecoderClient> client_;
  // The local video decoder.
  std::unique_ptr<media::VideoDecoder> decoder_;
  // The video frame pool service.
  std::unique_ptr<GpuArcVideoFramePool> video_frame_pool_;

  // Initialization callback, used while the decoder is being initialized.
  InitializeCallback init_callback_;
  // The callback associated with the ongoing reset request if any.
  ResetCallback reset_callback_;
  // Requests currently waiting until resetting the decoder has completed.
  std::queue<Request> requests_;

  // The video frames currently in use by the client and their associated
  // video frame ids. We need to hold references to video frames to prevent
  // them from being returned to the video frame pool for reuse while they are
  // still in use by our client. The use count is tracked as the same frame
  // might be sent multiple times to the client when using the VP9
  // 'show_existing_frame' feature.
  std::map<int32_t, std::pair<scoped_refptr<media::VideoFrame>, size_t>>
      client_video_frames_;

  // The protected buffer manager, used when decoding an encrypted video.
  scoped_refptr<ProtectedBufferManager> protected_buffer_manager_;
  // Whether we're decoding an encrypted video.
  std::optional<bool> secure_mode_;

  // The client task runner and its sequence checker. All methods should be run
  // on this task runner.
  scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtr<GpuArcVideoDecoder> weak_this_;
  base::WeakPtrFactory<GpuArcVideoDecoder> weak_this_factory_{this};
};

}  // namespace arc

#endif  // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_