Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 #ifndef CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ | 5 #ifndef CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ |
| 6 #define CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ | 6 #define CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ |
| 7 | 7 |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| 11 #include <queue> | 11 #include <queue> |
| 12 | 12 |
| 13 #include "base/mac/scoped_cftyperef.h" | 13 #include "base/mac/scoped_cftyperef.h" |
| 14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/linked_ptr.h" |
| 15 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
| 18 #include "base/threading/thread_checker.h" | |
| 18 #include "content/common/gpu/media/vt.h" | 19 #include "content/common/gpu/media/vt.h" |
| 19 #include "media/filters/h264_parser.h" | 20 #include "media/filters/h264_parser.h" |
| 20 #include "media/video/video_decode_accelerator.h" | 21 #include "media/video/video_decode_accelerator.h" |
| 21 #include "ui/gfx/geometry/size.h" | 22 #include "ui/gfx/geometry/size.h" |
| 22 #include "ui/gl/gl_context_cgl.h" | 23 #include "ui/gl/gl_context_cgl.h" |
| 23 | 24 |
| 24 namespace base { | 25 namespace base { |
| 25 class SingleThreadTaskRunner; | 26 class SingleThreadTaskRunner; |
| 26 } // namespace base | 27 } // namespace base |
| 27 | 28 |
| 28 namespace content { | 29 namespace content { |
| 29 | 30 |
| 30 // VideoToolbox.framework implementation of the VideoDecodeAccelerator | 31 // VideoToolbox.framework implementation of the VideoDecodeAccelerator |
| 31 // interface for Mac OS X (currently limited to 10.9+). | 32 // interface for Mac OS X (currently limited to 10.9+). |
| 32 class VTVideoDecodeAccelerator | 33 class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator { |
| 33 : public media::VideoDecodeAccelerator, | |
| 34 public base::NonThreadSafe { | |
| 35 public: | 34 public: |
| 36 explicit VTVideoDecodeAccelerator( | 35 explicit VTVideoDecodeAccelerator( |
| 37 CGLContextObj cgl_context, | 36 CGLContextObj cgl_context, |
| 38 const base::Callback<bool(void)>& make_context_current); | 37 const base::Callback<bool(void)>& make_context_current); |
| 39 ~VTVideoDecodeAccelerator() override; | 38 ~VTVideoDecodeAccelerator() override; |
| 40 | 39 |
| 41 // VideoDecodeAccelerator implementation. | 40 // VideoDecodeAccelerator implementation. |
| 42 bool Initialize(media::VideoCodecProfile profile, Client* client) override; | 41 bool Initialize(media::VideoCodecProfile profile, Client* client) override; |
| 43 void Decode(const media::BitstreamBuffer& bitstream) override; | 42 void Decode(const media::BitstreamBuffer& bitstream) override; |
| 44 void AssignPictureBuffers( | 43 void AssignPictureBuffers( |
| 45 const std::vector<media::PictureBuffer>& pictures) override; | 44 const std::vector<media::PictureBuffer>& pictures) override; |
| 46 void ReusePictureBuffer(int32_t picture_id) override; | 45 void ReusePictureBuffer(int32_t picture_id) override; |
| 47 void Flush() override; | 46 void Flush() override; |
| 48 void Reset() override; | 47 void Reset() override; |
| 49 void Destroy() override; | 48 void Destroy() override; |
| 50 bool CanDecodeOnIOThread() override; | 49 bool CanDecodeOnIOThread() override; |
| 51 | 50 |
| 52 // Called by OutputThunk() when VideoToolbox finishes decoding a frame. | 51 // Called by OutputThunk() when VideoToolbox finishes decoding a frame. |
| 53 void Output( | 52 void Output( |
| 54 int32_t bitstream_id, | 53 void* source_frame_refcon, |
| 55 OSStatus status, | 54 OSStatus status, |
| 56 CVImageBufferRef image_buffer); | 55 CVImageBufferRef image_buffer); |
| 57 | 56 |
| 58 private: | 57 private: |
| 59 struct DecodedFrame { | 58 enum State { |
| 60 DecodedFrame(int32_t bitstream_id, CVImageBufferRef image_buffer); | 59 STATE_NORMAL, |
|
Pawel Osciak
2014/11/12 12:57:30
Maybe DECODING? RUNNING?
sandersd (OOO until July 31)
2014/11/13 00:05:45
Done.
| |
| 61 ~DecodedFrame(); | 60 STATE_DESTROYING, |
| 61 STATE_ERROR, | |
| 62 }; | |
| 63 | |
| 64 enum TaskType { | |
| 65 TASK_FRAME, | |
| 66 TASK_FLUSH, | |
| 67 TASK_RESET, | |
| 68 TASK_DESTROY, | |
| 69 }; | |
| 70 | |
| 71 struct Frame { | |
| 72 Frame(int32_t bitstream_id); | |
| 73 ~Frame(); | |
| 62 | 74 |
| 63 int32_t bitstream_id; | 75 int32_t bitstream_id; |
| 64 base::ScopedCFTypeRef<CVImageBufferRef> image_buffer; | 76 base::ScopedCFTypeRef<CVImageBufferRef> image; |
| 77 // TODO(sandersd): visible_rect. | |
| 78 gfx::Size coded_size; | |
| 65 }; | 79 }; |
| 66 | 80 |
| 67 // Actions are the possible types of pending operations, which are queued | 81 struct Task { |
| 68 // by Flush(), Reset(), and Destroy(). | 82 Task(TaskType type); |
| 69 enum Action { | 83 ~Task(); |
| 70 ACTION_FLUSH, | 84 |
| 71 ACTION_RESET, | 85 TaskType type; |
| 72 ACTION_DESTROY | 86 linked_ptr<Frame> frame; |
| 73 }; | 87 }; |
| 74 | 88 |
| 75 // PendingActions contain the |bitstream_id| of a frame that, once decoded and | 89 // |
| 76 // sent, a particular |action| should be completed at. | 90 // Methods for interacting with VideoToolbox. Run on |decoder_thread_|. |
| 77 struct PendingAction { | 91 // |
| 78 PendingAction(Action action, int32_t bitstream_id); | 92 // Set up VideoToolbox using the current SPS and PPS. Returns true or calls |
| 79 ~PendingAction(); | 93 // NotifyError() before returning false. |
| 94 bool ConfigureDecoder(); | |
| 80 | 95 |
| 81 Action action; | 96 // Wait for VideoToolbox to output all pending frames. Returns true or calls |
| 82 int32_t bitstream_id; | 97 // NotifyError() before returning false. |
| 83 }; | 98 bool FinishDelayedFrames(); |
| 84 | 99 |
| 85 // Methods for interacting with VideoToolbox. Run on |decoder_thread_|. | 100 // |frame| is owned by |pending_frames_|. |
| 86 bool ConfigureDecoder( | 101 void DecodeTask(const media::BitstreamBuffer&, Frame* frame); |
| 87 const std::vector<const uint8_t*>& nalu_data_ptrs, | 102 void DecodeDone(Frame* frame); |
| 88 const std::vector<size_t>& nalu_data_sizes); | |
| 89 void DecodeTask(const media::BitstreamBuffer&); | |
| 90 void FlushTask(); | |
| 91 void DropBitstream(int32_t bitstream_id); | |
| 92 | 103 |
| 104 // | |
| 93 // Methods for interacting with |client_|. Run on |gpu_task_runner_|. | 105 // Methods for interacting with |client_|. Run on |gpu_task_runner_|. |
| 94 void OutputTask(DecodedFrame frame); | 106 // |
| 95 void NotifyError(Error error); | 107 void NotifyError(Error error); |
| 96 | 108 |
| 97 // Send decoded frames up to and including |up_to_bitstream_id|, and return | 109 // |type| is the type of task that the flush will complete, one of TASK_FLUSH, |
| 98 // the last sent |bitstream_id|. | 110 // TASK_RESET, or TASK_DESTROY. |
| 99 int32_t SendPictures(int32_t up_to_bitstream_id); | 111 void QueueFlush(TaskType type); |
| 112 void FlushTask(TaskType type); | |
| 113 void FlushDone(TaskType type); | |
| 100 | 114 |
| 101 // Internal helper for SendPictures(): Drop frames with no image data up to | 115 // Attempt to make progress on |pending_tasks_|. |
| 102 // a particular bitstream ID, so that if there is still a frame in the queue | 116 void ProcessTasks(); |
| 103 // when this function returns, it is guaranteed to have image data, and thus | |
| 104 // it is time to set up the GPU context. Returns the last bitstream ID that | |
| 105 // was dropped, or |last_sent_bitstream_id| if no frames were dropped. | |
| 106 int32_t ProcessDroppedFrames( | |
| 107 int32_t last_sent_bitstream_id, | |
| 108 int32_t up_to_bitstream_id); | |
| 109 | 117 |
| 110 // Internal helper for SendPictures(): Check if the next frame has a size | 118 // These methods returns true if the task was completed, false if it couldn't |
| 111 // different from the current picture buffers, and request new ones if so. | 119 // be completed yet. |
| 112 void ProcessSizeChangeIfNeeded(); | 120 bool ProcessTask(const Task& task); |
| 113 | 121 bool ProcessFrame(const Frame& frame); |
| 114 // Since VideoToolbox has no reset feature (only flush), and the VDA API | 122 bool SendFrame(const Frame& frame); |
| 115 // allows Decode() and Flush() calls during a reset operation, it's possible | |
| 116 // to have multiple pending actions at once. We handle the fully general case | |
| 117 // of an arbitrary sequence of pending actions (in reality, there should | |
| 118 // probably be at most one reset and one flush at a time). | |
| 119 void QueueAction(Action action); | |
| 120 | |
| 121 // Process queued decoded frames, usually by sending them (unless there | |
| 122 // is a pending ACTION_RESET or ACTION_DESTROY, in which case they are | |
| 123 // dropped), completing queued actions along the way. | |
| 124 void ProcessDecodedFrames(); | |
| 125 | |
| 126 // Complete a particular action, by eg. calling NotifyFlushDone(). | |
| 127 // Warning: Deletes |this| if |action| is ACTION_DESTROY. | |
| 128 void CompleteAction(Action action); | |
| 129 | |
| 130 // Complete all actions pending for a particular |bitstream_id|. | |
| 131 // Warning: Do not call if there is a pending ACTION_DESTROY. | |
| 132 void CompleteActions(int32_t bitstream_id); | |
| 133 | 123 |
| 134 // | 124 // |
| 135 // GPU thread state. | 125 // GPU thread state. |
| 136 // | 126 // |
| 137 CGLContextObj cgl_context_; | 127 CGLContextObj cgl_context_; |
| 138 base::Callback<bool(void)> make_context_current_; | 128 base::Callback<bool(void)> make_context_current_; |
| 139 media::VideoDecodeAccelerator::Client* client_; | 129 media::VideoDecodeAccelerator::Client* client_; |
| 130 State state_; | |
| 140 | 131 |
| 141 // client_->NotifyError() called. | 132 // Queue of pending flush tasks. This is used to drop frames when a reset |
| 142 bool has_error_; | 133 // is pending. |
| 134 std::queue<TaskType> pending_flush_tasks_; | |
| 135 | |
| 136 // Queue of tasks to complete in the GPU thread. | |
| 137 std::queue<Task> pending_tasks_; | |
| 143 | 138 |
| 144 // Size of assigned picture buffers. | 139 // Size of assigned picture buffers. |
| 145 gfx::Size picture_size_; | 140 gfx::Size picture_size_; |
| 146 | 141 |
| 147 // Queue of actions so that we can quickly discover what the next action will | 142 // Queue of frames that have not yet been decoded; maintains ownership of the |
| 148 // be; this is useful because we are dropping all frames when the next action | 143 // Frame objects while they flow through VideoToolbox. |
| 149 // is ACTION_RESET or ACTION_DESTROY. | 144 std::queue<linked_ptr<Frame>> pending_frames_; |
| 150 std::queue<PendingAction> pending_actions_; | |
| 151 | 145 |
| 152 // Queue of bitstreams that have not yet been decoded. This is mostly needed | 146 // Set of assigned bitstream IDs, so that Destroy() can release them all. |
| 153 // to be sure we free them all in Destroy(). | 147 std::set<int32_t> assigned_bitstream_ids_; |
| 154 std::queue<int32_t> pending_bitstream_ids_; | |
| 155 | 148 |
| 156 // All picture buffers assigned to us. Used to check if reused picture buffers | 149 // All picture buffers assigned to us. Used to check if reused picture buffers |
| 157 // should be added back to the available list or released. (They are not | 150 // should be added back to the available list or released. (They are not |
| 158 // released immediately because we need the reuse event to free the binding.) | 151 // released immediately because we need the reuse event to free the binding.) |
| 159 std::set<int32_t> assigned_picture_ids_; | 152 std::set<int32_t> assigned_picture_ids_; |
| 160 | 153 |
| 161 // Texture IDs of assigned pictures. | 154 // Texture IDs of assigned pictures. |
| 162 std::map<int32_t, uint32_t> texture_ids_; | 155 std::map<int32_t, uint32_t> texture_ids_; |
| 163 | 156 |
| 164 // Pictures ready to be rendered to. | 157 // Pictures ready to be rendered to. |
| 165 std::vector<int32_t> available_picture_ids_; | 158 std::vector<int32_t> available_picture_ids_; |
| 166 | 159 |
| 167 // Decoded frames ready to render. | |
| 168 std::queue<DecodedFrame> decoded_frames_; | |
| 169 | |
| 170 // Image buffers kept alive while they are bound to pictures. | 160 // Image buffers kept alive while they are bound to pictures. |
| 171 std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_; | 161 std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_; |
| 172 | 162 |
| 173 // | 163 // |
| 174 // Decoder thread state. | 164 // Decoder thread state. |
| 175 // | 165 // |
| 176 VTDecompressionOutputCallbackRecord callback_; | 166 VTDecompressionOutputCallbackRecord callback_; |
| 177 base::ScopedCFTypeRef<CMFormatDescriptionRef> format_; | 167 base::ScopedCFTypeRef<CMFormatDescriptionRef> format_; |
| 178 base::ScopedCFTypeRef<VTDecompressionSessionRef> session_; | 168 base::ScopedCFTypeRef<VTDecompressionSessionRef> session_; |
| 179 media::H264Parser parser_; | 169 media::H264Parser parser_; |
| 170 gfx::Size coded_size_; | |
| 180 | 171 |
| 181 std::vector<uint8_t> last_sps_; | 172 std::vector<uint8_t> last_sps_; |
| 182 std::vector<uint8_t> last_spsext_; | 173 std::vector<uint8_t> last_spsext_; |
| 183 std::vector<uint8_t> last_pps_; | 174 std::vector<uint8_t> last_pps_; |
| 184 | 175 |
| 185 // | 176 // |
| 186 // Shared state (set up and torn down on GPU thread). | 177 // Shared state (set up and torn down on GPU thread). |
| 187 // | 178 // |
| 179 base::ThreadChecker gpu_thread_checker_; | |
| 188 scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; | 180 scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; |
| 189 | 181 |
| 190 // This WeakPtrFactory does not need to be last as its pointers are bound to | 182 // This WeakPtrFactory does not need to be last as its pointers are bound to |
| 191 // the same thread it is destructed on (the GPU thread). | 183 // the same thread it is destructed on (the GPU thread). |
| 192 base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_; | 184 base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_; |
| 193 | 185 |
| 194 // Declared last to ensure that all decoder thread tasks complete before any | 186 // Declared last to ensure that all decoder thread tasks complete before any |
| 195 // state is destructed. | 187 // state is destructed. |
| 196 base::Thread decoder_thread_; | 188 base::Thread decoder_thread_; |
| 197 | 189 |
| 198 DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator); | 190 DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator); |
| 199 }; | 191 }; |
| 200 | 192 |
| 201 } // namespace content | 193 } // namespace content |
| 202 | 194 |
| 203 #endif // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ | 195 #endif // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ |
| OLD | NEW |