Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: content/common/gpu/media/vaapi_h264_decoder.h

Issue 9814001: Add VAVDA, the VAAPI Video Decode Accelerator for Intel CPUs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix for occasional decode freeze on output falling behind for more demanding streams. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include <queue>
14
15 #include <GL/glx.h>
16
17 #include "base/callback_forward.h"
18 #include "base/lazy_instance.h"
19 #include "base/memory/linked_ptr.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "content/common/gpu/media/h264_dpb.h"
22 #include "content/common/gpu/media/h264_parser.h"
23 #include "media/base/video_decoder_config.h"
24 #include "third_party/libva/va/va.h"
25
26 namespace content {
Ami GONE FROM CHROMIUM 2012/04/09 02:41:47 This means you can drop content:: from everywhere
Pawel Osciak 2012/05/03 16:22:07 Done.
27
28 // An H264 decoder for use for VA-API-specific decoding. Provides features not
29 // supported by libva, including stream parsing, reference picture management
30 // and other operations not supported by the HW codec.
31 //
32 // Provides functionality to allow plugging VAAPI HW acceleration into the
33 // VDA framework.
34 //
35 // Clients of this class are expected to pass H264 Annex-B byte stream and
36 // will receive decoded pictures via client-provided |PictureReadyCallback|.
37 //
38 // If used in multi-threaded environment, some of the functions have to be
39 // called on the display thread (i.e. the thread that has the GLX context
Ami GONE FROM CHROMIUM 2012/04/09 02:41:47 Per my comments on the previous PS, I'd refer to t
Pawel Osciak 2012/05/03 16:22:07 Can't emphasize enough how awkward that is for me,
40 // passed to Initialize() set as current). This is essential so that the GLX
41 // calls can work properly. That thread is further referred to as "GLX thread".
42 // Decoder thread does not require GLX context and should be the same
43 // as the one on which Decode*() functions are called.
44 class VaapiH264Decoder {
45 public:
46 // Callback invoked on the client when a picture is to be displayed.
47 // Callee has to call PutPicToTexture() for the given picture before
48 // displaying it, to ensure the contents have been synced properly.
49 // Arguments: input buffer id, output buffer id (both provided by the client
50 // at the time of Decode() and AssignPictureBuffer() calls).
51 typedef base::Callback<void(int32, int32)> OutputPicCallback;
Ami GONE FROM CHROMIUM 2012/04/09 02:41:47 nit: FWIW new-style callbacks (which this is) are
Pawel Osciak 2012/05/03 16:22:07 Done.
52
53 // Decode result codes.
54 enum DecResult {
Ami GONE FROM CHROMIUM 2012/04/09 02:41:47 s/DecResult/DecodeResult/ but isn't this really De
Pawel Osciak 2012/05/03 16:22:07 No, it's the result. The enum for State is further
55 kDecodeError, // Error while decoding.
56 // TODO posciak: unsupported streams are currently treated as error
57 // in decoding; in future it could perhaps be possible to fall back
58 // to software decoding instead.
59 // kStreamError, // Error in stream.
60 kReadyToDecode, // Successfully initialized.
61 kDecodedFrame, // Successfully decoded a frame.
62 kNeedMoreStreamData, // Need more stream data to decode the next frame.
63 kNoOutputAvailable, // Waiting for the client to free up output surfaces.
64 };
65
66 VaapiH264Decoder();
67 // Should be called on the GLX thread, for the surface cleanup to work
68 // properly.
69 ~VaapiH264Decoder();
70
71 // Initializes and sets up libva connection and GL/X11 resources.
72 // Must be called on the GLX thread with |glx_context| being current and
73 // with decoder thread not yet running.
74 // |output_pic_callback| will be called to notify when a picture can be
75 // displayed.
76 bool Initialize(media::VideoCodecProfile profile,
77 Display* x_display,
78 GLXContext glx_context,
79 const OutputPicCallback& output_pic_callback);
80 void Destroy();
81
82 // Notify the decoder that this output buffer has been consumed and
83 // can be reused (overwritten).
84 // Must be run on the decoder thread.
85 void ReusePictureBuffer(int32 picture_buffer_id);
86
87 // Give a new picture buffer (texture) to decoder for use.
88 // Must be run on the GLX thread with decoder thread not yet running.
89 bool AssignPictureBuffer(int32 picture_buffer_id, uint32 texture_id);
90
91 // Sync the data so that the texture for given |picture_buffer_id| can
92 // be displayed.
93 // Must be run on the GLX thread.
94 bool PutPicToTexture(int32 picture_buffer_id);
95
96 // Have the decoder flush its state and trigger output of all previously
97 // decoded pictures via OutputPicCallback.
98 // Returns false if any of the resulting invocations of the callback fail.
Ami GONE FROM CHROMIUM 2012/04/09 02:41:47 I suspect this is in the realm of DCHECK (i.e. pro
Pawel Osciak 2012/05/03 16:22:07 There are two callers: 1. VAVDA on Flush request f
Ami GONE FROM CHROMIUM 2012/05/03 23:22:53 Of course the VDA interface *does* care; the fact
Pawel Osciak 2012/05/06 17:49:19 Right. Although in this case, ignoring it does not
99 bool Flush();
100
101 // Called while decoding.
102 // Stop decoding, discarding all remaining input/output, but do not flush
103 // state, so the playback of the same stream can be resumed (possibly from
104 // another location).
105 void Reset();
106
107 // Set current stream data pointer to |ptr| and |size|.
108 // Must be run on decoder thread.
109 void SetStream(uint8* ptr, size_t size);
110
111 // Start parsing stream to detect picture sizes. Does not produce any
112 // decoded pictures and can be called without providing output textures.
113 // Also to be used after Reset() to find a suitable location in the
114 // stream to resume playback from.
115 DecResult DecodeInitial(int32 input_id);
116
117 // Runs until a frame is decoded or end of provided stream data buffer
118 // is reached. Decoded pictures will be returned asynchronously via
119 // OutputPicCallback.
120 DecResult DecodeOneFrame(int32 input_id);
121
122 // Return dimensions for output buffer (texture) allocation.
123 // Valid only after a successful DecodeInitial().
124 int pic_height() { return pic_height_; }
125 int pic_width() { return pic_width_; }
126
127 // Return the number of output pictures required for decoding.
128 // Valid after a successful DecodeInitial().
129 static size_t GetRequiredNumOfPictures();
Ami GONE FROM CHROMIUM 2012/04/09 02:41:47 Why size_t (an unsigned type)? In practice we're t
Pawel Osciak 2012/05/03 16:22:07 Mostly because I'm comparing the return value agai
130
131 private:
132 // We need to keep at least kDPBMaxSize pictures in DPB for
133 // reference/to display later and an additional one for the one currently
134 // being decoded. We also ask for some additional ones since VDA needs
135 // to accumulate a few ready-to-output pictures before it actually starts
136 // displaying and giving them back.
137 enum { kNumReqPictures = H264DPB::kDPBMaxSize + 6 };
Ami GONE FROM CHROMIUM 2012/04/09 02:41:47 Please replace the "6" with the explicit math. I b
Pawel Osciak 2012/05/03 16:22:07 It'll have to be kMVF + 1, as one is also "in flig
138
139 // Internal state of the decoder.
140 enum State {
141 kUninitialized, // Initialize() not yet called.
142 kInitialized, // Initialize() called, pictures requested.
143 kDecoding, // DecodeInitial() successful, output surfaces allocated.
144 kAfterReset, // After Reset() during decoding.
145 kError, // Error in kDecoding state.
146 };
147
148 // Get usable framebuffer configuration for use in binding textures
149 // or return false on failure.
150 bool InitializeFBConfig();
151
152 // Process H264 stream structures.
153 bool ProcessSPS(int sps_id);
154 bool ProcessPPS(int pps_id);
155 bool ProcessSlice(content::H264SliceHeader* slice_hdr);
156
157 // Initialize the current picture according to data in |slice_hdr|.
158 bool InitCurrPicture(content::H264SliceHeader* slice_hdr);
159
160 // Calculate picture order counts for the new picture
161 // on initialization of a new frame (see spec).
162 bool CalculatePicOrderCounts(content::H264SliceHeader* slice_hdr);
163
164 // Update PicNum values in pictures stored in DPB on creation of new
165 // frame (see spec).
166 void UpdatePicNums();
167
168 // Construct initial reference picture lists for use in decoding of
169 // P and B pictures (see 8.2.4 in spec).
170 void ConstructReferencePicListsP(content::H264SliceHeader* slice_hdr);
171 void ConstructReferencePicListsB(content::H264SliceHeader* slice_hdr);
172
173 // Helper functions for reference list construction, per spec.
174 int PicNumF(H264Picture *pic);
175 int LongTermPicNumF(H264Picture *pic);
176
177 // Perform the reference picture lists' modification (reordering), as
178 // specified in spec (8.2.4).
179 //
180 // |list| indicates list number and should be either 0 or 1.
181 bool ModifyReferencePicList(content::H264SliceHeader *slice_hdr, int list);
182
183 // Perform reference picture memory management operations (marking/unmarking
184 // of reference pictures, long term picture management, discarding, etc.).
185 // See 8.2.5 in spec.
186 bool HandleMemoryManagementOps();
187 void ReferencePictureMarking();
188
189 // Start processing a new frame.
190 bool StartNewFrame(content::H264SliceHeader* slice_hdr);
191
192 // All data for a frame received, process it and decode.
193 bool FinishPrevFrameIfPresent();
194
195 // Called after decoding, performs all operations to be done after decoding,
196 // including DPB management, reference picture marking and memory management
197 // operations.
198 // This will also output a picture if one is ready for output.
199 bool FinishPicture();
200
201 // Convert VideoCodecProfile to VAProfile and set it as active.
202 bool SetProfile(media::VideoCodecProfile profile);
203
204 // Vaapi-related functions.
205
206 // Allocates VASurfaces and creates a VAContext for them.
207 bool CreateVASurfaces();
208
209 // Destroys allocated VASurfaces and related VAContext.
210 void DestroyVASurfaces();
211
212 // These queue up data for HW decoder to be committed on running HW decode.
213 bool SendPPS();
214 bool SendIQMatrix();
215 bool SendVASliceParam(content::H264SliceHeader* slice_hdr);
216 bool SendSliceData(const uint8* ptr, size_t size);
217 bool QueueSlice(content::H264SliceHeader* slice_hdr);
218
219 // Helper methods for filling HW structures.
220 void FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic);
221 int FillVARefFramesFromDPB(VAPictureH264 *va_pics, int num_pics);
222
223 // Commits all pending data for HW decoder and starts HW decoder.
224 bool DecodePicture();
225
226 // Notifies client that a picture is ready for output.
227 bool OutputPic(H264Picture* pic);
228
229 State state_;
230
231 // A frame has been sent to hardware as the result of the last
232 // DecodeOneFrame() call.
233 bool frame_ready_at_hw_;
234
235 // Parser in use.
236 content::H264Parser parser_;
237
238 // DPB in use.
239 H264DPB dpb_;
240
241 // Picture currently being processed/decoded.
242 scoped_ptr<H264Picture> curr_pic_;
243
244 // Reference picture lists, constructed for each picture before decoding.
245 // Those lists are not owners of the pointers (DPB is).
246 H264Picture::PtrVector ref_pic_list0_;
247 H264Picture::PtrVector ref_pic_list1_;
248
249 // Global state values, needed in decoding. See spec.
250 int max_pic_order_cnt_lsb_;
251 int max_frame_num_;
252 int max_pic_num_;
253 int max_long_term_frame_idx_;
254
255 int frame_num_;
256 int prev_frame_num_;
257 int prev_frame_num_offset_;
258
259 // Values related to previously decoded reference picture.
260 bool prev_ref_has_memmgmnt5_;
261 int prev_ref_top_field_order_cnt_;
262 int prev_ref_pic_order_cnt_msb_;
263 int prev_ref_pic_order_cnt_lsb_;
264 H264Picture::Field prev_ref_field_;
265
266 // Currently active SPS and PPS.
267 int curr_sps_id_;
268 int curr_pps_id_;
269
270 // Output picture size.
271 int pic_width_;
272 int pic_height_;
273
274 // Data queued up for HW decoder, to be commited on next HW decode.
275 std::queue<VABufferID> pending_slice_bufs_;
276 std::queue<VABufferID> pending_va_bufs_;
277
278 // Manages binding of a client-provided output buffer (texture) to VASurface.
279 class DecodeSurface;
280
281 // Maps output_buffer_id to a decode surface. Used to look up surfaces
282 // on requests from the client.
283 typedef std::map<int32, linked_ptr<DecodeSurface> > DecodeSurfaces;
284 DecodeSurfaces decode_surfaces_;
285
286 // Number of decode surface currently available for decoding.
287 int num_available_decode_surfaces_;
288
289 // Maps decode surfaces to PicOrderCount, used to look up output buffers
290 // when a decision to output a picture has been made.
291 typedef std::map<int, DecodeSurface*> POCToDecodeSurfaces;
292 POCToDecodeSurfaces poc_to_decode_surfaces_;
293
294 // Find an available surface and assign it to given PicOrderCnt |poc|,
295 // removing it from the available surfaces pool. Return true if a surface
296 // has been found, false otherwise.
297 bool AssignSurfaceToPoC(int poc);
298
299 // Unassign a surface from |poc| and return a pointer to it, or NULL if there
300 // is no surface associated with given |poc|. Note that this does not make
301 // the surface available for reuse - as this can only happen after client
302 // returns the surface via ReusePictureBuffer() - but only removes its
303 // association with given |poc|.
304 DecodeSurface* UnassignSurfaceFromPoC(int poc);
305
306 // The id of current input buffer, which will be associated with an
307 // output picture if a frame is decoded successfully.
308 int32 curr_input_id_;
309
310 // X/GLX handles.
311 Display* x_display_;
312 GLXContext parent_glx_context_;
313 GLXFBConfig fb_config_;
314
315 // VA handles.
316 VADisplay va_display_;
317 VAConfigID va_config_id_;
318 VAContextID va_context_id_;
319 VAProfile profile_;
320
321 // Allocated VASurfaces.
322 VASurfaceID va_surface_ids_[kNumReqPictures];
323
324 // Called by decoder when a picture should be outputted.
325 OutputPicCallback output_pic_callback_;
326
327 DISALLOW_COPY_AND_ASSIGN(VaapiH264Decoder);
328 };
329
330 } // namespace content
331
332 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_H264_DECODER_H_
333
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698