Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: content/common/gpu/media/exynos_video_decode_accelerator.h

Issue 122233002: vda: Rename Exynos VDA to V4L2 VDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | content/common/gpu/media/exynos_video_decode_accelerator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4 //
5 // This file contains an implementation of VideoDecoderAccelerator
6 // that utilizes the hardware video decoder present on the Exynos SoC.
7
8 #ifndef CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_DECODE_ACCELERATOR_H_
9 #define CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_DECODE_ACCELERATOR_H_
10
11 #include <queue>
12 #include <vector>
13
14 #include "base/callback_forward.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/threading/thread.h"
18 #include "content/common/content_export.h"
19 #include "content/common/gpu/media/video_decode_accelerator_impl.h"
20 #include "media/base/limits.h"
21 #include "media/base/video_decoder_config.h"
22 #include "media/video/picture.h"
23 #include "ui/gfx/size.h"
24 #include "ui/gl/gl_bindings.h"
25
26 namespace base {
27 class MessageLoopProxy;
28 }
29
30 namespace content {
31 class H264Parser;
32
33 // This class handles Exynos video acceleration directly through the V4L2
34 // device exported by the Multi Format Codec hardware block.
35 //
36 // The threading model of this class is driven by the fact that it needs to
37 // interface two fundamentally different event queues -- the one Chromium
38 // provides through MessageLoop, and the one driven by the V4L2 devices which
39 // is waited on with epoll(). There are three threads involved in this class:
40 //
41 // * The child thread, which is the main GPU process thread which calls the
42 // media::VideoDecodeAccelerator entry points. Calls from this thread
43 // generally do not block (with the exception of Initialize() and Destroy()).
44 // They post tasks to the decoder_thread_, which actually services the task
45 // and calls back when complete through the
46 // media::VideoDecodeAccelerator::Client interface.
47 // * The decoder_thread_, owned by this class. It services API tasks, through
48 // the *Task() routines, as well as V4L2 device events, through
49 // ServiceDeviceTask(). Almost all state modification is done on this thread.
50 // * The device_poll_thread_, owned by this class. All it does is epoll() on
51 // the V4L2 in DevicePollTask() and schedule a ServiceDeviceTask() on the
52 // decoder_thread_ when something interesting happens.
53 // TODO(sheu): replace this thread with an TYPE_IO decoder_thread_.
54 //
55 // Note that this class has no locks! Everything's serviced on the
56 // decoder_thread_, so there are no synchronization issues.
57 // ... well, there are, but it's a matter of getting messages posted in the
58 // right order, not fiddling with locks.
59 class CONTENT_EXPORT ExynosVideoDecodeAccelerator
60 : public VideoDecodeAcceleratorImpl {
61 public:
62 ExynosVideoDecodeAccelerator(
63 EGLDisplay egl_display,
64 Client* client,
65 const base::WeakPtr<Client>& io_client_,
66 const base::Callback<bool(void)>& make_context_current,
67 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy);
68 virtual ~ExynosVideoDecodeAccelerator();
69
70 // media::VideoDecodeAccelerator implementation.
71 // Note: Initialize() and Destroy() are synchronous.
72 virtual bool Initialize(media::VideoCodecProfile profile) OVERRIDE;
73 virtual void Decode(const media::BitstreamBuffer& bitstream_buffer) OVERRIDE;
74 virtual void AssignPictureBuffers(
75 const std::vector<media::PictureBuffer>& buffers) OVERRIDE;
76 virtual void ReusePictureBuffer(int32 picture_buffer_id) OVERRIDE;
77 virtual void Flush() OVERRIDE;
78 virtual void Reset() OVERRIDE;
79 virtual void Destroy() OVERRIDE;
80
81 // VideoDecodeAcceleratorImpl implementation.
82 virtual bool CanDecodeOnIOThread() OVERRIDE;
83
84 private:
85 // These are rather subjectively tuned.
86 enum {
87 kMfcInputBufferCount = 8,
88 // TODO(posciak): determine MFC input buffer size based on level limits.
89 // See http://crbug.com/255116.
90 kMfcInputBufferMaxSize = 1024 * 1024,
91 // Number of output buffers to use for each VDA stage above what's required
92 // by the decoder (e.g. DPB size, in H264). We need
93 // media::limits::kMaxVideoFrames to fill up the GpuVideoDecode pipeline,
94 // and +1 for a frame in transit.
95 kDpbOutputBufferExtraCount = media::limits::kMaxVideoFrames + 1,
96 };
97
98 // Internal state of the decoder.
99 enum State {
100 kUninitialized, // Initialize() not yet called.
101 kInitialized, // Initialize() returned true; ready to start decoding.
102 kDecoding, // DecodeBufferInitial() successful; decoding frames.
103 kResetting, // Presently resetting.
104 kAfterReset, // After Reset(), ready to start decoding again.
105 kChangingResolution, // Performing resolution change, all remaining
106 // pre-change frames decoded and processed.
107 kError, // Error in kDecoding state.
108 };
109
110 enum BufferId {
111 kFlushBufferId = -2 // Buffer id for flush buffer, queued by FlushTask().
112 };
113
114 // File descriptors we need to poll.
115 enum PollFds {
116 kPollMfc = (1 << 0),
117 };
118
119 // Auto-destruction reference for BitstreamBuffer, for message-passing from
120 // Decode() to DecodeTask().
121 struct BitstreamBufferRef;
122
123 // Auto-destruction reference for an array of PictureBuffer, for
124 // message-passing from AssignPictureBuffers() to AssignPictureBuffersTask().
125 struct PictureBufferArrayRef;
126
127 // Auto-destruction reference for EGLSync (for message-passing).
128 struct EGLSyncKHRRef;
129
130 // Record for decoded pictures that can be sent to PictureReady.
131 struct PictureRecord;
132
133 // Record for MFC input buffers.
134 struct MfcInputRecord {
135 MfcInputRecord();
136 ~MfcInputRecord();
137 bool at_device; // held by device.
138 void* address; // mmap() address.
139 size_t length; // mmap() length.
140 off_t bytes_used; // bytes filled in the mmap() segment.
141 int32 input_id; // triggering input_id as given to Decode().
142 };
143
144 // Record for MFC output buffers.
145 struct MfcOutputRecord {
146 MfcOutputRecord();
147 ~MfcOutputRecord();
148 bool at_device; // held by device.
149 bool at_client; // held by client.
150 int fds[2]; // file descriptors for each plane.
151 EGLImageKHR egl_image; // EGLImageKHR for the output buffer.
152 EGLSyncKHR egl_sync; // sync the compositor's use of the EGLImage.
153 int32 picture_id; // picture buffer id as returned to PictureReady().
154 bool cleared; // Whether the texture is cleared and safe to render
155 // from. See TextureManager for details.
156 };
157
158 //
159 // Decoding tasks, to be run on decode_thread_.
160 //
161
162 // Enqueue a BitstreamBuffer to decode. This will enqueue a buffer to the
163 // decoder_input_queue_, then queue a DecodeBufferTask() to actually decode
164 // the buffer.
165 void DecodeTask(const media::BitstreamBuffer& bitstream_buffer);
166
167 // Decode from the buffers queued in decoder_input_queue_. Calls
168 // DecodeBufferInitial() or DecodeBufferContinue() as appropriate.
169 void DecodeBufferTask();
170 // Advance to the next fragment that begins a frame.
171 bool AdvanceFrameFragment(const uint8* data, size_t size, size_t* endpos);
172 // Schedule another DecodeBufferTask() if we're behind.
173 void ScheduleDecodeBufferTaskIfNeeded();
174
175 // Return true if we should continue to schedule DecodeBufferTask()s after
176 // completion. Store the amount of input actually consumed in |endpos|.
177 bool DecodeBufferInitial(const void* data, size_t size, size_t* endpos);
178 bool DecodeBufferContinue(const void* data, size_t size);
179
180 // Accumulate data for the next frame to decode. May return false in
181 // non-error conditions; for example when pipeline is full and should be
182 // retried later.
183 bool AppendToInputFrame(const void* data, size_t size);
184 // Flush data for one decoded frame.
185 bool FlushInputFrame();
186
187 // Process an AssignPictureBuffers() API call. After this, the
188 // device_poll_thread_ can be started safely, since we have all our
189 // buffers.
190 void AssignPictureBuffersTask(scoped_ptr<PictureBufferArrayRef> pic_buffers);
191
192 // Service I/O on the V4L2 devices. This task should only be scheduled from
193 // DevicePollTask(). If |mfc_event_pending| is true, one or more events
194 // on MFC file descriptor are pending.
195 void ServiceDeviceTask(bool mfc_event_pending);
196 // Handle the various device queues.
197 void EnqueueMfc();
198 void DequeueMfc();
199 // Handle incoming MFC events.
200 void DequeueMfcEvents();
201 // Enqueue a buffer on the corresponding queue.
202 bool EnqueueMfcInputRecord();
203 bool EnqueueMfcOutputRecord();
204
205 // Process a ReusePictureBuffer() API call. The API call create an EGLSync
206 // object on the main (GPU process) thread; we will record this object so we
207 // can wait on it before reusing the buffer.
208 void ReusePictureBufferTask(int32 picture_buffer_id,
209 scoped_ptr<EGLSyncKHRRef> egl_sync_ref);
210
211 // Flush() task. Child thread should not submit any more buffers until it
212 // receives the NotifyFlushDone callback. This task will schedule an empty
213 // BitstreamBufferRef (with input_id == kFlushBufferId) to perform the flush.
214 void FlushTask();
215 // Notify the client of a flush completion, if required. This should be
216 // called any time a relevant queue could potentially be emptied: see
217 // function definition.
218 void NotifyFlushDoneIfNeeded();
219
220 // Reset() task. This task will schedule a ResetDoneTask() that will send
221 // the NotifyResetDone callback, then set the decoder state to kResetting so
222 // that all intervening tasks will drain.
223 void ResetTask();
224 // ResetDoneTask() will set the decoder state back to kAfterReset, so
225 // subsequent decoding can continue.
226 void ResetDoneTask();
227
228 // Device destruction task.
229 void DestroyTask();
230
231 // Attempt to start/stop device_poll_thread_.
232 bool StartDevicePoll();
233 // If |keep_mfc_input_state| is true, don't reset MFC input state; used during
234 // resolution change.
235 bool StopDevicePoll(bool keep_mfc_input_state);
236 // Set/clear the device poll interrupt (using device_poll_interrupt_fd_).
237 bool SetDevicePollInterrupt();
238 bool ClearDevicePollInterrupt();
239
240 void StartResolutionChangeIfNeeded();
241 void FinishResolutionChange();
242 void ResumeAfterResolutionChange();
243
244 // Try to get output format from MFC, detected after parsing the beginning
245 // of the stream. Sets |again| to true if more parsing is needed.
246 bool GetFormatInfo(struct v4l2_format* format, bool* again);
247 // Create MFC output buffers for the given |format|.
248 bool CreateBuffersForFormat(const struct v4l2_format& format);
249
250 //
251 // Device tasks, to be run on device_poll_thread_.
252 //
253
254 // The device task.
255 void DevicePollTask(unsigned int poll_fds);
256
257 //
258 // Safe from any thread.
259 //
260
261 // Error notification (using PostTask() to child thread, if necessary).
262 void NotifyError(Error error);
263
264 // Set the decoder_thread_ state (using PostTask to decoder thread, if
265 // necessary).
266 void SetDecoderState(State state);
267
268 //
269 // Other utility functions. Called on decoder_thread_, unless
270 // decoder_thread_ is not yet started, in which case the child thread can call
271 // these (e.g. in Initialize() or Destroy()).
272 //
273
274 // Create the buffers we need.
275 bool CreateMfcInputBuffers();
276 bool CreateMfcOutputBuffers();
277
278 //
279 // Methods run on child thread.
280 //
281
282 // Destroy buffers.
283 void DestroyMfcInputBuffers();
284 void DestroyMfcOutputBuffers();
285 void ResolutionChangeDestroyBuffers();
286
287 // Send decoded pictures to PictureReady.
288 void SendPictureReady();
289
290 // Callback that indicates a picture has been cleared.
291 void PictureCleared();
292
293 // Our original calling message loop for the child thread.
294 scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
295
296 // Message loop of the IO thread.
297 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
298
299 // WeakPtr<> pointing to |this| for use in posting tasks from the decoder or
300 // device worker threads back to the child thread. Because the worker threads
301 // are members of this class, any task running on those threads is guaranteed
302 // that this object is still alive. As a result, tasks posted from the child
303 // thread to the decoder or device thread should use base::Unretained(this),
304 // and tasks posted the other way should use |weak_this_|.
305 base::WeakPtr<ExynosVideoDecodeAccelerator> weak_this_;
306
307 // To expose client callbacks from VideoDecodeAccelerator.
308 // NOTE: all calls to these objects *MUST* be executed on
309 // child_message_loop_proxy_.
310 base::WeakPtrFactory<Client> client_ptr_factory_;
311 base::WeakPtr<Client> client_;
312 // Callbacks to |io_client_| must be executed on |io_message_loop_proxy_|.
313 base::WeakPtr<Client> io_client_;
314
315 //
316 // Decoder state, owned and operated by decoder_thread_.
317 // Before decoder_thread_ has started, the decoder state is managed by
318 // the child (main) thread. After decoder_thread_ has started, the decoder
319 // thread should be the only one managing these.
320 //
321
322 // This thread services tasks posted from the VDA API entry points by the
323 // child thread and device service callbacks posted from the device thread.
324 base::Thread decoder_thread_;
325 // Decoder state machine state.
326 State decoder_state_;
327 // BitstreamBuffer we're presently reading.
328 scoped_ptr<BitstreamBufferRef> decoder_current_bitstream_buffer_;
329 // FlushTask() and ResetTask() should not affect buffers that have been
330 // queued afterwards. For flushing or resetting the pipeline then, we will
331 // delay these buffers until after the flush or reset completes.
332 int decoder_delay_bitstream_buffer_id_;
333 // MFC input buffer we're presently filling.
334 int decoder_current_input_buffer_;
335 // We track the number of buffer decode tasks we have scheduled, since each
336 // task execution should complete one buffer. If we fall behind (due to
337 // resource backpressure, etc.), we'll have to schedule more to catch up.
338 int decoder_decode_buffer_tasks_scheduled_;
339 // Picture buffers held by the client.
340 int decoder_frames_at_client_;
341 // Are we flushing?
342 bool decoder_flushing_;
343 // Got a notification from driver that it reached resolution change point
344 // in the stream.
345 bool resolution_change_pending_;
346 // Got a reset request while we were performing resolution change.
347 bool resolution_change_reset_pending_;
348 // Input queue for decoder_thread_: BitstreamBuffers in.
349 std::queue<linked_ptr<BitstreamBufferRef> > decoder_input_queue_;
350 // For H264 decode, hardware requires that we send it frame-sized chunks.
351 // We'll need to parse the stream.
352 scoped_ptr<content::H264Parser> decoder_h264_parser_;
353 // Set if the decoder has a pending incomplete frame in an input buffer.
354 bool decoder_partial_frame_pending_;
355
356 //
357 // Hardware state and associated queues. Since decoder_thread_ services
358 // the hardware, decoder_thread_ owns these too.
359 //
360
361 // Completed decode buffers, waiting for MFC.
362 std::queue<int> mfc_input_ready_queue_;
363
364 // MFC decode device.
365 int mfc_fd_;
366
367 // MFC input buffer state.
368 bool mfc_input_streamon_;
369 // MFC input buffers enqueued to device.
370 int mfc_input_buffer_queued_count_;
371 // Input buffers ready to use, as a LIFO since we don't care about ordering.
372 std::vector<int> mfc_free_input_buffers_;
373 // Mapping of int index to MFC input buffer record.
374 std::vector<MfcInputRecord> mfc_input_buffer_map_;
375
376 // MFC output buffer state.
377 bool mfc_output_streamon_;
378 // MFC output buffers enqueued to device.
379 int mfc_output_buffer_queued_count_;
380 // Output buffers ready to use, as a FIFO since we want oldest-first to hide
381 // synchronization latency with GL.
382 std::queue<int> mfc_free_output_buffers_;
383 // Mapping of int index to MFC output buffer record.
384 std::vector<MfcOutputRecord> mfc_output_buffer_map_;
385 // MFC output pixel format.
386 uint32 mfc_output_buffer_pixelformat_;
387 // Required size of DPB for decoding.
388 int mfc_output_dpb_size_;
389
390 // Pictures that are ready but not sent to PictureReady yet.
391 std::queue<PictureRecord> pending_picture_ready_;
392
393 // The number of pictures that are sent to PictureReady and will be cleared.
394 int picture_clearing_count_;
395
396 // Output picture size.
397 gfx::Size frame_buffer_size_;
398
399 //
400 // The device polling thread handles notifications of V4L2 device changes.
401 //
402
403 // The thread.
404 base::Thread device_poll_thread_;
405 // eventfd fd to signal device poll thread when its poll() should be
406 // interrupted.
407 int device_poll_interrupt_fd_;
408
409 //
410 // Other state, held by the child (main) thread.
411 //
412
413 // Make our context current before running any EGL entry points.
414 base::Callback<bool(void)> make_context_current_;
415
416 // EGL state
417 EGLDisplay egl_display_;
418
419 // The codec we'll be decoding for.
420 media::VideoCodecProfile video_profile_;
421
422 DISALLOW_COPY_AND_ASSIGN(ExynosVideoDecodeAccelerator);
423 };
424
425 } // namespace content
426
427 #endif // CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_DECODE_ACCELERATOR_H_
OLDNEW
« no previous file with comments | « no previous file | content/common/gpu/media/exynos_video_decode_accelerator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698