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_DECODING, |
61 ~DecodedFrame(); | 60 STATE_ERROR, |
| 61 STATE_DESTROYING, |
| 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 // |
188 scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; | 179 scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_; |
| 180 base::ThreadChecker gpu_thread_checker_; |
| 181 base::WeakPtr<VTVideoDecodeAccelerator> weak_this_; |
| 182 base::Thread decoder_thread_; |
189 | 183 |
190 // This WeakPtrFactory does not need to be last as its pointers are bound to | 184 // Declared last to ensure that all weak pointers are invalidated before |
191 // the same thread it is destructed on (the GPU thread). | 185 // other destructors run. |
192 base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_; | 186 base::WeakPtrFactory<VTVideoDecodeAccelerator> weak_this_factory_; |
193 | 187 |
194 // Declared last to ensure that all decoder thread tasks complete before any | |
195 // state is destructed. | |
196 base::Thread decoder_thread_; | |
197 | |
198 DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator); | 188 DISALLOW_COPY_AND_ASSIGN(VTVideoDecodeAccelerator); |
199 }; | 189 }; |
200 | 190 |
201 } // namespace content | 191 } // namespace content |
202 | 192 |
203 #endif // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ | 193 #endif // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_DECODE_ACCELERATOR_H_ |
OLD | NEW |