summaryrefslogtreecommitdiff
path: root/chromium/media/gpu/vaapi/vaapi_video_encoder_delegate.h
blob: 5bdb6c27c2899e608b1174b372874288ea944d1b (plain)
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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_GPU_VAAPI_VAAPI_VIDEO_ENCODER_DELEGATE_H_
#define MEDIA_GPU_VAAPI_VAAPI_VIDEO_ENCODER_DELEGATE_H_

#include <va/va.h>
#include <vector>

#include "base/callback.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "media/base/video_bitrate_allocation.h"
#include "media/base/video_codecs.h"
#include "media/video/video_encode_accelerator.h"
#include "media/video/video_encoder_info.h"
#include "ui/gfx/geometry/size.h"

namespace base {
class RefCountedBytes;
}

namespace media {
struct BitstreamBufferMetadata;
class CodecPicture;
class ScopedVABuffer;
class VideoFrame;
class VASurface;
class VaapiWrapper;

// An VaapiVideoEncoderDelegate  performs high-level, platform-independent
// encoding process tasks, such as managing codec state, reference frames, etc.,
// but may require support from an external accelerator (typically a hardware
// accelerator) to offload some stages of the actual encoding process, using
// the parameters that the Delegate prepares beforehand.
//
// For each frame to be encoded, clients provide an EncodeJob object to be set
// up by a Delegate subclass with job parameters, and execute the job
// afterwards. Any resources required for the job are also provided by the
// clients, and associated with the EncodeJob object.
class VaapiVideoEncoderDelegate {
 public:
  VaapiVideoEncoderDelegate(scoped_refptr<VaapiWrapper> vaapi_wrapper,
                            base::RepeatingClosure error_cb);
  virtual ~VaapiVideoEncoderDelegate();

  enum class BitrateControl {
    kConstantBitrate,  // Constant Bitrate mode. This class relies on other
                       // parts (e.g. driver) to achieve the specified bitrate.
    kConstantQuantizationParameter  // Constant Quantization Parameter mode.
                                    // This class needs to compute a proper
                                    // quantization parameter and give other
                                    // parts (e.g. the driver) the value.
  };

  struct Config {
    // Maxium number of reference frames.
    // For H.264 encoding, the value represents the maximum number of reference
    // frames for both the reference picture list 0 (bottom 16 bits) and the
    // reference picture list 1 (top 16 bits).
    size_t max_num_ref_frames;

    BitrateControl bitrate_control = BitrateControl::kConstantBitrate;
  };

  // An abstraction of an encode job for one frame. Parameters required for an
  // EncodeJob to be executed are prepared by an VaapiVideoEncoderDelegate,
  // while the accelerator-specific callbacks required to set up and execute it
  // are provided by the accelerator itself, based on these parameters.
  // Accelerators are also responsible for providing any resources (such as
  // memory for output and reference pictures, etc.) as needed.
  class EncodeJob {
   public:
    // Creates an EncodeJob to encode |input_frame|, which will be executed
    // by calling |execute_cb|. If |keyframe| is true, requests this job
    // to produce a keyframe.
    EncodeJob(scoped_refptr<VideoFrame> input_frame,
              bool keyframe,
              base::OnceClosure execute_cb);
    // Constructor for VA-API.
    EncodeJob(scoped_refptr<VideoFrame> input_frame,
              bool keyframe,
              base::OnceClosure execute_cb,
              scoped_refptr<VASurface> input_surface,
              scoped_refptr<CodecPicture> picture,
              std::unique_ptr<ScopedVABuffer> coded_buffer);
    ~EncodeJob();

    // Schedules a callback to be run immediately before this job is executed.
    // Can be called multiple times to schedule multiple callbacks, and all
    // of them will be run, in order added.
    // Callbacks can be used to e.g. set up hardware parameters before the job
    // is executed.
    void AddSetupCallback(base::OnceClosure cb);

    // Schedules a callback to be run immediately after this job is executed.
    // Can be called multiple times to schedule multiple callbacks, and all
    // of them will be run, in order added. Callbacks can be used to e.g. get
    // the encoded buffer linear size.
    void AddPostExecuteCallback(base::OnceClosure cb);

    // Adds |ref_pic| to the list of pictures to be used as reference pictures
    // for this frame, to ensure they remain valid until the job is executed
    // (or discarded).
    void AddReferencePicture(scoped_refptr<CodecPicture> ref_pic);

    // Runs all setup callbacks previously scheduled, if any, in order added,
    // and executes the job by calling the execute callback. Note that the
    // actual job execution may be asynchronous, and returning from this method
    // does not have to indicate that the job has been finished. The execute
    // callback is responsible for retaining references to any resources that
    // may be in use after this method returns however, so it is safe to release
    // the EncodeJob object itself immediately after this method returns.
    void Execute();

    // Requests this job to produce a keyframe; requesting a keyframe may not
    // always result in one being produced by the encoder (e.g. if it would
    // not fit in the bitrate budget).
    void ProduceKeyframe() { keyframe_ = true; }

    // Returns true if this job has been requested to produce a keyframe.
    bool IsKeyframeRequested() const { return keyframe_; }

    // Returns the timestamp associated with this job.
    base::TimeDelta timestamp() const { return timestamp_; }

    // VA-API specific methods.
    VABufferID coded_buffer_id() const;
    const scoped_refptr<VASurface>& input_surface() const;
    const scoped_refptr<CodecPicture>& picture() const;

   private:
    // Input VideoFrame to be encoded.
    const scoped_refptr<VideoFrame> input_frame_;

    // Source timestamp for |input_frame_|.
    const base::TimeDelta timestamp_;

    // True if this job is to produce a keyframe.
    bool keyframe_;

    // VA-API specific members.
    // Input surface for video frame data or scaled data.
    const scoped_refptr<VASurface> input_surface_;
    const scoped_refptr<CodecPicture> picture_;
    // Buffer that will contain the output bitstream data for this frame.
    const std::unique_ptr<ScopedVABuffer> coded_buffer_;

    // Callbacks to be run (in the same order as the order of AddSetupCallback()
    // calls) to set up the job.
    base::queue<base::OnceClosure> setup_callbacks_;

    // Callbacks to be run (in the same order as the order of
    // AddPostExecuteCallback() calls) to do post processing after execute.
    base::queue<base::OnceClosure> post_execute_callbacks_;

    // Callback to be run to execute this job.
    base::OnceClosure execute_callback_;

    // Reference pictures required for this job.
    std::vector<scoped_refptr<CodecPicture>> reference_pictures_;

    DISALLOW_COPY_AND_ASSIGN(EncodeJob);
  };

  // Initializes the encoder with requested parameter set |config| and
  // |ave_config|. Returns false if the requested set of parameters is not
  // supported, true on success.
  virtual bool Initialize(
      const VideoEncodeAccelerator::Config& config,
      const VaapiVideoEncoderDelegate::Config& ave_config) = 0;

  // Updates current framerate and/or bitrate to |framerate| in FPS
  // and the specified video bitrate allocation.
  virtual bool UpdateRates(const VideoBitrateAllocation& bitrate_allocation,
                           uint32_t framerate) = 0;

  // Returns coded size for the input buffers required to encode, in pixels;
  // typically visible size adjusted to match codec alignment requirements.
  virtual gfx::Size GetCodedSize() const = 0;

  // Returns minimum size in bytes for bitstream buffers required to fit output
  // stream buffers produced.
  virtual size_t GetBitstreamBufferSize() const;

  // Returns maximum number of reference frames that may be used by the
  // encoder to encode one frame. The client should be able to provide up to
  // at least this many frames simultaneously for encode to make progress.
  virtual size_t GetMaxNumOfRefFrames() const = 0;

  // Prepares a new |encode_job| to be executed in Accelerator and returns true
  // on success. The caller may then call Execute() on the job to run it.
  virtual bool PrepareEncodeJob(EncodeJob* encode_job) = 0;

  // Notifies the encoded chunk size in bytes to update a bitrate controller in
  // VaapiVideoEncoderDelegate. This should be called only if
  // VaapiVideoEncoderDelegate is configured with
  // BitrateControl::kConstantQuantizationParameter.
  virtual void BitrateControlUpdate(uint64_t encoded_chunk_size_bytes);

  virtual BitstreamBufferMetadata GetMetadata(EncodeJob* encode_job,
                                              size_t payload_size);

  // Gets the active spatial layer resolutions for K-SVC encoding, VaapiVEA
  // can get this info from the encoder delegate. Returns empty vector on
  // failure.
  virtual std::vector<gfx::Size> GetSVCLayerResolutions() = 0;

  // Submits |buffer| of |type| to the driver.
  void SubmitBuffer(VABufferType type,
                    scoped_refptr<base::RefCountedBytes> buffer);

  // Submits a VAEncMiscParameterBuffer |buffer| of type |type| to the driver.
  void SubmitVAEncMiscParamBuffer(VAEncMiscParameterType type,
                                  scoped_refptr<base::RefCountedBytes> buffer);

 protected:
  const scoped_refptr<VaapiWrapper> vaapi_wrapper_;

  base::RepeatingClosure error_cb_;

  SEQUENCE_CHECKER(sequence_checker_);
};

}  // namespace media

#endif  // MEDIA_GPU_VAAPI_VAAPI_VIDEO_ENCODER_DELEGATE_H_