OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_ | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
TODO+crbug to add a vea_test.
| |
6 #define CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_ | |
7 | |
8 #include <list> | |
9 #include <vector> | |
10 | |
11 #include "base/callback_forward.h" | |
12 #include "base/memory/linked_ptr.h" | |
13 #include "base/memory/weak_ptr.h" | |
14 #include "base/threading/thread.h" | |
15 #include "content/common/gpu/gl_surface_encoder.h" | |
16 #include "media/base/video_decoder_config.h" | |
17 #include "media/video/video_encode_accelerator.h" | |
18 #include "ui/gfx/size.h" | |
19 #include "ui/gl/gl_bindings.h" | |
20 | |
21 namespace base { | |
22 | |
23 class MessageLoopProxy; | |
24 | |
25 } // namespace base | |
26 | |
27 namespace gfx { | |
28 | |
29 class GLSurface; | |
30 | |
31 } // namespace gfx | |
32 | |
33 namespace media { | |
34 | |
35 class BitstreamBuffer; | |
36 | |
37 } // namespace media | |
38 | |
39 namespace content { | |
40 | |
41 // This class handles Exynos video encode acceleration by interfacing with the | |
42 // V4L2 devices exported by the Multi Format Codec and GScaler hardware blocks | |
43 // on the Exynos platform. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
Can this be V4L2VEA instead of ExynosVEA?
(what ex
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
sanity check: no dlopen/dlsym's necessary for enco
| |
44 // | |
45 // The threading model of this class is the same as the | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
Much like EVDA IWBN to have the poll thread replac
| |
46 // ExynosVideoDecodeAccelerator (from which class this was designed). The one | |
47 // notable difference is in the thread "ownership" of the GSC free input buffers | |
48 // queue (gsc_free_input_buffers_). As this queue needs to be queried and | |
49 // dequeued from the child thread (to obtain a texture to copy the backbuffer | |
50 // to in Encode()), it is owned by the child thread. | |
51 class ExynosVideoEncodeAccelerator : public media::VideoEncodeAccelerator { | |
52 public: | |
53 ExynosVideoEncodeAccelerator( | |
54 EGLDisplay egl_display, | |
55 media::VideoEncodeAccelerator::Client* client, | |
56 const base::Callback<bool(void)>& make_context_current, | |
57 bool encode_from_backbuffer); | |
58 ~ExynosVideoEncodeAccelerator(); | |
59 | |
60 // media::VideoEncodeAccelerator implementation. | |
61 virtual void Initialize(media::VideoCodecProfile profile, | |
62 const gfx::Size& input_resolution, | |
Pawel Osciak
2013/06/17 23:21:56
Do you know if the codec supports in-flight resolu
| |
63 const gfx::Size& output_resolution, | |
64 int32 initial_bitrate) OVERRIDE; | |
65 virtual void Encode( | |
66 const scoped_refptr<media::VideoFrame>& frame, | |
67 int32 frame_id, | |
68 bool force_keyframe) OVERRIDE; | |
69 virtual void UseBitstreamBuffer( | |
70 const media::BitstreamBuffer& buffer) OVERRIDE; | |
71 virtual void RequestEncodingParameterChange(int32 bitrate) OVERRIDE; | |
72 virtual void Destroy() OVERRIDE; | |
73 | |
74 private: | |
75 // Auto-destroy reference for BitstreamBuffer, for tracking buffers passed as | |
76 // input to UseBitstreamBuffer. | |
77 struct BitstreamBufferRef; | |
78 | |
79 // Record for GSC input buffers. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
:'( for GSC staying in our lives. I take it there
| |
80 struct GscInputRecord { | |
81 GscInputRecord(); | |
82 bool at_device; | |
83 int frame_id; | |
84 EGLSyncKHR egl_sync; | |
85 EGLImageKHR egl_image; | |
86 GLuint texture_id; | |
87 void* address; | |
88 size_t length; | |
89 }; | |
90 | |
91 // Record for GSC output buffers. | |
92 struct GscOutputRecord { | |
93 GscOutputRecord(); | |
94 bool at_device; | |
95 int mfc_input; | |
96 void* address[3]; | |
97 size_t length[3]; | |
98 size_t bytes_used[3]; | |
99 }; | |
100 | |
101 // Record for MFC input buffers. | |
102 struct MfcInputRecord { | |
103 MfcInputRecord(); | |
104 bool at_device; | |
105 int fd[2]; | |
106 }; | |
107 | |
108 // Record for MFC output buffers. | |
109 struct MfcOutputRecord { | |
110 MfcOutputRecord(); | |
111 bool at_device; | |
112 void* address; | |
113 size_t length; | |
114 size_t bytes_used; | |
115 }; | |
116 | |
117 enum { | |
118 // These are rather subjectively tuned. | |
119 kGscInputBufferCount = 2, | |
120 kGscOutputBufferCount = 2, | |
121 kMfcOutputBufferCount = 3, | |
122 // MFC hardware does not report required output buffer size correctly. | |
123 // Use maximum theoretical size to avoid hanging the hardware. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
TODO/crbug pointer
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
What theory makes 2MB the "max theoretical size"?
| |
124 kMfcOutputBufferSize = (2 * 1024 * 1024), | |
125 }; | |
126 | |
127 // Internal state of the encoder. | |
128 enum State { | |
129 kUninitialized, // Initialize() not yet called. | |
130 kInitialized, // Initialize() returned true; ready to start decoding. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
"decoding"
| |
131 kEncoding, // Encoding frames. | |
132 kError, // Error in kEncoding state. | |
133 }; | |
134 | |
135 // File descriptors we need to poll. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
Reword to avoid implying that the actual FDs are 0
| |
136 enum PollFds { | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
can live in the .cc file
| |
137 kPollGsc = (1 << 0), | |
138 kPollMfc = (1 << 1), | |
139 }; | |
140 | |
141 // | |
142 // Child thread utility functions, supporting API entry points. | |
143 // | |
144 | |
145 // Return a buffer to gsc_free_input_buffers_. | |
146 void ReturnFreeGscInputBuffer(int index); | |
147 | |
148 // | |
149 // Decoding tasks, to be run on encode_thread_. | |
Pawel Osciak
2013/06/17 23:21:56
s/encode_thread_/encoder_thread_/
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
lol Decoding...encode...
| |
150 // | |
151 | |
152 // Encode a GSC input buffer. | |
153 void EncodeTask(int gsc_input_index); | |
154 | |
155 // Copy a media::VideoFrame to the GSC input buffer, then encode it. | |
156 void CopyFrameAndEncodeTask(const scoped_refptr<media::VideoFrame>& frame, | |
157 int gsc_input_index); | |
158 | |
159 // Add a BitstreamBuffer to out queue of buffers ready to be used for client | |
160 // output. | |
161 void UseBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref); | |
162 | |
163 // Device destruction task. | |
164 void DestroyTask(); | |
165 | |
166 // Service I/O on the V4L2 devices. This task should only be scheduled from | |
167 // DevicePollTask(). | |
168 void ServiceDeviceTask(); | |
169 // Handle the various device queues. | |
170 void EnqueueGsc(); | |
171 void DequeueGsc(); | |
172 void EnqueueMfc(); | |
173 void DequeueMfc(); | |
174 // Enqueue a buffer on the corresponding queue. | |
175 bool EnqueueGscInputRecord(); | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
here and below, doco that a false return means fat
| |
176 bool EnqueueGscOutputRecord(); | |
177 bool EnqueueMfcInputRecord(); | |
178 bool EnqueueMfcOutputRecord(); | |
179 // Return completed buffers to the client. | |
Pawel Osciak
2013/06/17 23:21:56
Doco which buffers (bitstream buffers)?
| |
180 void ReturnCompleteBuffers(); | |
181 | |
182 // Attempt to start/stop device_poll_thread_. | |
183 bool StartDevicePoll(); | |
184 bool StopDevicePoll(); | |
185 // Set/clear the device poll interrupt (using device_ooll_interrupt_fd_). | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
typo: ooll
| |
186 bool SetDevicePollInterrupt(); | |
187 bool ClearDevicePollInterrupt(); | |
188 | |
189 // | |
190 // Device tasks, to be run on device_poll_thread_. | |
191 // | |
192 | |
193 // The device task. | |
194 void DevicePollTask(unsigned int poll_fds); | |
195 | |
196 // | |
197 // Safe from any thread. | |
198 // | |
199 | |
200 // Error notification (using PostTask() to child thread, if necessary). | |
201 void NotifyError(Error error); | |
202 | |
203 // Set the encoder_thread_ state (using PostTask to encoder thread, if | |
204 // necessary). | |
205 void SetEncoderState(State state); | |
206 | |
207 // | |
208 // Other utility functions. Called on encoder_thread_, unless | |
209 // encoder_thread_ is not yet started, in which case the child thread can call | |
210 // these (e.g. in Initialize() or Destroy()). | |
211 // | |
212 | |
213 // Create the buffers we need. | |
214 bool CreateGscInputBuffers(); | |
215 bool CreateGscOutputBuffers(); | |
216 bool SetMfcFormats(); | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
Not really "creat[ing] the buffers we need".
| |
217 bool CreateMfcInputBuffers(); | |
218 bool CreateMfcOutputBuffers(); | |
219 | |
220 // Set encoding parameters. | |
221 void SetBitrate(int32 bitrate); | |
222 | |
223 // Destroy these buffers. | |
224 void DestroyGscInputBuffers(); | |
225 void DestroyGscOutputBuffers(); | |
226 void DestroyMfcInputBuffers(); | |
227 void DestroyMfcOutputBuffers(); | |
228 | |
229 // Our original calling message loop for the child thread. | |
230 const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_; | |
231 | |
232 // WeakPtr<> pointing to |this| for use in posting tasks from the encoder or | |
233 // device worker threads back to the child thread. Because the worker threads | |
234 // are members of this class, any task running on those threads is guaranteed | |
235 // that this object is still alive. As a result, tasks posted from the child | |
236 // thread to the encoder or device thread should use base::Unretained(this), | |
237 // and tasks posted the other way should use |weak_this_|. | |
238 base::WeakPtrFactory<ExynosVideoEncodeAccelerator> weak_this_ptr_factory_; | |
239 base::WeakPtr<ExynosVideoEncodeAccelerator> weak_this_; | |
240 | |
241 // To expose client callbacks from VideoEncodeAccelerator. | |
242 // NOTE: all calls to these objects *MUST* be executed on | |
243 // child_message_loop_proxy_. | |
244 base::WeakPtrFactory<Client> client_ptr_factory_; | |
245 base::WeakPtr<Client> client_; | |
246 | |
247 // | |
248 // Encoder state, owned and operated by encoder_thread_. | |
249 // Before encoder_thread_ has started, the encoder state is managed by | |
250 // the child (main) thread. After encoder_thread_ has started, the encoder | |
251 // thread should be the only one managing these. | |
252 // | |
253 | |
254 // This thread services tasks posted from the VEA API entry points by the | |
255 // child thread and device service callbacks posted from the device thread. | |
256 base::Thread encoder_thread_; | |
257 // Encoder state machine state. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
There's no explicit "machine" so drop "machine st
| |
258 State encoder_state_; | |
259 // The visible/allocated sizes of the input frame. | |
260 gfx::Size input_visible_size_; | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
"visible" is usually a Rect, not a Size, and it ca
| |
261 gfx::Size input_allocated_size_; | |
262 // The visible/allocated sizes of the color-converted frame. | |
263 gfx::Size converted_visible_size_; | |
Pawel Osciak
2013/06/17 23:21:56
Perhaps I'm misunderstanding the intentions here,
| |
264 gfx::Size converted_allocated_size_; | |
265 // The visible/allocated sizes of the output frame. | |
266 gfx::Size output_visible_size_; | |
267 // The required byte size of output BitstreamBuffers. | |
268 size_t output_buffer_byte_size_; | |
269 | |
270 // Bitstream buffers ready to be used to return encoded output. | |
271 std::vector<linked_ptr<BitstreamBufferRef> > encoder_bitstream_buffers_; | |
272 | |
273 // Buffers ready to be encoded. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
Here and elsewhere, doco what the int is an index
| |
274 std::list<int> encoder_input_queue_; | |
275 | |
276 // Encoded buffers ready to return to the client. | |
277 std::list<int> encoder_output_queue_; | |
278 | |
279 // Flag if we are encoding the output (and using MFC). | |
Pawel Osciak
2013/06/17 23:21:56
In what scenario we'd not want to encode? Is this
| |
280 bool do_output_encoding_; | |
281 | |
282 // Flag if we are encoding from the backbuffer (instead of a CPU allocation). | |
283 const bool do_encode_from_backbuffer_; | |
284 | |
285 // GSC color conversion device. | |
286 int gsc_fd_; | |
287 // GSC input buffer state. | |
288 bool gsc_input_streamon_; | |
289 // GSC input buffers enqueued to device. | |
290 int gsc_input_buffer_queued_count_; | |
291 // Mapping of int index to GSC input buffer record. | |
292 std::vector<GscInputRecord> gsc_input_buffer_map_; | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
s/_map_/s_/ and similarly update comment since thi
| |
293 | |
294 // GSC output buffer state. | |
295 bool gsc_output_streamon_; | |
296 // GSC output buffers enqueued to device. | |
297 int gsc_output_buffer_queued_count_; | |
298 // Output buffers ready to use, as a LIFO since we don't care about ordering. | |
299 std::vector<int> gsc_free_output_buffers_; | |
300 // Mapping of int index to GSC output buffer record. | |
301 std::vector<GscOutputRecord> gsc_output_buffer_map_; | |
302 | |
303 // Completed GSC outputs, waiting for GSC. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
lolwat?
| |
304 std::list<int> gsc_output_mfc_input_queue_; | |
Pawel Osciak
2013/06/17 23:21:56
s/waiting for GSC/waiting for MFC/ ?
| |
305 | |
306 // MFC video encoding device. | |
307 int mfc_fd_; | |
308 | |
309 // MFC input buffer state. | |
310 bool mfc_input_streamon_; | |
311 // MFC input buffers enqueued to device. | |
312 int mfc_input_buffer_queued_count_; | |
313 // Input buffers ready to use, as a LIFO since we don't care about ordering. | |
314 std::vector<int> mfc_free_input_buffers_; | |
315 // Mapping of int index to MFC input buffer record. | |
316 std::vector<MfcInputRecord> mfc_input_buffer_map_; | |
317 | |
318 // MFC output buffer state. | |
319 bool mfc_output_streamon_; | |
320 // MFC output buffers enqueued to device. | |
321 int mfc_output_buffer_queued_count_; | |
322 // Output buffers ready to use, as a LIFO since we don't care about ordering. | |
323 std::vector<int> mfc_free_output_buffers_; | |
324 // Mapping of int index to MFC output buffer record. | |
325 std::vector<MfcOutputRecord> mfc_output_buffer_map_; | |
326 | |
327 // | |
328 // The device polling thread handles notifications of V4L2 device changes. | |
329 // | |
330 | |
331 // The thread. | |
332 base::Thread device_poll_thread_; | |
333 // eventfd fd to signal device poll thread when its poll() should be | |
334 // interrupted. | |
335 int device_poll_interrupt_fd_; | |
336 | |
337 // | |
338 // Other state, held by child (main) thread. | |
339 // | |
340 | |
341 // Make our context current before running any EGL entry points. | |
342 base::Callback<bool(void)> make_context_current_; | |
343 | |
344 // Input buffers ready to use, as a LIFO since we don't care about ordering. | |
345 std::vector<int> gsc_free_input_buffers_; | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
This is both read & written on both the child thre
| |
346 | |
347 // EGL state | |
348 const EGLDisplay egl_display_; | |
349 | |
350 // The codec we'll be decoding for. | |
Ami GONE FROM CHROMIUM
2013/06/18 01:09:25
encoding
| |
351 media::VideoCodecProfile video_profile_; | |
352 }; | |
353 | |
354 } // namespace content | |
355 | |
356 #endif // CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_ | |
OLD | NEW |