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

media / gpu / v4l2 / v4l2_video_decoder_delegate_h264.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 MEDIA_GPU_V4L2_V4L2_VIDEO_DECODER_DELEGATE_H264_H_
#define MEDIA_GPU_V4L2_V4L2_VIDEO_DECODER_DELEGATE_H264_H_

#include <memory>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "media/base/cdm_context.h"
#include "media/gpu/h264_decoder.h"
#include "media/gpu/h264_dpb.h"
#include "media/parsers/h264_parser.h"

namespace media {

class V4L2Device;
class V4L2DecodeSurface;
class V4L2DecodeSurfaceHandler;
struct V4L2VideoDecoderDelegateH264Private;

// This is used by the secure world when parsing the stream to create
// CencV1SliceParameterBufferH264 (defined in the .cc file). This contains all
// the required SPS/PPS fields used in slice header parsing so that we don't
// need to re-parse the SPS/PPS in the secure world.
struct CencV1StreamDataForSliceHeader {
  int32_t log2_max_frame_num_minus4;
  int32_t log2_max_pic_order_cnt_lsb_minus4;
  int32_t pic_order_cnt_type;
  int32_t num_ref_idx_l0_default_active_minus1;
  int32_t num_ref_idx_l1_default_active_minus1;
  int32_t weighted_bipred_idc;
  int32_t chroma_array_type;
  uint8_t frame_mbs_only_flag;
  uint8_t bottom_field_pic_order_in_frame_present_flag;
  uint8_t delta_pic_order_always_zero_flag;
  uint8_t redundant_pic_cnt_present_flag;
  uint8_t weighted_pred_flag;
  uint8_t padding[3];
};

class V4L2VideoDecoderDelegateH264 : public H264Decoder::H264Accelerator {
 public:
  using Status = H264Decoder::H264Accelerator::Status;

  explicit V4L2VideoDecoderDelegateH264(
      V4L2DecodeSurfaceHandler* surface_handler,
      V4L2Device* device,
      CdmContext* cdm_context);

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

  ~V4L2VideoDecoderDelegateH264() override;

  // H264Decoder::H264Accelerator implementation.
  scoped_refptr<H264Picture> CreateH264Picture() override;
  scoped_refptr<H264Picture> CreateH264PictureSecure(
      uint64_t secure_handle) override;
  void ProcessSPS(const H264SPS* sps,
                  base::span<const uint8_t> sps_nalu_data) override;
  void ProcessPPS(const H264PPS* pps,
                  base::span<const uint8_t> pps_nalu_data) override;
  Status SubmitFrameMetadata(const H264SPS* sps,
                             const H264PPS* pps,
                             const H264DPB& dpb,
                             const H264Picture::Vector& ref_pic_listp0,
                             const H264Picture::Vector& ref_pic_listb0,
                             const H264Picture::Vector& ref_pic_listb1,
                             scoped_refptr<H264Picture> pic) override;
  Status ParseEncryptedSliceHeader(
      const std::vector<base::span<const uint8_t>>& data,
      const std::vector<SubsampleEntry>& subsamples,
      uint64_t secure_handle,
      H264SliceHeader* slice_header_out) override;
  Status SubmitSlice(const H264PPS* pps,
                     const H264SliceHeader* slice_hdr,
                     const H264Picture::Vector& ref_pic_list0,
                     const H264Picture::Vector& ref_pic_list1,
                     scoped_refptr<H264Picture> pic,
                     const uint8_t* data,
                     size_t size,
                     const std::vector<SubsampleEntry>& subsamples) override;
  Status SubmitDecode(scoped_refptr<H264Picture> pic) override;
  bool OutputPicture(scoped_refptr<H264Picture> pic) override;
  void Reset() override;

 private:
  std::vector<scoped_refptr<V4L2DecodeSurface>> H264DPBToV4L2DPB(
      const H264DPB& dpb);
  scoped_refptr<V4L2DecodeSurface> H264PictureToV4L2DecodeSurface(
      H264Picture* pic);
  void OnEncryptedSliceHeaderParsed(bool status,
                                    const std::vector<uint8_t>& parsed_headers);

  raw_ptr<V4L2DecodeSurfaceHandler> const surface_handler_;
  raw_ptr<V4L2Device> const device_;
  raw_ptr<CdmContext> cdm_context_;

  // The last returned data for async encrypted slice header parsing, we hold
  // onto this so when we get invoked a second time to parse it we know the
  // result and can immediately return it.
  std::vector<uint8_t> last_parsed_encrypted_slice_header_;
  bool encrypted_slice_header_parsing_failed_ = false;
  bool encrypted_slice_header_parsing_active_ = false;

  // For multi-slice CENCv1 H264 content we will need to track the size of the
  // headers already processed so we know where the subsequent headers are at in
  // the secure buffer.
  size_t encrypted_slice_header_offset_ = 0;

  // Tracking of the last SPS/PPS data so we can use the values for encrypted
  // slice header parsing.
  struct CencV1StreamDataForSliceHeader cencv1_stream_data_;

  // Contains the kernel-specific structures that we don't want to expose
  // outside of the compilation unit.
  const std::unique_ptr<V4L2VideoDecoderDelegateH264Private> priv_;

  base::WeakPtrFactory<V4L2VideoDecoderDelegateH264> weak_factory_{this};
};

}  // namespace media

#endif  // MEDIA_GPU_V4L2_V4L2_VIDEO_DECODER_DELEGATE_H264_H_