1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
6#define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
7
8#include <list>
9#include <queue>
10
11#include "base/memory/linked_ptr.h"
12#include "base/threading/thread.h"
13#include "content/common/content_export.h"
14#include "content/common/gpu/media/h264_dpb.h"
15#include "content/common/gpu/media/va_surface.h"
16#include "content/common/gpu/media/vaapi_wrapper.h"
17#include "media/filters/h264_bitstream_buffer.h"
18#include "media/video/video_encode_accelerator.h"
19
20namespace content {
21
22// A VideoEncodeAccelerator implementation that uses VA-API
23// (http://www.freedesktop.org/wiki/Software/vaapi) for HW-accelerated
24// video encode.
25class CONTENT_EXPORT VaapiVideoEncodeAccelerator
26    : public media::VideoEncodeAccelerator {
27 public:
28  explicit VaapiVideoEncodeAccelerator(Display* x_display);
29  virtual ~VaapiVideoEncodeAccelerator();
30
31  // media::VideoEncodeAccelerator implementation.
32  virtual std::vector<media::VideoEncodeAccelerator::SupportedProfile>
33      GetSupportedProfiles() OVERRIDE;
34  virtual bool Initialize(media::VideoFrame::Format format,
35                          const gfx::Size& input_visible_size,
36                          media::VideoCodecProfile output_profile,
37                          uint32 initial_bitrate,
38                          Client* client) OVERRIDE;
39  virtual void Encode(const scoped_refptr<media::VideoFrame>& frame,
40                      bool force_keyframe) OVERRIDE;
41  virtual void UseOutputBitstreamBuffer(
42      const media::BitstreamBuffer& buffer) OVERRIDE;
43  virtual void RequestEncodingParametersChange(uint32 bitrate,
44                                               uint32 framerate) OVERRIDE;
45  virtual void Destroy() OVERRIDE;
46
47 private:
48  // Reference picture list.
49  typedef std::list<scoped_refptr<VASurface> > RefPicList;
50
51  // Encode job for one frame. Created when an input frame is awaiting and
52  // enough resources are available to proceed. Once the job is prepared and
53  // submitted to the hardware, it awaits on the submitted_encode_jobs_ queue
54  // for an output bitstream buffer to become available. Once one is ready,
55  // the encoded bytes are downloaded to it and job resources are released
56  // and become available for reuse.
57  struct EncodeJob {
58    // Input surface for video frame data.
59    scoped_refptr<VASurface> input_surface;
60    // Surface for a reconstructed picture, which is used for reference
61    // for subsequent frames.
62    scoped_refptr<VASurface> recon_surface;
63    // Buffer that will contain output bitstream for this frame.
64    VABufferID coded_buffer;
65    // Reference surfaces required to encode this picture. We keep references
66    // to them here, because we may discard some of them from ref_pic_list*
67    // before the HW job is done.
68    RefPicList reference_surfaces;
69    // True if this job will produce a keyframe. Used to report
70    // to BitstreamBufferReady().
71    bool keyframe;
72
73    EncodeJob();
74    ~EncodeJob();
75  };
76
77  // Encoder state.
78  enum State {
79    kUninitialized,
80    kEncoding,
81    kError,
82  };
83
84  // Holds input frames coming from the client ready to be encoded.
85  struct InputFrameRef;
86  // Holds output buffers coming from the client ready to be filled.
87  struct BitstreamBufferRef;
88
89  // Tasks for each of the VEA interface calls to be executed on the
90  // encoder thread.
91  void InitializeTask();
92  void EncodeTask(const scoped_refptr<media::VideoFrame>& frame,
93                  bool force_keyframe);
94  void UseOutputBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref);
95  void RequestEncodingParametersChangeTask(uint32 bitrate, uint32 framerate);
96  void DestroyTask();
97
98  // Prepare and schedule an encode job if we have an input to encode
99  // and enough resources to proceed.
100  void EncodeFrameTask();
101
102  // Fill current_sps_/current_pps_ with current values.
103  void UpdateSPS();
104  void UpdatePPS();
105  void UpdateRates(uint32 bitrate, uint32 framerate);
106
107  // Generate packed SPS and PPS in packed_sps_/packed_pps_, using
108  // values in current_sps_/current_pps_.
109  void GeneratePackedSPS();
110  void GeneratePackedPPS();
111
112  // Check if we have sufficient resources for a new encode job, claim them and
113  // fill current_encode_job_ with them.
114  // Return false if we cannot start a new job yet, true otherwise.
115  bool PrepareNextJob();
116
117  // Begin a new frame, making it a keyframe if |force_keyframe| is true,
118  // updating current_pic_.
119  void BeginFrame(bool force_keyframe);
120
121  // End current frame, updating reference picture lists and storing current
122  // job in the jobs awaiting completion on submitted_encode_jobs_.
123  void EndFrame();
124
125  // Submit parameters for the current frame to the hardware.
126  bool SubmitFrameParameters();
127  // Submit keyframe headers to the hardware if the current frame is a keyframe.
128  bool SubmitHeadersIfNeeded();
129
130  // Upload image data from |frame| to the input surface for current job.
131  bool UploadFrame(const scoped_refptr<media::VideoFrame>& frame);
132
133  // Execute encode in hardware. This does not block and will return before
134  // the job is finished.
135  bool ExecuteEncode();
136
137  // Callback that returns a no longer used VASurfaceID to
138  // available_va_surface_ids_ for reuse.
139  void RecycleVASurfaceID(VASurfaceID va_surface_id);
140
141  // Tries to return a bitstream buffer if both a submitted job awaits to
142  // be completed and we have bitstream buffers from the client available
143  // to download the encoded data to.
144  void TryToReturnBitstreamBuffer();
145
146  // Puts the encoder into en error state and notifies client about the error.
147  void NotifyError(Error error);
148
149  // Sets the encoder state on the correct thread.
150  void SetState(State state);
151
152  // VaapiWrapper is the owner of all HW resources (surfaces and buffers)
153  // and will free them on destruction.
154  scoped_ptr<VaapiWrapper> vaapi_wrapper_;
155
156  // Input profile and sizes.
157  media::VideoCodecProfile profile_;
158  gfx::Size visible_size_;
159  gfx::Size coded_size_;  // Macroblock-aligned.
160  // Width/height in macroblocks.
161  unsigned int mb_width_;
162  unsigned int mb_height_;
163
164  // Maximum size of the reference list 0.
165  unsigned int max_ref_idx_l0_size_;
166
167  // Initial QP.
168  unsigned int qp_;
169
170  // IDR frame period.
171  unsigned int idr_period_;
172  // I frame period.
173  unsigned int i_period_;
174  // IP period, i.e. how often do we need to have either an I or a P frame in
175  // the stream. Period of 1 means we can have no B frames.
176  unsigned int ip_period_;
177
178  // Size in bytes required for input bitstream buffers.
179  size_t output_buffer_byte_size_;
180
181  Display* x_display_;
182
183  // All of the members below must be accessed on the encoder_thread_,
184  // while it is running.
185
186  // Encoder state. Encode tasks will only run in kEncoding state.
187  State state_;
188
189  // frame_num to be used for the next frame.
190  unsigned int frame_num_;
191  // frame_num of the previous IDR.
192  unsigned int last_idr_frame_num_;
193
194  // Current bitrate in bps.
195  unsigned int bitrate_;
196  // Current fps.
197  unsigned int framerate_;
198  // CPB size in bits, i.e. bitrate in kbps * window size in ms/1000.
199  unsigned int cpb_size_;
200  // True if the parameters have changed and we need to submit a keyframe
201  // with updated parameters.
202  bool encoding_parameters_changed_;
203
204  // Job currently being prepared for encode.
205  scoped_ptr<EncodeJob> current_encode_job_;
206
207  // Current SPS, PPS and their packed versions. Packed versions are their NALUs
208  // in AnnexB format *without* emulation prevention three-byte sequences
209  // (those will be added by the driver).
210  media::H264SPS current_sps_;
211  media::H264BitstreamBuffer packed_sps_;
212  media::H264PPS current_pps_;
213  media::H264BitstreamBuffer packed_pps_;
214
215  // Picture currently being prepared for encode.
216  H264Picture current_pic_;
217
218  // VA surfaces available for reuse.
219  std::vector<VASurfaceID> available_va_surface_ids_;
220
221  // VA buffers for coded frames.
222  std::vector<VABufferID> available_va_buffer_ids_;
223
224  // Currently active reference surfaces.
225  RefPicList ref_pic_list0_;
226
227  // Callback via which finished VA surfaces are returned to us.
228  VASurface::ReleaseCB va_surface_release_cb_;
229
230  // VideoFrames passed from the client, waiting to be encoded.
231  std::queue<linked_ptr<InputFrameRef> > encoder_input_queue_;
232
233  // BitstreamBuffers mapped, ready to be filled.
234  std::queue<linked_ptr<BitstreamBufferRef> > available_bitstream_buffers_;
235
236  // Jobs submitted for encode, awaiting bitstream buffers to become available.
237  std::queue<linked_ptr<EncodeJob> > submitted_encode_jobs_;
238
239  // Encoder thread. All tasks are executed on it.
240  base::Thread encoder_thread_;
241  scoped_refptr<base::MessageLoopProxy> encoder_thread_proxy_;
242
243  const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
244
245  // To expose client callbacks from VideoEncodeAccelerator.
246  // NOTE: all calls to these objects *MUST* be executed on
247  // child_message_loop_proxy_.
248  scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_;
249  base::WeakPtr<Client> client_;
250
251  // WeakPtr to post from the encoder thread back to the ChildThread, as it may
252  // outlive this. Posting from the ChildThread using base::Unretained(this)
253  // to the encoder thread is safe, because |this| always outlives the encoder
254  // thread (it's a member of this class).
255  base::WeakPtr<VaapiVideoEncodeAccelerator> weak_this_;
256  base::WeakPtrFactory<VaapiVideoEncodeAccelerator> weak_this_ptr_factory_;
257
258  DISALLOW_COPY_AND_ASSIGN(VaapiVideoEncodeAccelerator);
259};
260
261}  // namespace content
262
263#endif  // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_ENCODE_ACCELERATOR_H_
264