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

media / gpu / mac / video_toolbox_video_decoder.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_GPU_MAC_VIDEO_TOOLBOX_VIDEO_DECODER_H_
#define MEDIA_GPU_MAC_VIDEO_TOOLBOX_VIDEO_DECODER_H_

#include <CoreMedia/CoreMedia.h>
#include <VideoToolbox/VideoToolbox.h>

#include <memory>
#include <utility>
#include <vector>

#include "base/apple/scoped_cftyperef.h"
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "gpu/config/gpu_driver_bug_workarounds.h"
#include "media/base/decoder_buffer.h"
#include "media/base/supported_video_decoder_config.h"
#include "media/base/video_decoder.h"
#include "media/base/video_decoder_config.h"
#include "media/gpu/codec_picture.h"
#include "media/gpu/mac/video_toolbox_decompression_session_manager.h"
#include "media/gpu/mac/video_toolbox_frame_converter.h"
#include "media/gpu/mac/video_toolbox_output_queue.h"
#include "media/gpu/media_gpu_export.h"

namespace gpu {
class CommandBufferStub;
}  // namespace gpu

namespace media {

class AcceleratedVideoDecoder;
class MediaLog;
struct VideoToolboxDecodeMetadata;
struct VideoToolboxDecompressionSessionMetadata;

class MEDIA_GPU_EXPORT VideoToolboxVideoDecoder : public VideoDecoder {
 public:
  using GetCommandBufferStubCB =
      base::RepeatingCallback<gpu::CommandBufferStub*()>;

  VideoToolboxVideoDecoder(
      scoped_refptr<base::SequencedTaskRunner> task_runner,
      std::unique_ptr<MediaLog> media_log,
      const gpu::GpuDriverBugWorkarounds& gpu_workarounds,
      scoped_refptr<base::SequencedTaskRunner> gpu_task_runner,
      GetCommandBufferStubCB get_stub_cb);

  ~VideoToolboxVideoDecoder() override;

  // VideoDecoder implementation.
  void Initialize(const VideoDecoderConfig& config,
                  bool low_delay,
                  CdmContext* cdm_context,
                  InitCB init_cb,
                  const OutputCB& output_cb,
                  const WaitingCB& waiting_cb) override;
  void Decode(scoped_refptr<DecoderBuffer> buffer, DecodeCB decode_cb) override;
  void Reset(base::OnceClosure reset_cb) override;
  bool NeedsBitstreamConversion() const override;
  int GetMaxDecodeRequests() const override;
  VideoDecoderType GetDecoderType() const override;

  static std::vector<SupportedVideoDecoderConfig>
  GetSupportedVideoDecoderConfigs(
      const gpu::GpuDriverBugWorkarounds& gpu_workarounds);

 private:
  // Shut down and enter a permanent error state.
  void NotifyError(DecoderStatus status);

  // Drop all state, calling decode callbacks with |status|.
  void ResetInternal(DecoderStatus status);

  // Call |decode_cb_| entries until the correct backpressure is achieved.
  void ReleaseDecodeCallbacks();

  // |accelerator_| callbacks.
  void OnAcceleratorDecode(
      base::apple::ScopedCFTypeRef<CMSampleBufferRef> sample,
      VideoToolboxDecompressionSessionMetadata session_metadata,
      scoped_refptr<CodecPicture> picture);
  void OnAcceleratorOutput(scoped_refptr<CodecPicture> picture);

  // |video_toolbox_| callbacks.
  void OnVideoToolboxOutput(
      base::apple::ScopedCFTypeRef<CVImageBufferRef> image,
      std::unique_ptr<VideoToolboxDecodeMetadata> metadata);
  void OnVideoToolboxError(DecoderStatus status);

  // |converter_| callbacks.
  void OnConverterOutput(scoped_refptr<VideoFrame> frame,
                         std::unique_ptr<VideoToolboxDecodeMetadata> metadata);

  scoped_refptr<base::SequencedTaskRunner> task_runner_;
  std::unique_ptr<MediaLog> media_log_;
  gpu::GpuDriverBugWorkarounds gpu_workarounds_;
  scoped_refptr<base::SequencedTaskRunner> gpu_task_runner_;
  GetCommandBufferStubCB get_stub_cb_;

  bool has_error_ = false;

  std::unique_ptr<AcceleratedVideoDecoder> accelerator_;
  VideoToolboxDecompressionSessionManager video_toolbox_;
  scoped_refptr<VideoToolboxFrameConverter> converter_;
  VideoToolboxOutputQueue output_queue_;

  VideoDecoderConfig config_;

  // Used to link re-entrant OnAcceleratorDecode() callbacks to Decode() calls.
  scoped_refptr<DecoderBuffer> active_decode_;

  // Accounts for frames that have been decoded but not yet converted. These
  // contribute to backpressure.
  size_t num_conversions_ = 0;

  // Decode callbacks, which are released in decode order. There is no mapping
  // to decode requests or frames, it is simply a backpressure mechanism.
  base::queue<DecodeCB> decode_cbs_;

  // Converter callbacks are invalidated during resets.
  base::WeakPtrFactory<VideoToolboxVideoDecoder> converter_weak_this_factory_{
      this};
};

}  // namespace media

#endif  // MEDIA_GPU_MAC_VIDEO_TOOLBOX_VIDEO_DECODER_H_