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

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

Issue 852103002: Revert of Add accelerated video decoder interface, VP8 and H.264 implementations and hook up to V4L2SVDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 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
OLDNEW
(Empty)
1 // Copyright 2015 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_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
6 #define CONTENT_COMMON_GPU_MEDIA_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
7
8 #include <linux/videodev2.h>
9 #include <queue>
10 #include <vector>
11
12 #include "base/memory/linked_ptr.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/threading/thread.h"
18 #include "content/common/content_export.h"
19 #include "content/common/gpu/media/h264_decoder.h"
20 #include "content/common/gpu/media/v4l2_video_device.h"
21 #include "content/common/gpu/media/vp8_decoder.h"
22 #include "media/video/video_decode_accelerator.h"
23
24 namespace content {
25
26 // An implementation of VideoDecodeAccelerator that utilizes the V4L2 slice
27 // level codec API for decoding. The slice level API provides only a low-level
28 // decoding functionality and requires userspace to provide support for parsing
29 // the input stream and managing decoder state across frames.
30 class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
31 : public media::VideoDecodeAccelerator {
32 public:
33 class V4L2DecodeSurface;
34
35 V4L2SliceVideoDecodeAccelerator(
36 const scoped_refptr<V4L2Device>& device,
37 EGLDisplay egl_display,
38 EGLContext egl_context,
39 const base::WeakPtr<Client>& io_client_,
40 const base::Callback<bool(void)>& make_context_current,
41 const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy);
42 virtual ~V4L2SliceVideoDecodeAccelerator() override;
43
44 // media::VideoDecodeAccelerator implementation.
45 bool Initialize(media::VideoCodecProfile profile,
46 VideoDecodeAccelerator::Client* client) override;
47 void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
48 void AssignPictureBuffers(
49 const std::vector<media::PictureBuffer>& buffers) override;
50 void ReusePictureBuffer(int32 picture_buffer_id) override;
51 void Flush() override;
52 void Reset() override;
53 void Destroy() override;
54 bool CanDecodeOnIOThread() override;
55
56 private:
57 class V4L2H264Accelerator;
58 class V4L2VP8Accelerator;
59
60 // Record for input buffers.
61 struct InputRecord {
62 InputRecord();
63 int32 input_id;
64 void* address;
65 size_t length;
66 size_t bytes_used;
67 bool at_device;
68 };
69
70 // Record for output buffers.
71 struct OutputRecord {
72 OutputRecord();
73 bool at_device;
74 bool at_client;
75 int32 picture_id;
76 EGLImageKHR egl_image;
77 EGLSyncKHR egl_sync;
78 bool cleared;
79 };
80
81 // See http://crbug.com/255116.
82 // Input bitstream buffer size for up to 1080p streams.
83 const size_t kInputBufferMaxSizeFor1080p = 1024 * 1024;
84 // Input bitstream buffer size for up to 4k streams.
85 const size_t kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p;
86 const size_t kNumInputBuffers = 16;
87
88 //
89 // Below methods are used by accelerator implementations.
90 //
91 // Append slice data in |data| of size |size| to pending hardware
92 // input buffer with |index|. This buffer will be submitted for decode
93 // on the next DecodeSurface(). Return true on success.
94 bool SubmitSlice(int index, const uint8_t* data, size_t size);
95
96 // Submit controls in |ext_ctrls| to hardware. Return true on success.
97 bool SubmitExtControls(struct v4l2_ext_controls* ext_ctrls);
98
99 // Decode of |dec_surface| is ready to be submitted and all codec-specific
100 // settings are set in hardware.
101 void DecodeSurface(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
102
103 // |dec_surface| is ready to be outputted once decode is finished.
104 // This can be called before decode is actually done in hardware, and this
105 // method is responsible for maintaining the ordering, i.e. the surfaces will
106 // be outputted in the same order as SurfaceReady calls. To do so, the
107 // surfaces are put on decoder_display_queue_ and sent to output in that
108 // order once all preceding surfaces are sent.
109 void SurfaceReady(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
110
111 //
112 // Internal methods of this class.
113 //
114 // Recycle V4L2 output buffer with |index|. Used as surface release callback.
115 void ReuseOutputBuffer(int index);
116
117 // Queue a |dec_surface| to device for decoding.
118 void Enqueue(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
119
120 // Dequeue any V4L2 buffers available and process.
121 void Dequeue();
122
123 // V4L2 QBUF helpers.
124 bool EnqueueInputRecord(int index, uint32_t config_store);
125 bool EnqueueOutputRecord(int index);
126
127 // Set input and output formats in hardware.
128 bool SetupFormats();
129
130 // Create input and output buffers.
131 bool CreateInputBuffers();
132 bool CreateOutputBuffers();
133
134 // Destroy input buffers.
135 void DestroyInputBuffers();
136
137 // Destroy output buffers and release associated resources (textures,
138 // EGLImages). If |dismiss| is true, also dismissing the associated
139 // PictureBuffers.
140 bool DestroyOutputs(bool dismiss);
141
142 // Used by DestroyOutputs.
143 bool DestroyOutputBuffers();
144
145 // Dismiss all |picture_buffer_ids| via Client::DismissPictureBuffer()
146 // and signal |done| after finishing.
147 void DismissPictures(std::vector<int32> picture_buffer_ids,
148 base::WaitableEvent* done);
149
150 // Task to finish initialization on decoder_thread_.
151 void InitializeTask();
152
153 // Surface set change (resolution change) flow.
154 // If we have no surfaces allocated, just allocate them and return.
155 // Otherwise mark us as pending for surface set change.
156 void InitiateSurfaceSetChange();
157 // If a surface set change is pending and we are ready, stop the device,
158 // destroy outputs, releasing resources and dismissing pictures as required,
159 // followed by allocating a new set for the new resolution/DPB size
160 // as provided by decoder. Finally, try to resume decoding.
161 void FinishSurfaceSetChangeIfNeeded();
162
163 void NotifyError(Error error);
164 void DestroyTask();
165
166 // Sets the state to kError and notifies client if needed.
167 void SetErrorState(Error error);
168
169 // Flush flow when requested by client.
170 // When Flush() is called, it posts a FlushTask, which checks the input queue.
171 // If nothing is pending for decode on decoder_input_queue_, we call
172 // InitiateFlush() directly. Otherwise, we push a dummy BitstreamBufferRef
173 // onto the decoder_input_queue_ to schedule a flush. When we reach it later
174 // on, we call InitiateFlush() to perform it at the correct time.
175 void FlushTask();
176 // Tell the decoder to flush all frames, reset it and mark us as scheduled
177 // for flush, so that we can finish it once all pending decodes are finished.
178 void InitiateFlush();
179 // If all pending frames are decoded and we are waiting to flush, perform it.
180 // This will send all pending pictures to client and notify the client that
181 // flush is complete and puts us in a state ready to resume.
182 void FinishFlushIfNeeded();
183
184 // Reset flow when requested by client.
185 // Drop all inputs and reset the decoder and mark us as pending for reset.
186 void ResetTask();
187 // If all pending frames are decoded and we are waiting to reset, perform it.
188 // This drops all pending outputs (client is not interested anymore),
189 // notifies the client we are done and puts us in a state ready to resume.
190 void FinishResetIfNeeded();
191
192 // Process pending events if any.
193 void ProcessPendingEventsIfNeeded();
194
195 // Performed on decoder_thread_ as a consequence of poll() on decoder_thread_
196 // returning an event.
197 void ServiceDeviceTask();
198
199 // Schedule poll if we have any buffers queued and the poll thread
200 // is not stopped (on surface set change).
201 void SchedulePollIfNeeded();
202
203 // Attempt to start/stop device_poll_thread_.
204 bool StartDevicePoll();
205 bool StopDevicePoll(bool keep_input_state);
206
207 // Ran on device_poll_thread_ to wait for device events.
208 void DevicePollTask(bool poll_device);
209
210 enum State {
211 // We are in this state until Initialize() returns successfully.
212 // We can't post errors to the client in this state yet.
213 kUninitialized,
214 // Initialize() returned successfully.
215 kInitialized,
216 // This state allows making progress decoding more input stream.
217 kDecoding,
218 // Transitional state when we are not decoding any more stream, but are
219 // performing flush, reset, resolution change or are destroying ourselves.
220 kIdle,
221 // Error state, set when sending NotifyError to client.
222 kError,
223 };
224
225 // Buffer id for flush buffer, queued by FlushTask().
226 const int kFlushBufferId = -2;
227
228 // Handler for Decode() on decoder_thread_.
229 void DecodeTask(const media::BitstreamBuffer& bitstream_buffer);
230
231 // Schedule a new DecodeBufferTask if we are decoding.
232 void ScheduleDecodeBufferTaskIfNeeded();
233
234 // Main decoder loop. Keep decoding the current buffer in decoder_, asking
235 // for more stream via TrySetNewBistreamBuffer() if decoder_ requests so,
236 // and handle other returns from it appropriately.
237 void DecodeBufferTask();
238
239 // Check decoder_input_queue_ for any available buffers to decode and
240 // set the decoder_current_bitstream_buffer_ to the next buffer if one is
241 // available, taking it off the queue. Also set the current stream pointer
242 // in decoder_, and return true.
243 // Return false if no buffers are pending on decoder_input_queue_.
244 bool TrySetNewBistreamBuffer();
245
246 // Auto-destruction reference for EGLSync (for message-passing).
247 struct EGLSyncKHRRef;
248 void ReusePictureBufferTask(int32 picture_buffer_id,
249 scoped_ptr<EGLSyncKHRRef> egl_sync_ref);
250
251 // Called to actually send |dec_surface| to the client, after it is decoded
252 // preserving the order in which it was scheduled via SurfaceReady().
253 void OutputSurface(const scoped_refptr<V4L2DecodeSurface>& dec_surface);
254
255 // Goes over the |decoder_display_queue_| and sends all buffers from the
256 // front of the queue that are already decoded to the client, in order.
257 void TryOutputSurfaces();
258
259 // Creates a new decode surface or returns nullptr if one is not available.
260 scoped_refptr<V4L2DecodeSurface> CreateSurface();
261
262 // Send decoded pictures to PictureReady.
263 void SendPictureReady();
264
265 // Callback that indicates a picture has been cleared.
266 void PictureCleared();
267
268 size_t input_planes_count_;
269 size_t output_planes_count_;
270
271 // GPU Child thread message loop.
272 const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_;
273
274 // IO thread message loop.
275 scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
276
277 // WeakPtr<> pointing to |this| for use in posting tasks from the decoder or
278 // device worker threads back to the child thread.
279 base::WeakPtr<V4L2SliceVideoDecodeAccelerator> weak_this_;
280
281 // To expose client callbacks from VideoDecodeAccelerator.
282 // NOTE: all calls to these objects *MUST* be executed on
283 // child_message_loop_proxy_.
284 scoped_ptr<base::WeakPtrFactory<VideoDecodeAccelerator::Client>>
285 client_ptr_factory_;
286 base::WeakPtr<VideoDecodeAccelerator::Client> client_;
287 // Callbacks to |io_client_| must be executed on |io_message_loop_proxy_|.
288 base::WeakPtr<Client> io_client_;
289
290 // V4L2 device in use.
291 scoped_refptr<V4L2Device> device_;
292
293 // Thread to communicate with the device on.
294 base::Thread decoder_thread_;
295 scoped_refptr<base::MessageLoopProxy> decoder_thread_proxy_;
296
297 // Thread used to poll the device for events.
298 base::Thread device_poll_thread_;
299
300 // Input queue state.
301 bool input_streamon_;
302 // Number of input buffers enqueued to the device.
303 int input_buffer_queued_count_;
304 // Input buffers ready to use; LIFO since we don't care about ordering.
305 std::list<int> free_input_buffers_;
306 // Mapping of int index to an input buffer record.
307 std::vector<InputRecord> input_buffer_map_;
308
309 // Output queue state.
310 bool output_streamon_;
311 // Number of output buffers enqueued to the device.
312 int output_buffer_queued_count_;
313 // Output buffers ready to use.
314 std::list<int> free_output_buffers_;
315 // Mapping of int index to an output buffer record.
316 std::vector<OutputRecord> output_buffer_map_;
317
318 media::VideoCodecProfile video_profile_;
319 uint32_t output_format_fourcc_;
320 gfx::Size frame_buffer_size_;
321 size_t output_dpb_size_;
322
323 struct BitstreamBufferRef;
324 // Input queue of stream buffers coming from the client.
325 std::queue<linked_ptr<BitstreamBufferRef>> decoder_input_queue_;
326 // BitstreamBuffer currently being processed.
327 scoped_ptr<BitstreamBufferRef> decoder_current_bitstream_buffer_;
328
329 // Queue storing decode surfaces ready to be output as soon as they are
330 // decoded. The surfaces must be output in order they are queued.
331 std::queue<scoped_refptr<V4L2DecodeSurface>> decoder_display_queue_;
332
333 // Decoder state.
334 State state_;
335
336 // If any of these are true, we are waiting for the device to finish decoding
337 // all previously-queued frames, so we can finish the flush/reset/surface
338 // change flows. These can stack.
339 bool decoder_flushing_;
340 bool decoder_resetting_;
341 bool surface_set_change_pending_;
342
343 // Hardware accelerators.
344 // TODO(posciak): Try to have a superclass here if possible.
345 scoped_ptr<V4L2H264Accelerator> h264_accelerator_;
346 scoped_ptr<V4L2VP8Accelerator> vp8_accelerator_;
347
348 // Codec-specific software decoder in use.
349 scoped_ptr<AcceleratedVideoDecoder> decoder_;
350
351 // Surfaces queued to device to keep references to them while decoded.
352 using V4L2DecodeSurfaceByOutputId =
353 std::map<int, scoped_refptr<V4L2DecodeSurface>>;
354 V4L2DecodeSurfaceByOutputId surfaces_at_device_;
355
356 // Surfaces sent to client to keep references to them while displayed.
357 using V4L2DecodeSurfaceByPictureBufferId =
358 std::map<int32, scoped_refptr<V4L2DecodeSurface>>;
359 V4L2DecodeSurfaceByPictureBufferId surfaces_at_display_;
360
361 // Record for decoded pictures that can be sent to PictureReady.
362 struct PictureRecord;
363 // Pictures that are ready but not sent to PictureReady yet.
364 std::queue<PictureRecord> pending_picture_ready_;
365
366 // The number of pictures that are sent to PictureReady and will be cleared.
367 int picture_clearing_count_;
368
369 // Used by the decoder thread to wait for AssignPictureBuffers to arrive
370 // to avoid races with potential Reset requests.
371 base::WaitableEvent pictures_assigned_;
372
373 // Make the GL context current callback.
374 base::Callback<bool(void)> make_context_current_;
375
376 // EGL state
377 EGLDisplay egl_display_;
378 EGLContext egl_context_;
379
380 // The WeakPtrFactory for |weak_this_|.
381 base::WeakPtrFactory<V4L2SliceVideoDecodeAccelerator> weak_this_factory_;
382
383 DISALLOW_COPY_AND_ASSIGN(V4L2SliceVideoDecodeAccelerator);
384 };
385
386 class V4L2H264Picture;
387 class V4L2VP8Picture;
388
389 } // namespace content
390
391 #endif // CONTENT_COMMON_GPU_MEDIA_V4L2_SLICE_VIDEO_DECODE_ACCELERATOR_H_
OLDNEW
« no previous file with comments | « content/common/gpu/media/v4l2_image_processor.cc ('k') | content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698