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" |
26 #include "content/common/gpu/media/vaapi_delegate.h" | |
25 #include "content/common/gpu/media/vaapi_h264_decoder.h" | 27 #include "content/common/gpu/media/vaapi_h264_decoder.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. |
(...skipping 15 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 GetOutputSurfaces_Locked(); |
Ami GONE FROM CHROMIUM
2013/05/17 23:19:15
function name is crying out for improvement
Pawel Osciak
2013/05/21 22:32:35
Done.
| |
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 // Put contents of the |va_surface| into given |tfp_picture| for output | |
136 // and release the surface afterwards. | |
137 void SyncSurfaceToPicture(VASurfaceID va_surface_id, TFPPicture* tfp_picture); | |
Ami GONE FROM CHROMIUM
2013/05/17 23:19:15
This CL finaly makes it possible for this madness
Pawel Osciak
2013/05/21 22:32:35
Yes!
Done.
| |
138 | |
139 // Callback to be executed once we have a |va_surface| to be output and | |
140 // an available |tfp_picture| to use for output. | |
141 void OutputPicture(const scoped_refptr<VASurface>& va_surface, | |
142 int32 input_id, | |
143 TFPPicture* tfp_picture); | |
144 | |
145 // Try to OutputPicture() if we have both a ready surface and picture. | |
146 void TryOutputSurface(); | |
147 | |
148 // Called when a VASurface is no longer in use by the decoder or is not being | |
149 // synced/waiting to be synced to a picture. Returns it to available surfaces | |
150 // pool. | |
151 void RecycleVASurfaceID(VASurfaceID va_surface_id); | |
130 | 152 |
131 // Client-provided X/GLX state. | 153 // Client-provided X/GLX state. |
132 Display* x_display_; | 154 Display* x_display_; |
133 GLXContext glx_context_; | 155 GLXContext glx_context_; |
134 base::Callback<bool(void)> make_context_current_; | 156 base::Callback<bool(void)> make_context_current_; |
157 GLXFBConfig fb_config_; | |
135 | 158 |
136 // VAVDA state. | 159 // VAVDA state. |
137 enum State { | 160 enum State { |
138 // Initialize() not called yet or failed. | 161 // Initialize() not called yet or failed. |
139 kUninitialized, | 162 kUninitialized, |
140 // Initialize() succeeded, no initial decode and no pictures requested. | 163 // Initialize() succeeded, no initial decode and no pictures requested. |
141 kInitialized, | 164 kInitialized, |
142 // Initial decode finished, requested pictures and waiting for them. | 165 // Initial decode finished, requested pictures and waiting for them. |
143 kPicturesRequested, | 166 kPicturesRequested, |
144 // Everything initialized, pictures received and assigned, in decoding. | 167 // Everything initialized, pictures received and assigned, in decoding. |
145 kDecoding, | 168 kDecoding, |
146 // Resetting, waiting for decoder to finish current task and cleanup. | 169 // Resetting, waiting for decoder to finish current task and cleanup. |
147 kResetting, | 170 kResetting, |
148 // Flushing, waiting for decoder to finish current task and cleanup. | 171 // Flushing, waiting for decoder to finish current task and cleanup. |
149 kFlushing, | 172 kFlushing, |
150 // Idle, decoder in state ready to resume decoding. | 173 // Idle, decoder in state ready to resume decoding. |
151 kIdle, | 174 kIdle, |
152 // Destroying, waiting for the decoder to finish current task. | 175 // Destroying, waiting for the decoder to finish current task. |
153 kDestroying, | 176 kDestroying, |
154 }; | 177 }; |
155 | 178 |
156 State state_; | 179 State state_; |
Ami GONE FROM CHROMIUM
2013/05/17 23:19:15
should go under lock_
Pawel Osciak
2013/05/21 22:32:35
Done.
| |
157 | 180 |
158 // Protects input and output buffer queues and state_. | 181 // Protects input buffer and surface queues and state_. |
159 base::Lock lock_; | 182 base::Lock lock_; |
160 | 183 |
161 // An input buffer awaiting consumption, provided by the client. | 184 // An input buffer awaiting consumption, provided by the client. |
162 struct InputBuffer { | 185 struct InputBuffer { |
163 InputBuffer(); | 186 InputBuffer(); |
164 ~InputBuffer(); | 187 ~InputBuffer(); |
165 | 188 |
166 int32 id; | 189 int32 id; |
167 size_t size; | 190 size_t size; |
168 scoped_ptr<base::SharedMemory> shm; | 191 scoped_ptr<base::SharedMemory> shm; |
169 }; | 192 }; |
170 | 193 |
171 // Queue for incoming input buffers. | 194 // Queue for incoming input buffers. |
172 typedef std::queue<linked_ptr<InputBuffer> > InputBuffers; | 195 typedef std::queue<linked_ptr<InputBuffer> > InputBuffers; |
173 InputBuffers input_buffers_; | 196 InputBuffers input_buffers_; |
174 // Signalled when input buffers are queued onto the input_buffers_ queue. | 197 // Signalled when input buffers are queued onto the input_buffers_ queue. |
175 base::ConditionVariable input_ready_; | 198 base::ConditionVariable input_ready_; |
176 | 199 |
177 // Current input buffer at decoder. | 200 // Current input buffer at decoder. |
178 linked_ptr<InputBuffer> curr_input_buffer_; | 201 linked_ptr<InputBuffer> curr_input_buffer_; |
179 | 202 |
180 // Queue for incoming input buffers. | 203 // Queue for incoming output buffers (texture ids). |
181 typedef std::queue<int32> OutputBuffers; | 204 typedef std::queue<int32> OutputBuffers; |
182 OutputBuffers output_buffers_; | 205 OutputBuffers output_buffers_; |
183 // Signalled when output buffers are queued onto the output_buffers_ queue. | 206 |
184 base::ConditionVariable output_ready_; | 207 typedef std::map<int32, linked_ptr<TFPPicture> > TFPPictures; |
208 // All allocated TFPPictures, regardless of their current state. TFPPictures | |
209 // are allocated once and destroyed at the end of decode. | |
210 TFPPictures tfp_pictures_; | |
211 std::list<TFPPicture*> available_tfp_pictures_; | |
212 | |
213 // Return a TFPPicture associated with given client-provided id. | |
214 TFPPicture* TFPPictureById(int32 picture_buffer_id); | |
215 | |
216 // Number/resolution of output picture buffers. | |
217 size_t num_pics_; | |
218 gfx::Size pic_size_; | |
Ami GONE FROM CHROMIUM
2013/05/17 23:19:15
You can drop both of these in favor of simply call
Pawel Osciak
2013/05/21 22:32:35
This would result in calling the decoder from Chil
| |
219 | |
220 // VA Surfaces no longer in use that can be passed back to the decoder for | |
221 // reuse, once it requests them. | |
222 std::list<VASurfaceID> available_va_surfaces_; | |
223 // Signalled when output surfaces are queued onto the available_va_surfaces_ | |
224 // queue. | |
225 base::ConditionVariable surfaces_available_; | |
226 | |
227 // Pending output requests from the decoder. When it indicates that we should | |
228 // output a surface and we have an available TFPPicture (i.e. texture) ready | |
229 // to use, we'll execute the callback passing the TFPPicture. The callback | |
230 // will put the contents of the surface into the picture and return it to | |
231 // the client, releasing the surface as well. | |
232 // If we don't have any available TFPPictures at the time when the decoder | |
233 // requests output, we'll store the request on pending_output_cbs_ queue for | |
234 // later and run it once the client gives us more textures | |
235 // via ReusePictureBuffer(). | |
236 typedef base::Callback<void(TFPPicture*)> OutputCB; | |
237 std::queue<OutputCB> pending_output_cbs_; | |
185 | 238 |
186 // ChildThread's message loop | 239 // ChildThread's message loop |
187 base::MessageLoop* message_loop_; | 240 base::MessageLoop* message_loop_; |
188 | 241 |
189 // WeakPtr<> pointing to |this| for use in posting tasks from the decoder | 242 // 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 | 243 // 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 | 244 // 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 | 245 // 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 | 246 // decoder thread should use base::Unretained(this), and tasks posted from the |
194 // decoder thread to the ChildThread should use |weak_this_|. | 247 // decoder thread to the ChildThread should use |weak_this_|. |
195 base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_; | 248 base::WeakPtr<VaapiVideoDecodeAccelerator> weak_this_; |
196 | 249 |
197 // To expose client callbacks from VideoDecodeAccelerator. | 250 // To expose client callbacks from VideoDecodeAccelerator. |
198 // NOTE: all calls to these objects *MUST* be executed on message_loop_. | 251 // NOTE: all calls to these objects *MUST* be executed on message_loop_. |
199 base::WeakPtrFactory<Client> client_ptr_factory_; | 252 base::WeakPtrFactory<Client> client_ptr_factory_; |
200 base::WeakPtr<Client> client_; | 253 base::WeakPtr<Client> client_; |
201 | 254 |
202 base::Thread decoder_thread_; | 255 base::Thread decoder_thread_; |
203 VaapiH264Decoder decoder_; | 256 scoped_ptr<VaapiH264Decoder> decoder_; |
Ami GONE FROM CHROMIUM
2013/05/17 23:19:15
this should go above thread_ so that it's easy to
Pawel Osciak
2013/05/21 22:32:35
Done.
| |
204 | 257 |
205 int num_frames_at_client_; | 258 int num_frames_at_client_; |
206 int num_stream_bufs_at_decoder_; | 259 int num_stream_bufs_at_decoder_; |
207 | 260 |
208 // Posted onto ChildThread by the decoder to submit a GPU job to decode | 261 scoped_refptr<VaapiDelegate> vaapi_delegate_; |
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 | 262 |
215 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); | 263 DISALLOW_COPY_AND_ASSIGN(VaapiVideoDecodeAccelerator); |
216 }; | 264 }; |
217 | 265 |
218 } // namespace content | 266 } // namespace content |
219 | 267 |
220 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ | 268 #endif // CONTENT_COMMON_GPU_MEDIA_VAAPI_VIDEO_DECODE_ACCELERATOR_H_ |
OLD | NEW |