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 "content/common/gpu/media/vt.h" | 18 #include "content/common/gpu/media/vt.h" |
| 19 #include "media/filters/h264_parser.h" | 19 #include "media/filters/h264_parser.h" |
| 20 #include "media/video/video_decode_accelerator.h" | 20 #include "media/video/video_decode_accelerator.h" |
| 21 #include "ui/gfx/geometry/size.h" | 21 #include "ui/gfx/geometry/size.h" |
| 22 #include "ui/gl/gl_context_cgl.h" | 22 #include "ui/gl/gl_context_cgl.h" |
| 23 | 23 |
| 24 namespace base { | 24 namespace base { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 44 void AssignPictureBuffers( | 44 void AssignPictureBuffers( |
| 45 const std::vector<media::PictureBuffer>& pictures) override; | 45 const std::vector<media::PictureBuffer>& pictures) override; |
| 46 void ReusePictureBuffer(int32_t picture_id) override; | 46 void ReusePictureBuffer(int32_t picture_id) override; |
| 47 void Flush() override; | 47 void Flush() override; |
| 48 void Reset() override; | 48 void Reset() override; |
| 49 void Destroy() override; | 49 void Destroy() override; |
| 50 bool CanDecodeOnIOThread() override; | 50 bool CanDecodeOnIOThread() override; |
| 51 | 51 |
| 52 // Called by OutputThunk() when VideoToolbox finishes decoding a frame. | 52 // Called by OutputThunk() when VideoToolbox finishes decoding a frame. |
| 53 void Output( | 53 void Output( |
| 54 int32_t bitstream_id, | 54 void* source_frame_refcon, |
| 55 OSStatus status, | 55 OSStatus status, |
| 56 CVImageBufferRef image_buffer); | 56 CVImageBufferRef image_buffer); |
| 57 | 57 |
| 58 private: | 58 private: |
| 59 struct DecodedFrame { | 59 enum State { |
| 60 DecodedFrame(int32_t bitstream_id, CVImageBufferRef image_buffer); | 60 STATE_NORMAL, |
| 61 ~DecodedFrame(); | 61 STATE_DESTROYING, |
| 62 STATE_ERROR, | |
| 63 }; | |
| 64 | |
| 65 enum TaskType { | |
| 66 TASK_FRAME, | |
| 67 TASK_FLUSH, | |
| 68 TASK_RESET, | |
| 69 TASK_DESTROY, | |
| 70 }; | |
| 71 | |
| 72 struct Frame { | |
| 73 Frame(int32_t bitstream_id); | |
| 74 ~Frame(); | |
| 62 | 75 |
| 63 int32_t bitstream_id; | 76 int32_t bitstream_id; |
| 64 base::ScopedCFTypeRef<CVImageBufferRef> image_buffer; | 77 base::ScopedCFTypeRef<CVImageBufferRef> image; |
| 78 // TODO(sandersd): visible_rect. | |
| 79 gfx::Size coded_size; | |
| 65 }; | 80 }; |
| 66 | 81 |
| 67 // Actions are the possible types of pending operations, which are queued | 82 struct Task { |
| 68 // by Flush(), Reset(), and Destroy(). | 83 Task(TaskType type); |
| 69 enum Action { | 84 ~Task(); |
| 70 ACTION_FLUSH, | 85 |
| 71 ACTION_RESET, | 86 TaskType type; |
| 72 ACTION_DESTROY | 87 linked_ptr<Frame> frame; |
| 73 }; | 88 }; |
| 74 | 89 |
| 75 // PendingActions contain the |bitstream_id| of a frame that, once decoded and | 90 // |
| 76 // sent, a particular |action| should be completed at. | 91 // Methods for interacting with VideoToolbox. Run on |decoder_thread_|. |
| 77 struct PendingAction { | 92 // |
| 78 PendingAction(Action action, int32_t bitstream_id); | 93 // Set up VideoToolbox using the current SPS and PPS. Returns true or calls |
| 79 ~PendingAction(); | 94 // NotifyError() before returning false. |
| 95 bool ConfigureDecoder(); | |
| 80 | 96 |
| 81 Action action; | 97 // Wait for VideoToolbox to output all pending frames. Returns true or calls |
| 82 int32_t bitstream_id; | 98 // NotifyError() before returning false. |
| 83 }; | 99 bool FinishDelayedFrames(); |
| 84 | 100 |
| 85 // Methods for interacting with VideoToolbox. Run on |decoder_thread_|. | 101 // |frame| is owned by |pending_frames_|. |
| 86 bool ConfigureDecoder( | 102 void DecodeTask(const media::BitstreamBuffer&, Frame* frame); |
| 87 const std::vector<const uint8_t*>& nalu_data_ptrs, | 103 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 | 104 |
| 105 // | |
| 93 // Methods for interacting with |client_|. Run on |gpu_task_runner_|. | 106 // Methods for interacting with |client_|. Run on |gpu_task_runner_|. |
| 94 void OutputTask(DecodedFrame frame); | 107 // |
| 95 void NotifyError(Error error); | 108 void NotifyError(Error error); |
| 96 | 109 |
| 97 // Send decoded frames up to and including |up_to_bitstream_id|, and return | 110 // |type| is the type of task that the flush will complete, one of TASK_FLUSH, |
| 98 // the last sent |bitstream_id|. | 111 // TASK_RESET, or TASK_DESTROY. |
| 99 int32_t SendPictures(int32_t up_to_bitstream_id); | 112 void QueueFlush(TaskType type); |
| 113 void FlushTask(TaskType type); | |
| 114 void FlushDone(TaskType type); | |
| 100 | 115 |
| 101 // Internal helper for SendPictures(): Drop frames with no image data up to | 116 // Attempt to make progress on |pending_tasks_|. |
| 102 // a particular bitstream ID, so that if there is still a frame in the queue | 117 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 | 118 |
| 110 // Internal helper for SendPictures(): Check if the next frame has a size | 119 // 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. | 120 // be completed yet. |
| 112 void ProcessSizeChange(); | 121 bool ProcessTask(const Task& task); |
| 113 | 122 bool ProcessFrame(const Frame& frame); |
| 114 // Since VideoToolbox has no reset feature (only flush), and the VDA API | 123 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 | 124 |
| 134 // | 125 // |
| 135 // GPU thread state. | 126 // GPU thread state. |
| 136 // | 127 // |
| 137 CGLContextObj cgl_context_; | 128 CGLContextObj cgl_context_; |
| 138 base::Callback<bool(void)> make_context_current_; | 129 base::Callback<bool(void)> make_context_current_; |
| 139 media::VideoDecodeAccelerator::Client* client_; | 130 media::VideoDecodeAccelerator::Client* client_; |
| 131 State state_; | |
| 140 | 132 |
| 141 // client_->NotifyError() called. | 133 // Queue of pending flush tasks. This is used to drop frames when a reset |
| 142 bool has_error_; | 134 // is pending. |
| 135 std::queue<TaskType> pending_flush_tasks_; | |
| 136 | |
| 137 // Queue of tasks to complete in the GPU thread. | |
| 138 std::queue<Task> pending_tasks_; | |
| 143 | 139 |
| 144 // Size of assigned picture buffers. | 140 // Size of assigned picture buffers. |
| 145 gfx::Size picture_size_; | 141 gfx::Size picture_size_; |
| 146 | 142 |
| 147 // Queue of actions so that we can quickly discover what the next action will | 143 // 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 | 144 // Frame objects while they flow through VideoToolbox. |
| 149 // is ACTION_RESET or ACTION_DESTROY. | 145 std::queue<linked_ptr<Frame>> pending_frames_; |
|
DaleCurtis
2014/11/10 21:10:39
Why queue vs vector ==> ScopedVector instead of li
sandersd (OOO until July 31)
2014/11/11 18:46:07
The short answer is that it makes moving ownership
| |
| 150 std::queue<PendingAction> pending_actions_; | |
| 151 | 146 |
| 152 // Queue of bitstreams that have not yet been decoded. This is mostly needed | 147 // Set of assigned bitstream IDs, so that Destroy() can release them all. |
| 153 // to be sure we free them all in Destroy(). | 148 std::set<int32_t> assigned_bitstream_ids_; |
| 154 std::queue<int32_t> pending_bitstream_ids_; | |
| 155 | 149 |
| 156 // All picture buffers assigned to us. Used to check if reused picture buffers | 150 // 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 | 151 // 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.) | 152 // released immediately because we need the reuse event to free the binding.) |
| 159 std::set<int32_t> assigned_picture_ids_; | 153 std::set<int32_t> assigned_picture_ids_; |
| 160 | 154 |
| 161 // Texture IDs of assigned pictures. | 155 // Texture IDs of assigned pictures. |
| 162 std::map<int32_t, uint32_t> texture_ids_; | 156 std::map<int32_t, uint32_t> texture_ids_; |
| 163 | 157 |
| 164 // Pictures ready to be rendered to. | 158 // Pictures ready to be rendered to. |
| 165 std::vector<int32_t> available_picture_ids_; | 159 std::vector<int32_t> available_picture_ids_; |
| 166 | 160 |
| 167 // Decoded frames ready to render. | |
| 168 std::queue<DecodedFrame> decoded_frames_; | |
| 169 | |
| 170 // Image buffers kept alive while they are bound to pictures. | 161 // Image buffers kept alive while they are bound to pictures. |
| 171 std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_; | 162 std::map<int32_t, base::ScopedCFTypeRef<CVImageBufferRef>> picture_bindings_; |
| 172 | 163 |
| 173 // | 164 // |
| 174 // Decoder thread state. | 165 // Decoder thread state. |
| 175 // | 166 // |
| 176 VTDecompressionOutputCallbackRecord callback_; | 167 VTDecompressionOutputCallbackRecord callback_; |
| 177 base::ScopedCFTypeRef<CMFormatDescriptionRef> format_; | 168 base::ScopedCFTypeRef<CMFormatDescriptionRef> format_; |
| 178 base::ScopedCFTypeRef<VTDecompressionSessionRef> session_; | 169 base::ScopedCFTypeRef<VTDecompressionSessionRef> session_; |
| 179 media::H264Parser parser_; | 170 media::H264Parser parser_; |
| 171 gfx::Size coded_size_; | |
| 180 | 172 |
| 181 std::vector<uint8_t> last_sps_; | 173 std::vector<uint8_t> last_sps_; |
| 182 std::vector<uint8_t> last_spsext_; | 174 std::vector<uint8_t> last_spsext_; |
| 183 std::vector<uint8_t> last_pps_; | 175 std::vector<uint8_t> last_pps_; |
| 184 | 176 |
| 185 // | 177 // |
| 186 // Shared state (set up and torn down on GPU thread). | 178 // Shared state (set up and torn down on GPU thread). |
| 187 // | 179 // |
| 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 |