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.
5 // This file contains an implementation of VideoDecoderAccelerator
6 // that utilizes hardware video decoder present on Intel CPUs.
8 #ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
9 #define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_
17 #include "base/logging.h"
18 #include "base/memory/linked_ptr.h"
19 #include "base/memory/shared_memory.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/synchronization/condition_variable.h"
23 #include "base/synchronization/lock.h"
24 #include "base/threading/thread.h"
25 #include "content/common/content_export.h"
26 #include "content/common/gpu/media/vaapi_wrapper.h"
27 #include "media/base/bitstream_buffer.h"
28 #include "media/video/picture.h"
29 #include "media/video/video_decode_accelerator.h"
37 class AcceleratedVideoDecoder
;
40 // Class to provide video decode acceleration for Intel systems with hardware
41 // support for it, and on which libva is available.
42 // Decoding tasks are performed in a separate decoding thread.
44 // Threading/life-cycle: this object is created & destroyed on the GPU
45 // ChildThread. A few methods on it are called on the decoder thread which is
46 // stopped during |this->Destroy()|, so any tasks posted to the decoder thread
47 // can assume |*this| is still alive. See |weak_this_| below for more details.
48 class CONTENT_EXPORT VaapiVideoDecodeAccelerator
49 : public media::VideoDecodeAccelerator
{
51 class VaapiDecodeSurface
;
53 VaapiVideoDecodeAccelerator(
54 const base::Callback
<bool(void)>& make_context_current
,
55 const base::Callback
<void(uint32
, uint32
, scoped_refptr
<gfx::GLImage
>)>&
57 ~VaapiVideoDecodeAccelerator() override
;
59 // media::VideoDecodeAccelerator implementation.
60 bool Initialize(media::VideoCodecProfile profile
, Client
* client
) override
;
61 void Decode(const media::BitstreamBuffer
& bitstream_buffer
) override
;
62 void AssignPictureBuffers(
63 const std::vector
<media::PictureBuffer
>& buffers
) override
;
64 void ReusePictureBuffer(int32 picture_buffer_id
) override
;
65 void Flush() override
;
66 void Reset() override
;
67 void Destroy() override
;
68 bool CanDecodeOnIOThread() override
;
70 static media::VideoDecodeAccelerator::SupportedProfiles
71 GetSupportedProfiles();
74 class VaapiH264Accelerator
;
75 class VaapiVP8Accelerator
;
76 class VaapiVP9Accelerator
;
78 // Notify the client that an error has occurred and decoding cannot continue.
79 void NotifyError(Error error
);
81 // Map the received input buffer into this process' address space and
82 // queue it for decode.
83 void MapAndQueueNewInputBuffer(
84 const media::BitstreamBuffer
& bitstream_buffer
);
86 // Get a new input buffer from the queue and set it up in decoder. This will
87 // sleep if no input buffers are available. Return true if a new buffer has
88 // been set up, false if an early exit has been requested (due to initiated
89 // reset/flush/destroy).
90 bool GetInputBuffer_Locked();
92 // Signal the client that the current buffer has been read and can be
93 // returned. Will also release the mapping.
94 void ReturnCurrInputBuffer_Locked();
96 // Wait for more surfaces to become available. Return true once they do or
97 // false if an early exit has been requested (due to an initiated
98 // reset/flush/destroy).
99 bool WaitForSurfaces_Locked();
101 // Continue decoding given input buffers and sleep waiting for input/output
102 // as needed. Will exit if a new set of surfaces or reset/flush/destroy
106 // Scheduled after receiving a flush request and executed after the current
107 // decoding task finishes decoding pending inputs. Makes the decoder return
108 // all remaining output pictures and puts it in an idle state, ready
109 // to resume if needed and schedules a FinishFlush.
112 // Scheduled by the FlushTask after decoder is flushed to put VAVDA into idle
113 // state and notify the client that flushing has been finished.
116 // Scheduled after receiving a reset request and executed after the current
117 // decoding task finishes decoding the current frame. Puts the decoder into
118 // an idle state, ready to resume if needed, discarding decoded but not yet
119 // outputted pictures (decoder keeps ownership of their associated picture
120 // buffers). Schedules a FinishReset afterwards.
123 // Scheduled by ResetTask after it's done putting VAVDA into an idle state.
124 // Drops remaining input buffers and notifies the client that reset has been
128 // Helper for Destroy(), doing all the actual work except for deleting self.
131 // Get a usable framebuffer configuration for use in binding textures
132 // or return false on failure.
133 bool InitializeFBConfig();
135 // Callback to be executed once we have a |va_surface| to be output and
136 // an available |picture| to use for output.
137 // Puts contents of |va_surface| into given |picture|, releases the
138 // surface and passes the resulting picture to client for output.
139 void OutputPicture(const scoped_refptr
<VASurface
>& va_surface
,
141 VaapiPicture
* picture
);
143 // Try to OutputPicture() if we have both a ready surface and picture.
144 void TryOutputSurface();
146 // Called when a VASurface is no longer in use by the decoder or is not being
147 // synced/waiting to be synced to a picture. Returns it to available surfaces
149 void RecycleVASurfaceID(VASurfaceID va_surface_id
);
151 // Initiate wait cycle for surfaces to be released before we release them
152 // and allocate new ones, as requested by the decoder.
153 void InitiateSurfaceSetChange(size_t num_pics
, gfx::Size size
);
155 // Check if the surfaces have been released or post ourselves for later.
156 void TryFinishSurfaceSetChange();
159 // Below methods are used by accelerator implementations.
161 // Decode of |dec_surface| is ready to be submitted and all codec-specific
162 // settings are set in hardware.
163 bool DecodeSurface(const scoped_refptr
<VaapiDecodeSurface
>& dec_surface
);
165 // |dec_surface| is ready to be outputted once decode is finished.
166 // This can be called before decode is actually done in hardware, and this
167 // method is responsible for maintaining the ordering, i.e. the surfaces have
168 // to be outputted in the same order as SurfaceReady is called.
169 // On Intel, we don't have to explicitly maintain the ordering however, as the
170 // driver will maintain ordering, as well as dependencies, and will process
171 // each submitted command in order, and run each command only if its
172 // dependencies are ready.
173 void SurfaceReady(const scoped_refptr
<VaapiDecodeSurface
>& dec_surface
);
175 // Return a new VaapiDecodeSurface for decoding into, or nullptr if not
177 scoped_refptr
<VaapiDecodeSurface
> CreateSurface();
180 // Client-provided GL state.
181 base::Callback
<bool(void)> make_context_current_
;
185 // Initialize() not called yet or failed.
187 // DecodeTask running.
189 // Resetting, waiting for decoder to finish current task and cleanup.
191 // Flushing, waiting for decoder to finish current task and cleanup.
193 // Idle, decoder in state ready to start/resume decoding.
195 // Destroying, waiting for the decoder to finish current task.
199 // Protects input buffer and surface queues and state_.
203 // An input buffer awaiting consumption, provided by the client.
210 scoped_ptr
<base::SharedMemory
> shm
;
213 // Queue for incoming input buffers.
214 typedef std::queue
<linked_ptr
<InputBuffer
> > InputBuffers
;
215 InputBuffers input_buffers_
;
216 // Signalled when input buffers are queued onto the input_buffers_ queue.
217 base::ConditionVariable input_ready_
;
219 // Current input buffer at decoder.
220 linked_ptr
<InputBuffer
> curr_input_buffer_
;
222 // Queue for incoming output buffers (texture ids).
223 typedef std::queue
<int32
> OutputBuffers
;
224 OutputBuffers output_buffers_
;
226 scoped_ptr
<VaapiWrapper
> vaapi_wrapper_
;
228 typedef std::map
<int32
, linked_ptr
<VaapiPicture
>> Pictures
;
229 // All allocated Pictures, regardless of their current state.
230 // Pictures are allocated once and destroyed at the end of decode.
231 // Comes after vaapi_wrapper_ to ensure all pictures are destroyed
232 // before vaapi_wrapper_ is destroyed.
235 // Return a VaapiPicture associated with given client-provided id.
236 VaapiPicture
* PictureById(int32 picture_buffer_id
);
238 // VA Surfaces no longer in use that can be passed back to the decoder for
239 // reuse, once it requests them.
240 std::list
<VASurfaceID
> available_va_surfaces_
;
241 // Signalled when output surfaces are queued onto the available_va_surfaces_
243 base::ConditionVariable surfaces_available_
;
245 // Pending output requests from the decoder. When it indicates that we should
246 // output a surface and we have an available Picture (i.e. texture) ready
247 // to use, we'll execute the callback passing the Picture. The callback
248 // will put the contents of the surface into the picture and return it to
249 // the client, releasing the surface as well.
250 // If we don't have any available Pictures at the time when the decoder
251 // requests output, we'll store the request on pending_output_cbs_ queue for
252 // later and run it once the client gives us more textures
253 // via ReusePictureBuffer().
254 typedef base::Callback
<void(VaapiPicture
*)> OutputCB
;
255 std::queue
<OutputCB
> pending_output_cbs_
;
257 // ChildThread's message loop
258 base::MessageLoop
* message_loop_
;
260 // WeakPtr<> pointing to |this| for use in posting tasks from the decoder
261 // thread back to the ChildThread. Because the decoder thread is a member of
262 // this class, any task running on the decoder thread is guaranteed that this
263 // object is still alive. As a result, tasks posted from ChildThread to
264 // decoder thread should use base::Unretained(this), and tasks posted from the
265 // decoder thread to the ChildThread should use |weak_this_|.
266 base::WeakPtr
<VaapiVideoDecodeAccelerator
> weak_this_
;
268 // Callback used when creating VASurface objects.
269 VASurface::ReleaseCB va_surface_release_cb_
;
271 // To expose client callbacks from VideoDecodeAccelerator.
272 // NOTE: all calls to these objects *MUST* be executed on message_loop_.
273 scoped_ptr
<base::WeakPtrFactory
<Client
> > client_ptr_factory_
;
274 base::WeakPtr
<Client
> client_
;
276 // Accelerators come after vaapi_wrapper_ to ensure they are destroyed first.
277 scoped_ptr
<VaapiH264Accelerator
> h264_accelerator_
;
278 scoped_ptr
<VaapiVP8Accelerator
> vp8_accelerator_
;
279 scoped_ptr
<VaapiVP9Accelerator
> vp9_accelerator_
;
280 // After *_accelerator_ to ensure correct destruction order.
281 scoped_ptr
<AcceleratedVideoDecoder
> decoder_
;
283 base::Thread decoder_thread_
;
284 // Use this to post tasks to |decoder_thread_| instead of
285 // |decoder_thread_.message_loop()| because the latter will be NULL once
286 // |decoder_thread_.Stop()| returns.
287 scoped_refptr
<base::SingleThreadTaskRunner
> decoder_thread_task_runner_
;
289 int num_frames_at_client_
;
290 int num_stream_bufs_at_decoder_
;
292 // Whether we are waiting for any pending_output_cbs_ to be run before
293 // NotifyingFlushDone.
294 bool finish_flush_pending_
;
296 // Decoder requested a new surface set and we are waiting for all the surfaces
297 // to be returned before we can free them.
298 bool awaiting_va_surfaces_recycle_
;
300 // Last requested number/resolution of output picture buffers.
301 size_t requested_num_pics_
;
302 gfx::Size requested_pic_size_
;
304 // Binds the provided GLImage to a givenr client texture ID & texture target
305 // combination in GLES.
306 base::Callback
<void(uint32
, uint32
, scoped_refptr
<gfx::GLImage
>)> bind_image_
;
308 // The WeakPtrFactory for |weak_this_|.
309 base::WeakPtrFactory
<VaapiVideoDecodeAccelerator
> weak_this_factory_
;
311 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator
);
314 } // namespace content
316 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_