OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // This file contains an implementation of VideoDecoderAccelerator | 5 // This file contains an implementation of VideoDecoderAccelerator |
6 // that utilizes hardware video decoder present on Intel CPUs. | 6 // that utilizes hardware video decoder present on Intel CPUs. |
7 | 7 |
8 #ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ | 8 #ifndef CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ |
9 #define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ | 9 #define CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ |
10 | 10 |
11 #include <list> | |
11 #include <map> | 12 #include <map> |
12 #include <queue> | 13 #include <queue> |
13 #include <utility> | 14 #include <utility> |
14 #include <vector> | 15 #include <vector> |
15 | 16 |
16 #include "base/logging.h" | 17 #include "base/logging.h" |
17 #include "base/memory/linked_ptr.h" | 18 #include "base/memory/linked_ptr.h" |
18 #include "base/memory/shared_memory.h" | 19 #include "base/memory/shared_memory.h" |
19 #include "base/memory/weak_ptr.h" | 20 #include "base/memory/weak_ptr.h" |
20 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
21 #include "base/synchronization/condition_variable.h" | 22 #include "base/synchronization/condition_variable.h" |
22 #include "base/synchronization/lock.h" | 23 #include "base/synchronization/lock.h" |
23 #include "base/threading/thread.h" | 24 #include "base/threading/thread.h" |
24 #include "content/common/content_export.h" | 25 #include "content/common/content_export.h" |
25 #include "content/common/gpu/media/vaapi_h264_decoder.h" | |
26 #include "content/common/gpu/media/vaapi_wrapper.h" | 26 #include "content/common/gpu/media/vaapi_wrapper.h" |
27 #include "media/base/bitstream_buffer.h" | 27 #include "media/base/bitstream_buffer.h" |
28 #include "media/video/picture.h" | 28 #include "media/video/picture.h" |
29 #include "media/video/video_decode_accelerator.h" | 29 #include "media/video/video_decode_accelerator.h" |
30 | 30 |
31 namespace gfx { | 31 namespace gfx { |
32 class GLImage; | 32 class GLImage; |
33 } | 33 } |
34 | 34 |
35 namespace content { | 35 namespace content { |
36 | 36 |
37 class AcceleratedVideoDecoder; | |
37 class VaapiPicture; | 38 class VaapiPicture; |
38 | 39 |
39 // Class to provide video decode acceleration for Intel systems with hardware | 40 // Class to provide video decode acceleration for Intel systems with hardware |
40 // support for it, and on which libva is available. | 41 // support for it, and on which libva is available. |
41 // Decoding tasks are performed in a separate decoding thread. | 42 // Decoding tasks are performed in a separate decoding thread. |
42 // | 43 // |
43 // Threading/life-cycle: this object is created & destroyed on the GPU | 44 // Threading/life-cycle: this object is created & destroyed on the GPU |
44 // ChildThread. A few methods on it are called on the decoder thread which is | 45 // ChildThread. A few methods on it are called on the decoder thread which is |
45 // stopped during |this->Destroy()|, so any tasks posted to the decoder thread | 46 // stopped during |this->Destroy()|, so any tasks posted to the decoder thread |
46 // can assume |*this| is still alive. See |weak_this_| below for more details. | 47 // can assume |*this| is still alive. See |weak_this_| below for more details. |
47 class CONTENT_EXPORT VaapiVideoDecodeAccelerator | 48 class CONTENT_EXPORT VaapiVideoDecodeAccelerator |
48 : public media::VideoDecodeAccelerator { | 49 : public media::VideoDecodeAccelerator { |
49 public: | 50 public: |
51 class VaapiDecodeSurface; | |
52 | |
50 VaapiVideoDecodeAccelerator( | 53 VaapiVideoDecodeAccelerator( |
51 const base::Callback<bool(void)>& make_context_current, | 54 const base::Callback<bool(void)>& make_context_current, |
52 const base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)>& | 55 const base::Callback<void(uint32, uint32, scoped_refptr<gfx::GLImage>)>& |
53 bind_image); | 56 bind_image); |
54 ~VaapiVideoDecodeAccelerator() override; | 57 ~VaapiVideoDecodeAccelerator() override; |
55 | 58 |
56 // media::VideoDecodeAccelerator implementation. | 59 // media::VideoDecodeAccelerator implementation. |
57 bool Initialize(media::VideoCodecProfile profile, | 60 bool Initialize(media::VideoCodecProfile profile, Client* client) override; |
58 Client* client) override; | |
59 void Decode(const media::BitstreamBuffer& bitstream_buffer) override; | 61 void Decode(const media::BitstreamBuffer& bitstream_buffer) override; |
60 void AssignPictureBuffers( | 62 void AssignPictureBuffers( |
61 const std::vector<media::PictureBuffer>& buffers) override; | 63 const std::vector<media::PictureBuffer>& buffers) override; |
62 void ReusePictureBuffer(int32 picture_buffer_id) override; | 64 void ReusePictureBuffer(int32 picture_buffer_id) override; |
63 void Flush() override; | 65 void Flush() override; |
64 void Reset() override; | 66 void Reset() override; |
65 void Destroy() override; | 67 void Destroy() override; |
66 bool CanDecodeOnIOThread() override; | 68 bool CanDecodeOnIOThread() override; |
67 | 69 |
68 private: | 70 private: |
71 class VaapiH264Accelerator; | |
72 | |
69 // Notify the client that an error has occurred and decoding cannot continue. | 73 // Notify the client that an error has occurred and decoding cannot continue. |
70 void NotifyError(Error error); | 74 void NotifyError(Error error); |
71 | 75 |
72 // Map the received input buffer into this process' address space and | 76 // Map the received input buffer into this process' address space and |
73 // queue it for decode. | 77 // queue it for decode. |
74 void MapAndQueueNewInputBuffer( | 78 void MapAndQueueNewInputBuffer( |
75 const media::BitstreamBuffer& bitstream_buffer); | 79 const media::BitstreamBuffer& bitstream_buffer); |
76 | 80 |
77 // Get a new input buffer from the queue and set it up in decoder. This will | 81 // Get a new input buffer from the queue and set it up in decoder. This will |
78 // sleep if no input buffers are available. Return true if a new buffer has | 82 // sleep if no input buffers are available. Return true if a new buffer has |
79 // been set up, false if an early exit has been requested (due to initiated | 83 // been set up, false if an early exit has been requested (due to initiated |
80 // reset/flush/destroy). | 84 // reset/flush/destroy). |
81 bool GetInputBuffer_Locked(); | 85 bool GetInputBuffer_Locked(); |
82 | 86 |
83 // Signal the client that the current buffer has been read and can be | 87 // Signal the client that the current buffer has been read and can be |
84 // returned. Will also release the mapping. | 88 // returned. Will also release the mapping. |
85 void ReturnCurrInputBuffer_Locked(); | 89 void ReturnCurrInputBuffer_Locked(); |
86 | 90 |
87 // Pass one or more output buffers to the decoder. This will sleep | 91 // Wait for more surfaces to become available. Return true once they do or |
88 // if no buffers are available. Return true if buffers have been set up or | 92 // false if an early exit has been requested (due to an initiated |
89 // false if an early exit has been requested (due to initiated | |
90 // reset/flush/destroy). | 93 // reset/flush/destroy). |
91 bool FeedDecoderWithOutputSurfaces_Locked(); | 94 bool WaitForSurfaces_Locked(); |
92 | 95 |
93 // Continue decoding given input buffers and sleep waiting for input/output | 96 // Continue decoding given input buffers and sleep waiting for input/output |
94 // as needed. Will exit if a new set of surfaces or reset/flush/destroy | 97 // as needed. Will exit if a new set of surfaces or reset/flush/destroy |
95 // is requested. | 98 // is requested. |
96 void DecodeTask(); | 99 void DecodeTask(); |
97 | 100 |
98 // Scheduled after receiving a flush request and executed after the current | 101 // Scheduled after receiving a flush request and executed after the current |
99 // decoding task finishes decoding pending inputs. Makes the decoder return | 102 // decoding task finishes decoding pending inputs. Makes the decoder return |
100 // all remaining output pictures and puts it in an idle state, ready | 103 // all remaining output pictures and puts it in an idle state, ready |
101 // to resume if needed and schedules a FinishFlush. | 104 // to resume if needed and schedules a FinishFlush. |
(...skipping 15 matching lines...) Expand all Loading... | |
117 // finished. | 120 // finished. |
118 void FinishReset(); | 121 void FinishReset(); |
119 | 122 |
120 // Helper for Destroy(), doing all the actual work except for deleting self. | 123 // Helper for Destroy(), doing all the actual work except for deleting self. |
121 void Cleanup(); | 124 void Cleanup(); |
122 | 125 |
123 // Get a usable framebuffer configuration for use in binding textures | 126 // Get a usable framebuffer configuration for use in binding textures |
124 // or return false on failure. | 127 // or return false on failure. |
125 bool InitializeFBConfig(); | 128 bool InitializeFBConfig(); |
126 | 129 |
127 // Callback for the decoder to execute when it wants us to output given | |
128 // |va_surface|. | |
129 void SurfaceReady(int32 input_id, const scoped_refptr<VASurface>& va_surface); | |
130 | |
131 // Callback to be executed once we have a |va_surface| to be output and | 130 // Callback to be executed once we have a |va_surface| to be output and |
132 // an available |picture| to use for output. | 131 // an available |picture| to use for output. |
133 // Puts contents of |va_surface| into given |picture|, releases the | 132 // Puts contents of |va_surface| into given |picture|, releases the |
134 // surface and passes the resulting picture to client for output. | 133 // surface and passes the resulting picture to client for output. |
135 void OutputPicture(const scoped_refptr<VASurface>& va_surface, | 134 void OutputPicture(const scoped_refptr<VASurface>& va_surface, |
136 int32 input_id, | 135 int32 input_id, |
137 VaapiPicture* picture); | 136 VaapiPicture* picture); |
138 | 137 |
139 // Try to OutputPicture() if we have both a ready surface and picture. | 138 // Try to OutputPicture() if we have both a ready surface and picture. |
140 void TryOutputSurface(); | 139 void TryOutputSurface(); |
141 | 140 |
142 // Called when a VASurface is no longer in use by the decoder or is not being | 141 // Called when a VASurface is no longer in use by the decoder or is not being |
143 // synced/waiting to be synced to a picture. Returns it to available surfaces | 142 // synced/waiting to be synced to a picture. Returns it to available surfaces |
144 // pool. | 143 // pool. |
145 void RecycleVASurfaceID(VASurfaceID va_surface_id); | 144 void RecycleVASurfaceID(VASurfaceID va_surface_id); |
146 | 145 |
147 // Initiate wait cycle for surfaces to be released before we release them | 146 // Initiate wait cycle for surfaces to be released before we release them |
148 // and allocate new ones, as requested by the decoder. | 147 // and allocate new ones, as requested by the decoder. |
149 void InitiateSurfaceSetChange(size_t num_pics, gfx::Size size); | 148 void InitiateSurfaceSetChange(size_t num_pics, gfx::Size size); |
149 | |
150 // Check if the surfaces have been released or post ourselves for later. | 150 // Check if the surfaces have been released or post ourselves for later. |
151 void TryFinishSurfaceSetChange(); | 151 void TryFinishSurfaceSetChange(); |
152 | 152 |
153 // | |
154 // Below methods are used by accelerator implementations. | |
155 // | |
156 // Decode of |dec_surface| is ready to be submitted and all codec-specific | |
157 // settings are set in hardware. | |
158 bool DecodeSurface(const scoped_refptr<VaapiDecodeSurface>& dec_surface); | |
159 | |
160 // |dec_surface| is ready to be outputted once decode is finished. | |
161 // This can be called before decode is actually done in hardware, and this | |
162 // method is responsible for maintaining the ordering, i.e. the surfaces have | |
163 // to be outputted in the same order as SurfaceReady is called. | |
164 // On Intel, we don't have to explicitly maintain the ordering however, as the | |
165 // driver will maintain ordering, as well as dependencies, and will process | |
166 // each submitted command in order, and run each command only if its | |
167 // dependencies are ready. | |
168 void SurfaceReady(const scoped_refptr<VaapiDecodeSurface>& dec_surface); | |
169 | |
170 // Return a new VaapiDecodeSurface for decoding into, or nullptr if not | |
171 // available. | |
172 scoped_refptr<VaapiDecodeSurface> CreateSurface(); | |
173 | |
174 | |
153 // Client-provided GL state. | 175 // Client-provided GL state. |
154 base::Callback<bool(void)> make_context_current_; | 176 base::Callback<bool(void)> make_context_current_; |
155 | 177 |
156 // VAVDA state. | 178 // VAVDA state. |
157 enum State { | 179 enum State { |
158 // Initialize() not called yet or failed. | 180 // Initialize() not called yet or failed. |
159 kUninitialized, | 181 kUninitialized, |
160 // DecodeTask running. | 182 // DecodeTask running. |
161 kDecoding, | 183 kDecoding, |
162 // Resetting, waiting for decoder to finish current task and cleanup. | 184 // Resetting, waiting for decoder to finish current task and cleanup. |
163 kResetting, | 185 kResetting, |
164 // Flushing, waiting for decoder to finish current task and cleanup. | 186 // Flushing, waiting for decoder to finish current task and cleanup. |
165 kFlushing, | 187 kFlushing, |
166 // Idle, decoder in state ready to start/resume decoding. | 188 // Idle, decoder in state ready to start/resume decoding. |
167 kIdle, | 189 kIdle, |
168 // Destroying, waiting for the decoder to finish current task. | 190 // Destroying, waiting for the decoder to finish current task. |
169 kDestroying, | 191 kDestroying, |
170 }; | 192 }; |
171 | 193 |
172 // Protects input buffer and surface queues and state_. | 194 // Protects input buffer and surface queues and state_. |
wuchengli
2015/04/07 09:36:47
Not related to this CL. What are all the variables
kcwu1
2015/04/07 09:42:47
I have the same concern.
Pawel Osciak
2015/04/08 08:36:03
Yes, looks like a dormant bug, but shouldn't have
| |
173 base::Lock lock_; | 195 base::Lock lock_; |
174 State state_; | 196 State state_; |
175 | 197 |
176 // An input buffer awaiting consumption, provided by the client. | 198 // An input buffer awaiting consumption, provided by the client. |
177 struct InputBuffer { | 199 struct InputBuffer { |
178 InputBuffer(); | 200 InputBuffer(); |
179 ~InputBuffer(); | 201 ~InputBuffer(); |
180 | 202 |
181 int32 id; | 203 int32 id; |
182 size_t size; | 204 size_t size; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 // Callback used when creating VASurface objects. | 263 // Callback used when creating VASurface objects. |
242 VASurface::ReleaseCB va_surface_release_cb_; | 264 VASurface::ReleaseCB va_surface_release_cb_; |
243 | 265 |
244 // To expose client callbacks from VideoDecodeAccelerator. | 266 // To expose client callbacks from VideoDecodeAccelerator. |
245 // NOTE: all calls to these objects *MUST* be executed on message_loop_. | 267 // NOTE: all calls to these objects *MUST* be executed on message_loop_. |
246 scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_; | 268 scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_; |
247 base::WeakPtr<Client> client_; | 269 base::WeakPtr<Client> client_; |
248 | 270 |
249 // Comes after vaapi_wrapper_ to ensure its destructor is executed before | 271 // Comes after vaapi_wrapper_ to ensure its destructor is executed before |
250 // vaapi_wrapper_ is destroyed. | 272 // vaapi_wrapper_ is destroyed. |
251 scoped_ptr<VaapiH264Decoder> decoder_; | 273 scoped_ptr<VaapiH264Accelerator> h264_accelerator_; |
274 // After h264_accelerator_ to ensure correct destruction order. | |
275 scoped_ptr<AcceleratedVideoDecoder> decoder_; | |
276 | |
252 base::Thread decoder_thread_; | 277 base::Thread decoder_thread_; |
253 // Use this to post tasks to |decoder_thread_| instead of | 278 // Use this to post tasks to |decoder_thread_| instead of |
254 // |decoder_thread_.message_loop()| because the latter will be NULL once | 279 // |decoder_thread_.message_loop()| because the latter will be NULL once |
255 // |decoder_thread_.Stop()| returns. | 280 // |decoder_thread_.Stop()| returns. |
256 scoped_refptr<base::MessageLoopProxy> decoder_thread_proxy_; | 281 scoped_refptr<base::MessageLoopProxy> decoder_thread_proxy_; |
257 | 282 |
258 int num_frames_at_client_; | 283 int num_frames_at_client_; |
259 int num_stream_bufs_at_decoder_; | 284 int num_stream_bufs_at_decoder_; |
260 | 285 |
261 // Whether we are waiting for any pending_output_cbs_ to be run before | 286 // Whether we are waiting for any pending_output_cbs_ to be run before |
(...skipping 14 matching lines...) Expand all Loading... | |
276 | 301 |
277 // The WeakPtrFactory for |weak_this_|. | 302 // The WeakPtrFactory for |weak_this_|. |
278 base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_; | 303 base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_; |
279 | 304 |
280 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); | 305 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); |
281 }; | 306 }; |
282 | 307 |
283 } // namespace content | 308 } // namespace content |
284 | 309 |
285 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ | 310 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ |
OLD | NEW |