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 <map> |
11 #include <queue> | 12 #include <queue> |
12 #include <utility> | 13 #include <utility> |
13 #include <vector> | 14 #include <vector> |
14 | 15 |
15 #include "base/logging.h" | 16 #include "base/logging.h" |
16 #include "base/memory/ref_counted.h" | 17 #include "base/memory/linked_ptr.h" |
17 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
18 #include "base/message_loop.h" | 19 #include "base/message_loop.h" |
19 #include "base/shared_memory.h" | 20 #include "base/shared_memory.h" |
20 #include "base/synchronization/condition_variable.h" | 21 #include "base/synchronization/condition_variable.h" |
21 #include "base/synchronization/lock.h" | 22 #include "base/synchronization/lock.h" |
22 #include "base/threading/non_thread_safe.h" | 23 #include "base/threading/non_thread_safe.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_h264_decoder.h" |
| 27 #include "content/common/gpu/media/vaapi_wrapper.h" |
26 #include "media/base/bitstream_buffer.h" | 28 #include "media/base/bitstream_buffer.h" |
27 #include "media/video/picture.h" | 29 #include "media/video/picture.h" |
28 #include "media/video/video_decode_accelerator.h" | 30 #include "media/video/video_decode_accelerator.h" |
29 #include "ui/gl/gl_bindings.h" | 31 #include "ui/gl/gl_bindings.h" |
30 | 32 |
31 namespace content { | 33 namespace content { |
32 | 34 |
33 // Class to provide video decode acceleration for Intel systems with hardware | 35 // Class to provide video decode acceleration for Intel systems with hardware |
34 // support for it, and on which libva is available. | 36 // support for it, and on which libva is available. |
35 // Decoding tasks are performed in a separate decoding thread. | 37 // Decoding tasks are performed in a separate decoding thread. |
(...skipping 14 matching lines...) Expand all Loading... |
50 // media::VideoDecodeAccelerator implementation. | 52 // media::VideoDecodeAccelerator implementation. |
51 virtual bool Initialize(media::VideoCodecProfile profile) OVERRIDE; | 53 virtual bool Initialize(media::VideoCodecProfile profile) OVERRIDE; |
52 virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE; | 54 virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE; |
53 virtual void AssignPictureBuffers( | 55 virtual void AssignPictureBuffers( |
54 const std::vector<media::PictureBuffer>& buffers) OVERRIDE; | 56 const std::vector<media::PictureBuffer>& buffers) OVERRIDE; |
55 virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE; | 57 virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE; |
56 virtual void Flush() OVERRIDE; | 58 virtual void Flush() OVERRIDE; |
57 virtual void Reset() OVERRIDE; | 59 virtual void Reset() OVERRIDE; |
58 virtual void Destroy() OVERRIDE; | 60 virtual void Destroy() OVERRIDE; |
59 | 61 |
60 // Do any necessary initialization before the sandbox is enabled. | |
61 static void PreSandboxInitialization(); | |
62 | |
63 private: | 62 private: |
64 // Notify the client that |output_id| is ready for displaying. | 63 // Notify the client that |output_id| is ready for displaying. |
65 void NotifyPictureReady(int32 input_id, int32 output_id); | 64 void NotifyPictureReady(int32 input_id, int32 output_id); |
66 | 65 |
67 // Notify the client that an error has occurred and decoding cannot continue. | 66 // Notify the client that an error has occurred and decoding cannot continue. |
68 void NotifyError(Error error); | 67 void NotifyError(Error error); |
69 | 68 |
70 // Map the received input buffer into this process' address space and | 69 // Map the received input buffer into this process' address space and |
71 // queue it for decode. | 70 // queue it for decode. |
72 void MapAndQueueNewInputBuffer( | 71 void MapAndQueueNewInputBuffer( |
73 const media::BitstreamBuffer& bitstream_buffer); | 72 const media::BitstreamBuffer& bitstream_buffer); |
74 | 73 |
75 // Get a new input buffer from the queue and set it up in decoder. This will | 74 // Get a new input buffer from the queue and set it up in decoder. This will |
76 // sleep if no input buffers are available. Return true if a new buffer has | 75 // sleep if no input buffers are available. Return true if a new buffer has |
77 // been set up, false if an early exit has been requested (due to initiated | 76 // been set up, false if an early exit has been requested (due to initiated |
78 // reset/flush/destroy). | 77 // reset/flush/destroy). |
79 bool GetInputBuffer_Locked(); | 78 bool GetInputBuffer_Locked(); |
80 | 79 |
81 // Signal the client that the current buffer has been read and can be | 80 // Signal the client that the current buffer has been read and can be |
82 // returned. Will also release the mapping. | 81 // returned. Will also release the mapping. |
83 void ReturnCurrInputBuffer_Locked(); | 82 void ReturnCurrInputBuffer_Locked(); |
84 | 83 |
85 // Get and set up one or more output buffers in the decoder. This will sleep | 84 // Pass one or more output buffers to the decoder. This will sleep |
86 // if no buffers are available. Return true if buffers have been set up or | 85 // if no buffers are available. Return true if buffers have been set up or |
87 // false if an early exit has been requested (due to initiated | 86 // false if an early exit has been requested (due to initiated |
88 // reset/flush/destroy). | 87 // reset/flush/destroy). |
89 bool GetOutputBuffers_Locked(); | 88 bool FeedDecoderWithOutputSurfaces_Locked(); |
90 | 89 |
91 // Initial decode task: get the decoder to the point in the stream from which | 90 // Get the decoder to the point in the stream from which it can start/continue |
92 // it can start/continue decoding. Does not require output buffers and does | 91 // decoding. Called either when starting to decode a new stream or when |
93 // not produce output frames. Called either when starting with a new stream | 92 // playback is to be resumed following a seek. |
94 // or when playback is to be resumed following a seek. | |
95 void InitialDecodeTask(); | 93 void InitialDecodeTask(); |
96 | 94 |
97 // Decoding task. Will continue decoding given input buffers and sleep | 95 // Continue decoding given input buffers and sleep waiting for input/output |
98 // waiting for input/output as needed. Will exit if a reset/flush/destroy | 96 // as needed. Will exit if a reset/flush/destroy is requested. |
99 // is requested. | |
100 void DecodeTask(); | 97 void DecodeTask(); |
101 | 98 |
102 // Scheduled after receiving a flush request and executed after the current | 99 // Scheduled after receiving a flush request and executed after the current |
103 // decoding task finishes decoding pending inputs. Makes the decoder return | 100 // decoding task finishes decoding pending inputs. Makes the decoder return |
104 // all remaining output pictures and puts it in an idle state, ready | 101 // all remaining output pictures and puts it in an idle state, ready |
105 // to resume if needed and schedules a FinishFlush. | 102 // to resume if needed and schedules a FinishFlush. |
106 void FlushTask(); | 103 void FlushTask(); |
107 | 104 |
108 // Scheduled by the FlushTask after decoder is flushed to put VAVDA into idle | 105 // Scheduled by the FlushTask after decoder is flushed to put VAVDA into idle |
109 // state and notify the client that flushing has been finished. | 106 // state and notify the client that flushing has been finished. |
110 void FinishFlush(); | 107 void FinishFlush(); |
111 | 108 |
112 // Scheduled after receiving a reset request and executed after the current | 109 // Scheduled after receiving a reset request and executed after the current |
113 // decoding task finishes decoding the current frame. Puts the decoder into | 110 // decoding task finishes decoding the current frame. Puts the decoder into |
114 // an idle state, ready to resume if needed, discarding decoded but not yet | 111 // an idle state, ready to resume if needed, discarding decoded but not yet |
115 // outputted pictures (decoder keeps ownership of their associated picture | 112 // outputted pictures (decoder keeps ownership of their associated picture |
116 // buffers). Schedules a FinishReset afterwards. | 113 // buffers). Schedules a FinishReset afterwards. |
117 void ResetTask(); | 114 void ResetTask(); |
118 | 115 |
119 // Scheduled by ResetTask after it's done putting VAVDA into an idle state. | 116 // Scheduled by ResetTask after it's done putting VAVDA into an idle state. |
120 // Drops remaining input buffers and notifies the client that reset has been | 117 // Drops remaining input buffers and notifies the client that reset has been |
121 // finished. | 118 // finished. |
122 void FinishReset(); | 119 void FinishReset(); |
123 | 120 |
124 // Helper for Destroy(), doing all the actual work except for deleting self. | 121 // Helper for Destroy(), doing all the actual work except for deleting self. |
125 void Cleanup(); | 122 void Cleanup(); |
126 | 123 |
127 // Lazily initialize static data after sandbox is enabled. Return false on | 124 // Get a usable framebuffer configuration for use in binding textures |
128 // init failure. | 125 // or return false on failure. |
129 static bool PostSandboxInitialization(); | 126 bool InitializeFBConfig(); |
| 127 |
| 128 // Callback for the decoder to execute when it wants us to output given |
| 129 // |va_surface|. |
| 130 void SurfaceReady(int32 input_id, const scoped_refptr<VASurface>& va_surface); |
| 131 |
| 132 // Represents a texture bound to an X Pixmap for output purposes. |
| 133 class TFPPicture; |
| 134 |
| 135 // Callback to be executed once we have a |va_surface| to be output and |
| 136 // an available |tfp_picture| to use for output. |
| 137 // Puts contents of |va_surface| into given |tfp_picture|, releases the |
| 138 // surface and passes the resulting picture to client for output. |
| 139 void OutputPicture(const scoped_refptr<VASurface>& va_surface, |
| 140 int32 input_id, |
| 141 TFPPicture* tfp_picture); |
| 142 |
| 143 // Try to OutputPicture() if we have both a ready surface and picture. |
| 144 void TryOutputSurface(); |
| 145 |
| 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 |
| 148 // pool. |
| 149 void RecycleVASurfaceID(VASurfaceID va_surface_id); |
130 | 150 |
131 // Client-provided X/GLX state. | 151 // Client-provided X/GLX state. |
132 Display* x_display_; | 152 Display* x_display_; |
133 GLXContext glx_context_; | 153 GLXContext glx_context_; |
134 base::Callback<bool(void)> make_context_current_; | 154 base::Callback<bool(void)> make_context_current_; |
| 155 GLXFBConfig fb_config_; |
135 | 156 |
136 // VAVDA state. | 157 // VAVDA state. |
137 enum State { | 158 enum State { |
138 // Initialize() not called yet or failed. | 159 // Initialize() not called yet or failed. |
139 kUninitialized, | 160 kUninitialized, |
140 // Initialize() succeeded, no initial decode and no pictures requested. | 161 // Initialize() succeeded, no initial decode and no pictures requested. |
141 kInitialized, | 162 kInitialized, |
142 // Initial decode finished, requested pictures and waiting for them. | 163 // Initial decode finished, requested pictures and waiting for them. |
143 kPicturesRequested, | 164 kPicturesRequested, |
144 // Everything initialized, pictures received and assigned, in decoding. | 165 // Everything initialized, pictures received and assigned, in decoding. |
145 kDecoding, | 166 kDecoding, |
146 // Resetting, waiting for decoder to finish current task and cleanup. | 167 // Resetting, waiting for decoder to finish current task and cleanup. |
147 kResetting, | 168 kResetting, |
148 // Flushing, waiting for decoder to finish current task and cleanup. | 169 // Flushing, waiting for decoder to finish current task and cleanup. |
149 kFlushing, | 170 kFlushing, |
150 // Idle, decoder in state ready to resume decoding. | 171 // Idle, decoder in state ready to resume decoding. |
151 kIdle, | 172 kIdle, |
152 // Destroying, waiting for the decoder to finish current task. | 173 // Destroying, waiting for the decoder to finish current task. |
153 kDestroying, | 174 kDestroying, |
154 }; | 175 }; |
155 | 176 |
| 177 // Protects input buffer and surface queues and state_. |
| 178 base::Lock lock_; |
156 State state_; | 179 State state_; |
157 | 180 |
158 // Protects input and output buffer queues and state_. | |
159 base::Lock lock_; | |
160 | |
161 // An input buffer awaiting consumption, provided by the client. | 181 // An input buffer awaiting consumption, provided by the client. |
162 struct InputBuffer { | 182 struct InputBuffer { |
163 InputBuffer(); | 183 InputBuffer(); |
164 ~InputBuffer(); | 184 ~InputBuffer(); |
165 | 185 |
166 int32 id; | 186 int32 id; |
167 size_t size; | 187 size_t size; |
168 scoped_ptr<base::SharedMemory> shm; | 188 scoped_ptr<base::SharedMemory> shm; |
169 }; | 189 }; |
170 | 190 |
171 // Queue for incoming input buffers. | 191 // Queue for incoming input buffers. |
172 typedef std::queue<linked_ptr<InputBuffer> > InputBuffers; | 192 typedef std::queue<linked_ptr<InputBuffer> > InputBuffers; |
173 InputBuffers input_buffers_; | 193 InputBuffers input_buffers_; |
174 // Signalled when input buffers are queued onto the input_buffers_ queue. | 194 // Signalled when input buffers are queued onto the input_buffers_ queue. |
175 base::ConditionVariable input_ready_; | 195 base::ConditionVariable input_ready_; |
176 | 196 |
177 // Current input buffer at decoder. | 197 // Current input buffer at decoder. |
178 linked_ptr<InputBuffer> curr_input_buffer_; | 198 linked_ptr<InputBuffer> curr_input_buffer_; |
179 | 199 |
180 // Queue for incoming input buffers. | 200 // Queue for incoming output buffers (texture ids). |
181 typedef std::queue<int32> OutputBuffers; | 201 typedef std::queue<int32> OutputBuffers; |
182 OutputBuffers output_buffers_; | 202 OutputBuffers output_buffers_; |
183 // Signalled when output buffers are queued onto the output_buffers_ queue. | 203 |
184 base::ConditionVariable output_ready_; | 204 typedef std::map<int32, linked_ptr<TFPPicture> > TFPPictures; |
| 205 // All allocated TFPPictures, regardless of their current state. TFPPictures |
| 206 // are allocated once and destroyed at the end of decode. |
| 207 TFPPictures tfp_pictures_; |
| 208 std::list<TFPPicture*> available_tfp_pictures_; |
| 209 |
| 210 // Return a TFPPicture associated with given client-provided id. |
| 211 TFPPicture* TFPPictureById(int32 picture_buffer_id); |
| 212 |
| 213 // Number/resolution of output picture buffers. |
| 214 size_t num_pics_; |
| 215 gfx::Size pic_size_; |
| 216 |
| 217 // VA Surfaces no longer in use that can be passed back to the decoder for |
| 218 // reuse, once it requests them. |
| 219 std::list<VASurfaceID> available_va_surfaces_; |
| 220 // Signalled when output surfaces are queued onto the available_va_surfaces_ |
| 221 // queue. |
| 222 base::ConditionVariable surfaces_available_; |
| 223 |
| 224 // Pending output requests from the decoder. When it indicates that we should |
| 225 // output a surface and we have an available TFPPicture (i.e. texture) ready |
| 226 // to use, we'll execute the callback passing the TFPPicture. The callback |
| 227 // will put the contents of the surface into the picture and return it to |
| 228 // the client, releasing the surface as well. |
| 229 // If we don't have any available TFPPictures at the time when the decoder |
| 230 // requests output, we'll store the request on pending_output_cbs_ queue for |
| 231 // later and run it once the client gives us more textures |
| 232 // via ReusePictureBuffer(). |
| 233 typedef base::Callback<void(TFPPicture*)> OutputCB; |
| 234 std::queue<OutputCB> pending_output_cbs_; |
185 | 235 |
186 // ChildThread's message loop | 236 // ChildThread's message loop |
187 base::MessageLoop* message_loop_; | 237 base::MessageLoop* message_loop_; |
188 | 238 |
189 // WeakPtr<> pointing to |this| for use in posting tasks from the decoder | 239 // WeakPtr<> pointing to |this| for use in posting tasks from the decoder |
190 // thread back to the ChildThread. Because the decoder thread is a member of | 240 // thread back to the ChildThread. Because the decoder thread is a member of |
191 // this class, any task running on the decoder thread is guaranteed that this | 241 // this class, any task running on the decoder thread is guaranteed that this |
192 // object is still alive. As a result, tasks posted from ChildThread to | 242 // object is still alive. As a result, tasks posted from ChildThread to |
193 // decoder thread should use base::Unretained(this), and tasks posted from the | 243 // decoder thread should use base::Unretained(this), and tasks posted from the |
194 // decoder thread to the ChildThread should use |weak_this_|. | 244 // decoder thread to the ChildThread should use |weak_this_|. |
195 base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_; | 245 base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_; |
196 | 246 |
197 // To expose client callbacks from VideoDecodeAccelerator. | 247 // To expose client callbacks from VideoDecodeAccelerator. |
198 // NOTE: all calls to these objects *MUST* be executed on message_loop_. | 248 // NOTE: all calls to these objects *MUST* be executed on message_loop_. |
199 base::WeakPtrFactory<Client> client_ptr_factory_; | 249 base::WeakPtrFactory<Client> client_ptr_factory_; |
200 base::WeakPtr<Client> client_; | 250 base::WeakPtr<Client> client_; |
201 | 251 |
| 252 scoped_ptr<VaapiWrapper> vaapi_wrapper_; |
| 253 |
| 254 // Comes after vaapi_wrapper_ to ensure its destructor is executed before |
| 255 // vaapi_wrapper_ is destroyed. |
| 256 scoped_ptr<VaapiH264Decoder> decoder_; |
202 base::Thread decoder_thread_; | 257 base::Thread decoder_thread_; |
203 VaapiH264Decoder decoder_; | |
204 | 258 |
205 int num_frames_at_client_; | 259 int num_frames_at_client_; |
206 int num_stream_bufs_at_decoder_; | 260 int num_stream_bufs_at_decoder_; |
207 | 261 |
208 // Posted onto ChildThread by the decoder to submit a GPU job to decode | |
209 // and put the decoded picture into output buffer. Takes ownership of | |
210 // the queues' memory. | |
211 void SubmitDecode(int32 output_id, | |
212 scoped_ptr<std::queue<VABufferID> > va_bufs, | |
213 scoped_ptr<std::queue<VABufferID> > slice_bufs); | |
214 | |
215 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); | 262 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); |
216 }; | 263 }; |
217 | 264 |
218 } // namespace content | 265 } // namespace content |
219 | 266 |
220 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ | 267 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ |
OLD | NEW |