Chromium Code Reviews| 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 |