1// Copyright (c) 2012 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// This file contains an implementation of a class that provides H264 decode
6// support for use with VAAPI hardware video decode acceleration on Intel
7// systems.
8
9#ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_
10#define CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_
11
12#include <vector>
13
14#include "base/callback_forward.h"
15#include "base/memory/linked_ptr.h"
16#include "base/memory/ref_counted.h"
17#include "base/memory/scoped_ptr.h"
18#include "content/common/gpu/media/h264_dpb.h"
19#include "content/common/gpu/media/vaapi_wrapper.h"
20#include "media/base/limits.h"
21#include "media/filters/h264_parser.h"
22
23namespace content {
24
25// An H264 decoder that utilizes VA-API. Provides features not supported by
26// the VA-API userspace library (libva), including stream parsing, reference
27// picture management and other operations not supported by the HW codec.
28//
29// Provides functionality to allow plugging VAAPI HW acceleration into the
30// VDA framework.
31//
32// Clients of this class are expected to pass H264 Annex-B byte stream and
33// will receive decoded surfaces via client-provided |OutputPicCB|.
34//
35// This class must be created, called and destroyed on a single thread, and
36// does nothing internally on any other thread.
37class CONTENT_EXPORT VaapiH264Decoder {
38 public:
39  // Callback invoked on the client when a surface is to be displayed.
40  // Arguments: input buffer id provided at the time of Decode()
41  // and VASurface to output.
42  typedef base::Callback<
43      void(int32, const scoped_refptr<VASurface>&)> OutputPicCB;
44
45  enum VAVDAH264DecoderFailure {
46    FRAME_MBS_ONLY_FLAG_NOT_ONE = 0,
47    GAPS_IN_FRAME_NUM = 1,
48    MID_STREAM_RESOLUTION_CHANGE = 2,
49    INTERLACED_STREAM = 3,
50    VAAPI_ERROR = 4,
51    VAVDA_H264_DECODER_FAILURES_MAX,
52  };
53
54  // Callback to report errors for UMA purposes, not used to return errors
55  // to clients.
56  typedef base::Callback<void(VAVDAH264DecoderFailure error)>
57      ReportErrorToUmaCB;
58
59  // Decode result codes.
60  enum DecResult {
61    kDecodeError,  // Error while decoding.
62    // TODO posciak: unsupported streams are currently treated as error
63    // in decoding; in future it could perhaps be possible to fall back
64    // to software decoding instead.
65    // kStreamError,  // Error in stream.
66    kAllocateNewSurfaces,  // Need a new set of surfaces to be allocated.
67    kRanOutOfStreamData,  // Need more stream data to proceed.
68    kRanOutOfSurfaces,  // Waiting for the client to free up output surfaces.
69  };
70
71  // |vaapi_wrapper| should be initialized.
72  // |output_pic_cb| notifies the client a surface is to be displayed.
73  // |report_error_to_uma_cb| called on errors for UMA purposes, not used
74  // to report errors to clients.
75  VaapiH264Decoder(VaapiWrapper* vaapi_wrapper,
76                   const OutputPicCB& output_pic_cb,
77                   const ReportErrorToUmaCB& report_error_to_uma_cb);
78
79  ~VaapiH264Decoder();
80
81  // Have the decoder flush its state and trigger output of all previously
82  // decoded surfaces via OutputPicCB. Return false on failure.
83  bool Flush() WARN_UNUSED_RESULT;
84
85  // To be called during decoding.
86  // Stop (pause) decoding, discarding all remaining inputs and outputs,
87  // but do not flush decoder state, so that the playback can be resumed later,
88  // possibly from a different location.
89  void Reset();
90
91  // Set current stream data pointer to |ptr| and |size|. Output surfaces
92  // that are decoded from data in this stream chunk are to be returned along
93  // with the given |input_id|.
94  void SetStream(const uint8* ptr, size_t size, int32 input_id);
95
96  // Try to decode more of the stream, returning decoded frames asynchronously
97  // via output_pic_cb_. Return when more stream is needed, when we run out
98  // of free surfaces, when we need a new set of them, or when an error occurs.
99  DecResult Decode() WARN_UNUSED_RESULT;
100
101  // Return dimensions/required number of output surfaces that client should
102  // be ready to provide for the decoder to function properly.
103  // To be used after Decode() returns kNeedNewSurfaces.
104  gfx::Size GetPicSize() { return pic_size_; }
105  size_t GetRequiredNumOfPictures();
106
107  // To be used by the client to feed decoder with output surfaces.
108  void ReuseSurface(const scoped_refptr<VASurface>& va_surface);
109
110 private:
111  // We need to keep at most kDPBMaxSize pictures in DPB for
112  // reference/to display later and an additional one for the one currently
113  // being decoded. We also ask for some additional ones since VDA needs
114  // to accumulate a few ready-to-output pictures before it actually starts
115  // displaying and giving them back. +2 instead of +1 because of subjective
116  // smoothness improvement during testing.
117  enum {
118    kPicsInPipeline = media::limits::kMaxVideoFrames + 2,
119    kMaxNumReqPictures = H264DPB::kDPBMaxSize + kPicsInPipeline,
120  };
121
122  // Internal state of the decoder.
123  enum State {
124    kNeedStreamMetadata,  // After initialization, need an SPS.
125    kDecoding,  // Ready to decode from any point.
126    kAfterReset, // After Reset(), need a resume point.
127    kError,  // Error in decode, can't continue.
128  };
129
130  // Process H264 stream structures.
131  bool ProcessSPS(int sps_id, bool* need_new_buffers);
132  bool ProcessPPS(int pps_id);
133  bool ProcessSlice(media::H264SliceHeader* slice_hdr);
134
135  // Initialize the current picture according to data in |slice_hdr|.
136  bool InitCurrPicture(media::H264SliceHeader* slice_hdr);
137
138  // Calculate picture order counts for the new picture
139  // on initialization of a new frame (see spec).
140  bool CalculatePicOrderCounts(media::H264SliceHeader* slice_hdr);
141
142  // Update PicNum values in pictures stored in DPB on creation of new
143  // frame (see spec).
144  void UpdatePicNums();
145
146  bool UpdateMaxNumReorderFrames(const media::H264SPS* sps);
147
148  // Prepare reference picture lists (ref_pic_list[01]_).
149  bool PrepareRefPicLists(media::H264SliceHeader* slice_hdr);
150
151  // Construct initial reference picture lists for use in decoding of
152  // P and B pictures (see 8.2.4 in spec).
153  void ConstructReferencePicListsP(media::H264SliceHeader* slice_hdr);
154  void ConstructReferencePicListsB(media::H264SliceHeader* slice_hdr);
155
156  // Helper functions for reference list construction, per spec.
157  int PicNumF(H264Picture *pic);
158  int LongTermPicNumF(H264Picture *pic);
159
160  // Perform the reference picture lists' modification (reordering), as
161  // specified in spec (8.2.4).
162  //
163  // |list| indicates list number and should be either 0 or 1.
164  bool ModifyReferencePicList(media::H264SliceHeader* slice_hdr, int list);
165
166  // Perform reference picture memory management operations (marking/unmarking
167  // of reference pictures, long term picture management, discarding, etc.).
168  // See 8.2.5 in spec.
169  bool HandleMemoryManagementOps();
170  void ReferencePictureMarking();
171
172  // Start processing a new frame.
173  bool StartNewFrame(media::H264SliceHeader* slice_hdr);
174
175  // All data for a frame received, process it and decode.
176  bool FinishPrevFrameIfPresent();
177
178  // Called after decoding, performs all operations to be done after decoding,
179  // including DPB management, reference picture marking and memory management
180  // operations.
181  // This will also output a picture if one is ready for output.
182  bool FinishPicture();
183
184  // Clear DPB contents and remove all surfaces in DPB from *in_use_ list.
185  // Cleared pictures will be made available for decode, unless they are
186  // at client waiting to be displayed.
187  void ClearDPB();
188
189  // These queue up data for HW decoder to be committed on running HW decode.
190  bool SendPPS();
191  bool SendIQMatrix();
192  bool SendVASliceParam(media::H264SliceHeader* slice_hdr);
193  bool SendSliceData(const uint8* ptr, size_t size);
194  bool QueueSlice(media::H264SliceHeader* slice_hdr);
195
196  // Helper methods for filling HW structures.
197  void FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic);
198  int FillVARefFramesFromDPB(VAPictureH264 *va_pics, int num_pics);
199
200  // Commits all pending data for HW decoder and starts HW decoder.
201  bool DecodePicture();
202
203  // Notifies client that a picture is ready for output.
204  bool OutputPic(H264Picture* pic);
205
206  // Output all pictures in DPB that have not been outputted yet.
207  bool OutputAllRemainingPics();
208
209  // Represents a frame being decoded. Will always have a VASurface
210  // assigned to it, which will eventually contain decoded picture data.
211  class DecodeSurface;
212
213  // Assign an available surface to the given PicOrderCnt |poc|,
214  // removing it from the available surfaces pool. Return true if a surface
215  // has been found, false otherwise.
216  bool AssignSurfaceToPoC(int32 input_id, int poc);
217
218  // Indicate that a surface is no longer needed by decoder.
219  void UnassignSurfaceFromPoC(int poc);
220
221  // Return DecodeSurface assigned to |poc|.
222  DecodeSurface* DecodeSurfaceByPoC(int poc);
223
224  // Decoder state.
225  State state_;
226
227  // Parser in use.
228  media::H264Parser parser_;
229
230  // DPB in use.
231  H264DPB dpb_;
232
233  // Picture currently being processed/decoded.
234  scoped_ptr<H264Picture> curr_pic_;
235
236  // Reference picture lists, constructed for each picture before decoding.
237  // Those lists are not owners of the pointers (DPB is).
238  H264Picture::PtrVector ref_pic_list0_;
239  H264Picture::PtrVector ref_pic_list1_;
240
241  // Global state values, needed in decoding. See spec.
242  int max_pic_order_cnt_lsb_;
243  int max_frame_num_;
244  int max_pic_num_;
245  int max_long_term_frame_idx_;
246  size_t max_num_reorder_frames_;
247
248  int frame_num_;
249  int prev_frame_num_;
250  int prev_frame_num_offset_;
251  bool prev_has_memmgmnt5_;
252
253  // Values related to previously decoded reference picture.
254  bool prev_ref_has_memmgmnt5_;
255  int prev_ref_top_field_order_cnt_;
256  int prev_ref_pic_order_cnt_msb_;
257  int prev_ref_pic_order_cnt_lsb_;
258  H264Picture::Field prev_ref_field_;
259
260  // Currently active SPS and PPS.
261  int curr_sps_id_;
262  int curr_pps_id_;
263
264  // Output picture size.
265  gfx::Size pic_size_;
266
267  // Maps H.264 PicOrderCount to currently used DecodeSurfaces;
268  typedef std::map<int, linked_ptr<DecodeSurface> > DecSurfacesInUse;
269  DecSurfacesInUse decode_surfaces_in_use_;
270
271  // Unused VA surfaces returned by client, ready to be reused.
272  std::vector<scoped_refptr<VASurface> > available_va_surfaces_;
273
274  // The id of current input buffer, which will be associated with an
275  // output surface when a frame is successfully decoded.
276  int32 curr_input_id_;
277
278  VaapiWrapper* vaapi_wrapper_;
279
280  // Called by decoder when a surface should be outputted.
281  OutputPicCB output_pic_cb_;
282
283  // Called to report decoding error to UMA, not used to indicate errors
284  // to clients.
285  ReportErrorToUmaCB report_error_to_uma_cb_;
286
287  // PicOrderCount of the previously outputted frame.
288  int last_output_poc_;
289
290  DISALLOW_COPY_AND_ASSIGN(VaapiH264Decoder);
291};
292
293}  // namespace content
294
295#endif  // CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_
296