| 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 |