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 static media::VideoDecodeAccelerator::SupportedProfiles | 70 static media::VideoDecodeAccelerator::SupportedProfiles |
69 GetSupportedProfiles(); | 71 GetSupportedProfiles(); |
70 | 72 |
71 private: | 73 private: |
| 74 class VaapiH264Accelerator; |
| 75 |
72 // Notify the client that an error has occurred and decoding cannot continue. | 76 // Notify the client that an error has occurred and decoding cannot continue. |
73 void NotifyError(Error error); | 77 void NotifyError(Error error); |
74 | 78 |
75 // Map the received input buffer into this process' address space and | 79 // Map the received input buffer into this process' address space and |
76 // queue it for decode. | 80 // queue it for decode. |
77 void MapAndQueueNewInputBuffer( | 81 void MapAndQueueNewInputBuffer( |
78 const media::BitstreamBuffer& bitstream_buffer); | 82 const media::BitstreamBuffer& bitstream_buffer); |
79 | 83 |
80 // Get a new input buffer from the queue and set it up in decoder. This will | 84 // Get a new input buffer from the queue and set it up in decoder. This will |
81 // sleep if no input buffers are available. Return true if a new buffer has | 85 // sleep if no input buffers are available. Return true if a new buffer has |
82 // been set up, false if an early exit has been requested (due to initiated | 86 // been set up, false if an early exit has been requested (due to initiated |
83 // reset/flush/destroy). | 87 // reset/flush/destroy). |
84 bool GetInputBuffer_Locked(); | 88 bool GetInputBuffer_Locked(); |
85 | 89 |
86 // Signal the client that the current buffer has been read and can be | 90 // Signal the client that the current buffer has been read and can be |
87 // returned. Will also release the mapping. | 91 // returned. Will also release the mapping. |
88 void ReturnCurrInputBuffer_Locked(); | 92 void ReturnCurrInputBuffer_Locked(); |
89 | 93 |
90 // Pass one or more output buffers to the decoder. This will sleep | 94 // Wait for more surfaces to become available. Return true once they do or |
91 // if no buffers are available. Return true if buffers have been set up or | 95 // false if an early exit has been requested (due to an initiated |
92 // false if an early exit has been requested (due to initiated | |
93 // reset/flush/destroy). | 96 // reset/flush/destroy). |
94 bool FeedDecoderWithOutputSurfaces_Locked(); | 97 bool WaitForSurfaces_Locked(); |
95 | 98 |
96 // Continue decoding given input buffers and sleep waiting for input/output | 99 // Continue decoding given input buffers and sleep waiting for input/output |
97 // as needed. Will exit if a new set of surfaces or reset/flush/destroy | 100 // as needed. Will exit if a new set of surfaces or reset/flush/destroy |
98 // is requested. | 101 // is requested. |
99 void DecodeTask(); | 102 void DecodeTask(); |
100 | 103 |
101 // Scheduled after receiving a flush request and executed after the current | 104 // Scheduled after receiving a flush request and executed after the current |
102 // decoding task finishes decoding pending inputs. Makes the decoder return | 105 // decoding task finishes decoding pending inputs. Makes the decoder return |
103 // all remaining output pictures and puts it in an idle state, ready | 106 // all remaining output pictures and puts it in an idle state, ready |
104 // to resume if needed and schedules a FinishFlush. | 107 // to resume if needed and schedules a FinishFlush. |
(...skipping 15 matching lines...) Expand all Loading... |
120 // finished. | 123 // finished. |
121 void FinishReset(); | 124 void FinishReset(); |
122 | 125 |
123 // Helper for Destroy(), doing all the actual work except for deleting self. | 126 // Helper for Destroy(), doing all the actual work except for deleting self. |
124 void Cleanup(); | 127 void Cleanup(); |
125 | 128 |
126 // Get a usable framebuffer configuration for use in binding textures | 129 // Get a usable framebuffer configuration for use in binding textures |
127 // or return false on failure. | 130 // or return false on failure. |
128 bool InitializeFBConfig(); | 131 bool InitializeFBConfig(); |
129 | 132 |
130 // Callback for the decoder to execute when it wants us to output given | |
131 // |va_surface|. | |
132 void SurfaceReady(int32 input_id, const scoped_refptr<VASurface>& va_surface); | |
133 | |
134 // Callback to be executed once we have a |va_surface| to be output and | 133 // Callback to be executed once we have a |va_surface| to be output and |
135 // an available |picture| to use for output. | 134 // an available |picture| to use for output. |
136 // Puts contents of |va_surface| into given |picture|, releases the | 135 // Puts contents of |va_surface| into given |picture|, releases the |
137 // surface and passes the resulting picture to client for output. | 136 // surface and passes the resulting picture to client for output. |
138 void OutputPicture(const scoped_refptr<VASurface>& va_surface, | 137 void OutputPicture(const scoped_refptr<VASurface>& va_surface, |
139 int32 input_id, | 138 int32 input_id, |
140 VaapiPicture* picture); | 139 VaapiPicture* picture); |
141 | 140 |
142 // Try to OutputPicture() if we have both a ready surface and picture. | 141 // Try to OutputPicture() if we have both a ready surface and picture. |
143 void TryOutputSurface(); | 142 void TryOutputSurface(); |
144 | 143 |
145 // Called when a VASurface is no longer in use by the decoder or is not being | 144 // Called when a VASurface is no longer in use by the decoder or is not being |
146 // synced/waiting to be synced to a picture. Returns it to available surfaces | 145 // synced/waiting to be synced to a picture. Returns it to available surfaces |
147 // pool. | 146 // pool. |
148 void RecycleVASurfaceID(VASurfaceID va_surface_id); | 147 void RecycleVASurfaceID(VASurfaceID va_surface_id); |
149 | 148 |
150 // Initiate wait cycle for surfaces to be released before we release them | 149 // Initiate wait cycle for surfaces to be released before we release them |
151 // and allocate new ones, as requested by the decoder. | 150 // and allocate new ones, as requested by the decoder. |
152 void InitiateSurfaceSetChange(size_t num_pics, gfx::Size size); | 151 void InitiateSurfaceSetChange(size_t num_pics, gfx::Size size); |
| 152 |
153 // Check if the surfaces have been released or post ourselves for later. | 153 // Check if the surfaces have been released or post ourselves for later. |
154 void TryFinishSurfaceSetChange(); | 154 void TryFinishSurfaceSetChange(); |
155 | 155 |
| 156 // |
| 157 // Below methods are used by accelerator implementations. |
| 158 // |
| 159 // Decode of |dec_surface| is ready to be submitted and all codec-specific |
| 160 // settings are set in hardware. |
| 161 bool DecodeSurface(const scoped_refptr<VaapiDecodeSurface>& dec_surface); |
| 162 |
| 163 // |dec_surface| is ready to be outputted once decode is finished. |
| 164 // This can be called before decode is actually done in hardware, and this |
| 165 // method is responsible for maintaining the ordering, i.e. the surfaces have |
| 166 // to be outputted in the same order as SurfaceReady is called. |
| 167 // On Intel, we don't have to explicitly maintain the ordering however, as the |
| 168 // driver will maintain ordering, as well as dependencies, and will process |
| 169 // each submitted command in order, and run each command only if its |
| 170 // dependencies are ready. |
| 171 void SurfaceReady(const scoped_refptr<VaapiDecodeSurface>& dec_surface); |
| 172 |
| 173 // Return a new VaapiDecodeSurface for decoding into, or nullptr if not |
| 174 // available. |
| 175 scoped_refptr<VaapiDecodeSurface> CreateSurface(); |
| 176 |
| 177 |
156 // Client-provided GL state. | 178 // Client-provided GL state. |
157 base::Callback<bool(void)> make_context_current_; | 179 base::Callback<bool(void)> make_context_current_; |
158 | 180 |
159 // VAVDA state. | 181 // VAVDA state. |
160 enum State { | 182 enum State { |
161 // Initialize() not called yet or failed. | 183 // Initialize() not called yet or failed. |
162 kUninitialized, | 184 kUninitialized, |
163 // DecodeTask running. | 185 // DecodeTask running. |
164 kDecoding, | 186 kDecoding, |
165 // Resetting, waiting for decoder to finish current task and cleanup. | 187 // Resetting, waiting for decoder to finish current task and cleanup. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 // Callback used when creating VASurface objects. | 266 // Callback used when creating VASurface objects. |
245 VASurface::ReleaseCB va_surface_release_cb_; | 267 VASurface::ReleaseCB va_surface_release_cb_; |
246 | 268 |
247 // To expose client callbacks from VideoDecodeAccelerator. | 269 // To expose client callbacks from VideoDecodeAccelerator. |
248 // NOTE: all calls to these objects *MUST* be executed on message_loop_. | 270 // NOTE: all calls to these objects *MUST* be executed on message_loop_. |
249 scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_; | 271 scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_; |
250 base::WeakPtr<Client> client_; | 272 base::WeakPtr<Client> client_; |
251 | 273 |
252 // Comes after vaapi_wrapper_ to ensure its destructor is executed before | 274 // Comes after vaapi_wrapper_ to ensure its destructor is executed before |
253 // vaapi_wrapper_ is destroyed. | 275 // vaapi_wrapper_ is destroyed. |
254 scoped_ptr<VaapiH264Decoder> decoder_; | 276 scoped_ptr<VaapiH264Accelerator> h264_accelerator_; |
| 277 // After h264_accelerator_ to ensure correct destruction order. |
| 278 scoped_ptr<AcceleratedVideoDecoder> decoder_; |
| 279 |
255 base::Thread decoder_thread_; | 280 base::Thread decoder_thread_; |
256 // Use this to post tasks to |decoder_thread_| instead of | 281 // Use this to post tasks to |decoder_thread_| instead of |
257 // |decoder_thread_.message_loop()| because the latter will be NULL once | 282 // |decoder_thread_.message_loop()| because the latter will be NULL once |
258 // |decoder_thread_.Stop()| returns. | 283 // |decoder_thread_.Stop()| returns. |
259 scoped_refptr<base::MessageLoopProxy> decoder_thread_proxy_; | 284 scoped_refptr<base::MessageLoopProxy> decoder_thread_proxy_; |
260 | 285 |
261 int num_frames_at_client_; | 286 int num_frames_at_client_; |
262 int num_stream_bufs_at_decoder_; | 287 int num_stream_bufs_at_decoder_; |
263 | 288 |
264 // Whether we are waiting for any pending_output_cbs_ to be run before | 289 // Whether we are waiting for any pending_output_cbs_ to be run before |
(...skipping 14 matching lines...) Expand all Loading... |
279 | 304 |
280 // The WeakPtrFactory for |weak_this_|. | 305 // The WeakPtrFactory for |weak_this_|. |
281 base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_; | 306 base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_; |
282 | 307 |
283 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); | 308 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); |
284 }; | 309 }; |
285 | 310 |
286 } // namespace content | 311 } // namespace content |
287 | 312 |
288 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ | 313 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ |
OLD | NEW |