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_h265_accelerator.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_H265_ACCELERATOR_H_
#define MEDIA_GPU_MAC_VIDEO_TOOLBOX_H265_ACCELERATOR_H_

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

#include <memory>
#include <vector>

#include "base/apple/scoped_cftyperef.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/sequence_checker.h"
#include "media/base/video_types.h"
#include "media/gpu/h265_decoder.h"
#include "media/gpu/mac/video_toolbox_decompression_metadata.h"
#include "media/gpu/media_gpu_export.h"

namespace media {

class MediaLog;

class MEDIA_GPU_EXPORT VideoToolboxH265Accelerator
    : public H265Decoder::H265Accelerator {
 public:
  using DecodeCB = base::RepeatingCallback<void(
      base::apple::ScopedCFTypeRef<CMSampleBufferRef>,
      VideoToolboxDecompressionSessionMetadata,
      scoped_refptr<CodecPicture>)>;
  using OutputCB = base::RepeatingCallback<void(scoped_refptr<CodecPicture>)>;

  VideoToolboxH265Accelerator(std::unique_ptr<MediaLog> media_log,
                              DecodeCB decode_cb,
                              OutputCB output_cb);
  ~VideoToolboxH265Accelerator() override;

  // H265Accelerator implementation.
  scoped_refptr<H265Picture> CreateH265Picture() override;
  void ProcessVPS(const H265VPS* vps,
                  base::span<const uint8_t> vps_nalu_data) override;
  void ProcessSPS(const H265SPS* sps,
                  base::span<const uint8_t> sps_nalu_data) override;
  void ProcessPPS(const H265PPS* pps,
                  base::span<const uint8_t> pps_nalu_data) override;
  Status SubmitFrameMetadata(
      const H265SPS* sps,
      const H265PPS* pps,
      const H265SliceHeader* slice_hdr,
      const H265Picture::Vector& ref_pic_list,
      const H265Picture::Vector& ref_pic_set_lt_curr,
      const H265Picture::Vector& ref_pic_set_st_curr_after,
      const H265Picture::Vector& ref_pic_set_st_curr_before,
      scoped_refptr<H265Picture> pic) override;
  Status SubmitSlice(const H265SPS* sps,
                     const H265PPS* pps,
                     const H265SliceHeader* slice_hdr,
                     const H265Picture::Vector& ref_pic_list0,
                     const H265Picture::Vector& ref_pic_list1,
                     const H265Picture::Vector& ref_pic_set_lt_curr,
                     const H265Picture::Vector& ref_pic_set_st_curr_after,
                     const H265Picture::Vector& ref_pic_set_st_curr_before,
                     scoped_refptr<H265Picture> pic,
                     const uint8_t* data,
                     size_t size,
                     const std::vector<SubsampleEntry>& subsamples) override;
  Status SubmitDecode(scoped_refptr<H265Picture> pic) override;
  bool OutputPicture(scoped_refptr<H265Picture> pic) override;
  void Reset() override;
  bool IsChromaSamplingSupported(VideoChromaSampling format) override;
  bool IsAlphaLayerSupported() override;

 private:
  bool ExtractParameterSetData(
      const char* parameter_set_name,
      const base::flat_set<int>& parameter_set_ids,
      const base::flat_map<int, std::vector<uint8_t>>& seen_parameter_set_data,
      base::flat_map<int, std::vector<uint8_t>>* active_parameter_set_data_out,
      std::vector<const uint8_t*>* parameter_set_data_out,
      std::vector<size_t>* parameter_set_size_out);
  bool CreateFormat(scoped_refptr<H265Picture> pic);
  bool ExtractChangedParameterSetData(
      const char* parameter_set_name,
      const base::flat_set<int>& parameter_set_ids,
      const base::flat_map<int, std::vector<uint8_t>>& seen_parameter_set_data,
      base::flat_map<int, std::vector<uint8_t>>* active_parameter_set_data_out,
      std::vector<base::span<const uint8_t>>* parameter_set_data_out);
  void ResetFrameData();

  std::unique_ptr<MediaLog> media_log_;

  // Callbacks are called synchronously, which is always re-entrant.
  DecodeCB decode_cb_;
  OutputCB output_cb_;

  // Raw parameter set bytes that have been observed.
  base::flat_map<int, std::vector<uint8_t>> seen_vps_data_;  // IDs can be 0-16
  base::flat_map<int, std::vector<uint8_t>> seen_sps_data_;  // IDs can be 0-15
  base::flat_map<int, std::vector<uint8_t>> seen_pps_data_;  // IDs can be 0-63

  // Cached parameter values.
  base::flat_set<int> alpha_vps_ids_;

  // Raw parameter set bytes that have been sent to the decoder, to compare for
  // changes.
  base::flat_map<int, std::vector<uint8_t>> active_vps_data_;
  base::flat_map<int, std::vector<uint8_t>> active_sps_data_;
  base::flat_map<int, std::vector<uint8_t>> active_pps_data_;

  base::apple::ScopedCFTypeRef<CMFormatDescriptionRef> active_format_;
  VideoToolboxDecompressionSessionMetadata active_session_metadata_;

  // Accumulated data for the current frame.
  base::flat_set<int> frame_vps_ids_;  // Note: there should be exactly one VPS.
  base::flat_set<int> frame_sps_ids_;
  base::flat_set<int> frame_pps_ids_;
  // TODO(367764863) Rewrite to base::raw_span.
  RAW_PTR_EXCLUSION std::vector<base::span<const uint8_t>> frame_slice_data_;
  uint8_t frame_bit_depth_ = 8;
  VideoChromaSampling frame_chroma_sampling_ = VideoChromaSampling::k420;
  bool frame_is_keyframe_ = false;
  bool frame_has_alpha_ = false;
  bool drop_frame_ = false;

  SEQUENCE_CHECKER(sequence_checker_);
};

}  // namespace media

#endif  // MEDIA_GPU_MAC_VIDEO_TOOLBOX_H265_ACCELERATOR_H_