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 // This file contains an implementation of VideoDecodeAccelerator | 5 // This file contains an implementation of VideoDecodeAccelerator |
6 // that utilizes hardware video decoders, which expose Video4Linux 2 API | 6 // that utilizes hardware video decoders, which expose Video4Linux 2 API |
7 // (http://linuxtv.org/downloads/v4l-dvb-apis/). | 7 // (http://linuxtv.org/downloads/v4l-dvb-apis/). |
8 | 8 |
9 #ifndef MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ | 9 #ifndef MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ |
10 #define MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ | 10 #define MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ |
(...skipping 28 matching lines...) Expand all Loading... |
39 | 39 |
40 // This class handles video accelerators directly through a V4L2 device exported | 40 // This class handles video accelerators directly through a V4L2 device exported |
41 // by the hardware blocks. | 41 // by the hardware blocks. |
42 // | 42 // |
43 // The threading model of this class is driven by the fact that it needs to | 43 // The threading model of this class is driven by the fact that it needs to |
44 // interface two fundamentally different event queues -- the one Chromium | 44 // interface two fundamentally different event queues -- the one Chromium |
45 // provides through MessageLoop, and the one driven by the V4L2 devices which | 45 // provides through MessageLoop, and the one driven by the V4L2 devices which |
46 // is waited on with epoll(). There are three threads involved in this class: | 46 // is waited on with epoll(). There are three threads involved in this class: |
47 // | 47 // |
48 // * The child thread, which is the main GPU process thread which calls the | 48 // * The child thread, which is the main GPU process thread which calls the |
49 // media::VideoDecodeAccelerator entry points. Calls from this thread | 49 // VideoDecodeAccelerator entry points. Calls from this thread |
50 // generally do not block (with the exception of Initialize() and Destroy()). | 50 // generally do not block (with the exception of Initialize() and Destroy()). |
51 // They post tasks to the decoder_thread_, which actually services the task | 51 // They post tasks to the decoder_thread_, which actually services the task |
52 // and calls back when complete through the | 52 // and calls back when complete through the |
53 // media::VideoDecodeAccelerator::Client interface. | 53 // VideoDecodeAccelerator::Client interface. |
54 // * The decoder_thread_, owned by this class. It services API tasks, through | 54 // * The decoder_thread_, owned by this class. It services API tasks, through |
55 // the *Task() routines, as well as V4L2 device events, through | 55 // the *Task() routines, as well as V4L2 device events, through |
56 // ServiceDeviceTask(). Almost all state modification is done on this thread | 56 // ServiceDeviceTask(). Almost all state modification is done on this thread |
57 // (this doesn't include buffer (re)allocation sequence, see below). | 57 // (this doesn't include buffer (re)allocation sequence, see below). |
58 // * The device_poll_thread_, owned by this class. All it does is epoll() on | 58 // * The device_poll_thread_, owned by this class. All it does is epoll() on |
59 // the V4L2 in DevicePollTask() and schedule a ServiceDeviceTask() on the | 59 // the V4L2 in DevicePollTask() and schedule a ServiceDeviceTask() on the |
60 // decoder_thread_ when something interesting happens. | 60 // decoder_thread_ when something interesting happens. |
61 // TODO(sheu): replace this thread with an TYPE_IO decoder_thread_. | 61 // TODO(sheu): replace this thread with an TYPE_IO decoder_thread_. |
62 // | 62 // |
63 // Note that this class has (almost) no locks, apart from the pictures_assigned_ | 63 // Note that this class has (almost) no locks, apart from the pictures_assigned_ |
(...skipping 14 matching lines...) Expand all Loading... |
78 // V4L2VideoDecodeAccelerator may use image processor to convert the output. | 78 // V4L2VideoDecodeAccelerator may use image processor to convert the output. |
79 // There are three cases: | 79 // There are three cases: |
80 // Flush: V4L2VDA should wait until image processor returns all processed | 80 // Flush: V4L2VDA should wait until image processor returns all processed |
81 // frames. | 81 // frames. |
82 // Reset: V4L2VDA doesn't need to wait for image processor. When image processor | 82 // Reset: V4L2VDA doesn't need to wait for image processor. When image processor |
83 // returns an old frame, drop it. | 83 // returns an old frame, drop it. |
84 // Resolution change: V4L2VDA destroy image processor when destroying output | 84 // Resolution change: V4L2VDA destroy image processor when destroying output |
85 // buffrers. We cannot drop any frame during resolution change. So V4L2VDA | 85 // buffrers. We cannot drop any frame during resolution change. So V4L2VDA |
86 // should destroy output buffers after image processor returns all the frames. | 86 // should destroy output buffers after image processor returns all the frames. |
87 class MEDIA_GPU_EXPORT V4L2VideoDecodeAccelerator | 87 class MEDIA_GPU_EXPORT V4L2VideoDecodeAccelerator |
88 : public media::VideoDecodeAccelerator { | 88 : public VideoDecodeAccelerator { |
89 public: | 89 public: |
90 V4L2VideoDecodeAccelerator( | 90 V4L2VideoDecodeAccelerator( |
91 EGLDisplay egl_display, | 91 EGLDisplay egl_display, |
92 const GetGLContextCallback& get_gl_context_cb, | 92 const GetGLContextCallback& get_gl_context_cb, |
93 const MakeGLContextCurrentCallback& make_context_current_cb, | 93 const MakeGLContextCurrentCallback& make_context_current_cb, |
94 const scoped_refptr<V4L2Device>& device); | 94 const scoped_refptr<V4L2Device>& device); |
95 ~V4L2VideoDecodeAccelerator() override; | 95 ~V4L2VideoDecodeAccelerator() override; |
96 | 96 |
97 // media::VideoDecodeAccelerator implementation. | 97 // VideoDecodeAccelerator implementation. |
98 // Note: Initialize() and Destroy() are synchronous. | 98 // Note: Initialize() and Destroy() are synchronous. |
99 bool Initialize(const Config& config, Client* client) override; | 99 bool Initialize(const Config& config, Client* client) override; |
100 void Decode(const media::BitstreamBuffer& bitstream_buffer) override; | 100 void Decode(const BitstreamBuffer& bitstream_buffer) override; |
101 void AssignPictureBuffers( | 101 void AssignPictureBuffers(const std::vector<PictureBuffer>& buffers) override; |
102 const std::vector<media::PictureBuffer>& buffers) override; | |
103 void ReusePictureBuffer(int32_t picture_buffer_id) override; | 102 void ReusePictureBuffer(int32_t picture_buffer_id) override; |
104 void Flush() override; | 103 void Flush() override; |
105 void Reset() override; | 104 void Reset() override; |
106 void Destroy() override; | 105 void Destroy() override; |
107 bool TryToSetupDecodeOnSeparateThread( | 106 bool TryToSetupDecodeOnSeparateThread( |
108 const base::WeakPtr<Client>& decode_client, | 107 const base::WeakPtr<Client>& decode_client, |
109 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) | 108 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) |
110 override; | 109 override; |
111 | 110 |
112 static media::VideoDecodeAccelerator::SupportedProfiles | 111 static VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles(); |
113 GetSupportedProfiles(); | |
114 | 112 |
115 private: | 113 private: |
116 // These are rather subjectively tuned. | 114 // These are rather subjectively tuned. |
117 enum { | 115 enum { |
118 kInputBufferCount = 8, | 116 kInputBufferCount = 8, |
119 // TODO(posciak): determine input buffer size based on level limits. | 117 // TODO(posciak): determine input buffer size based on level limits. |
120 // See http://crbug.com/255116. | 118 // See http://crbug.com/255116. |
121 // Input bitstream buffer size for up to 1080p streams. | 119 // Input bitstream buffer size for up to 1080p streams. |
122 kInputBufferMaxSizeFor1080p = 1024 * 1024, | 120 kInputBufferMaxSizeFor1080p = 1024 * 1024, |
123 // Input bitstream buffer size for up to 4k streams. | 121 // Input bitstream buffer size for up to 4k streams. |
124 kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p, | 122 kInputBufferMaxSizeFor4k = 4 * kInputBufferMaxSizeFor1080p, |
125 // Number of output buffers to use for each VDA stage above what's required | 123 // Number of output buffers to use for each VDA stage above what's required |
126 // by the decoder (e.g. DPB size, in H264). We need | 124 // by the decoder (e.g. DPB size, in H264). We need |
127 // media::limits::kMaxVideoFrames to fill up the GpuVideoDecode pipeline, | 125 // limits::kMaxVideoFrames to fill up the GpuVideoDecode pipeline, |
128 // and +1 for a frame in transit. | 126 // and +1 for a frame in transit. |
129 kDpbOutputBufferExtraCount = media::limits::kMaxVideoFrames + 1, | 127 kDpbOutputBufferExtraCount = limits::kMaxVideoFrames + 1, |
130 }; | 128 }; |
131 | 129 |
132 // Internal state of the decoder. | 130 // Internal state of the decoder. |
133 enum State { | 131 enum State { |
134 kUninitialized, // Initialize() not yet called. | 132 kUninitialized, // Initialize() not yet called. |
135 kInitialized, // Initialize() returned true; ready to start decoding. | 133 kInitialized, // Initialize() returned true; ready to start decoding. |
136 kDecoding, // DecodeBufferInitial() successful; decoding frames. | 134 kDecoding, // DecodeBufferInitial() successful; decoding frames. |
137 kResetting, // Presently resetting. | 135 kResetting, // Presently resetting. |
138 kAfterReset, // After Reset(), ready to start decoding again. | 136 kAfterReset, // After Reset(), ready to start decoding again. |
139 kChangingResolution, // Performing resolution change, all remaining | 137 kChangingResolution, // Performing resolution change, all remaining |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 std::vector<base::ScopedFD> fds; | 186 std::vector<base::ScopedFD> fds; |
189 }; | 187 }; |
190 | 188 |
191 // | 189 // |
192 // Decoding tasks, to be run on decode_thread_. | 190 // Decoding tasks, to be run on decode_thread_. |
193 // | 191 // |
194 | 192 |
195 // Enqueue a BitstreamBuffer to decode. This will enqueue a buffer to the | 193 // Enqueue a BitstreamBuffer to decode. This will enqueue a buffer to the |
196 // decoder_input_queue_, then queue a DecodeBufferTask() to actually decode | 194 // decoder_input_queue_, then queue a DecodeBufferTask() to actually decode |
197 // the buffer. | 195 // the buffer. |
198 void DecodeTask(const media::BitstreamBuffer& bitstream_buffer); | 196 void DecodeTask(const BitstreamBuffer& bitstream_buffer); |
199 | 197 |
200 // Decode from the buffers queued in decoder_input_queue_. Calls | 198 // Decode from the buffers queued in decoder_input_queue_. Calls |
201 // DecodeBufferInitial() or DecodeBufferContinue() as appropriate. | 199 // DecodeBufferInitial() or DecodeBufferContinue() as appropriate. |
202 void DecodeBufferTask(); | 200 void DecodeBufferTask(); |
203 // Advance to the next fragment that begins a frame. | 201 // Advance to the next fragment that begins a frame. |
204 bool AdvanceFrameFragment(const uint8_t* data, size_t size, size_t* endpos); | 202 bool AdvanceFrameFragment(const uint8_t* data, size_t size, size_t* endpos); |
205 // Schedule another DecodeBufferTask() if we're behind. | 203 // Schedule another DecodeBufferTask() if we're behind. |
206 void ScheduleDecodeBufferTaskIfNeeded(); | 204 void ScheduleDecodeBufferTaskIfNeeded(); |
207 | 205 |
208 // Return true if we should continue to schedule DecodeBufferTask()s after | 206 // Return true if we should continue to schedule DecodeBufferTask()s after |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 // Picture buffers held by the client. | 394 // Picture buffers held by the client. |
397 int decoder_frames_at_client_; | 395 int decoder_frames_at_client_; |
398 // Are we flushing? | 396 // Are we flushing? |
399 bool decoder_flushing_; | 397 bool decoder_flushing_; |
400 // Got a reset request while we were performing resolution change. | 398 // Got a reset request while we were performing resolution change. |
401 bool resolution_change_reset_pending_; | 399 bool resolution_change_reset_pending_; |
402 // Input queue for decoder_thread_: BitstreamBuffers in. | 400 // Input queue for decoder_thread_: BitstreamBuffers in. |
403 std::queue<linked_ptr<BitstreamBufferRef>> decoder_input_queue_; | 401 std::queue<linked_ptr<BitstreamBufferRef>> decoder_input_queue_; |
404 // For H264 decode, hardware requires that we send it frame-sized chunks. | 402 // For H264 decode, hardware requires that we send it frame-sized chunks. |
405 // We'll need to parse the stream. | 403 // We'll need to parse the stream. |
406 std::unique_ptr<media::H264Parser> decoder_h264_parser_; | 404 std::unique_ptr<H264Parser> decoder_h264_parser_; |
407 // Set if the decoder has a pending incomplete frame in an input buffer. | 405 // Set if the decoder has a pending incomplete frame in an input buffer. |
408 bool decoder_partial_frame_pending_; | 406 bool decoder_partial_frame_pending_; |
409 | 407 |
410 // | 408 // |
411 // Hardware state and associated queues. Since decoder_thread_ services | 409 // Hardware state and associated queues. Since decoder_thread_ services |
412 // the hardware, decoder_thread_ owns these too. | 410 // the hardware, decoder_thread_ owns these too. |
413 // output_buffer_map_, free_output_buffers_ and output_planes_count_ are an | 411 // output_buffer_map_, free_output_buffers_ and output_planes_count_ are an |
414 // exception during the buffer (re)allocation sequence, when the | 412 // exception during the buffer (re)allocation sequence, when the |
415 // decoder_thread_ is blocked briefly while the Child thread manipulates | 413 // decoder_thread_ is blocked briefly while the Child thread manipulates |
416 // them. | 414 // them. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 | 470 |
473 // EGL state | 471 // EGL state |
474 EGLDisplay egl_display_; | 472 EGLDisplay egl_display_; |
475 | 473 |
476 // Callback to get current GLContext. | 474 // Callback to get current GLContext. |
477 GetGLContextCallback get_gl_context_cb_; | 475 GetGLContextCallback get_gl_context_cb_; |
478 // Callback to set the correct gl context. | 476 // Callback to set the correct gl context. |
479 MakeGLContextCurrentCallback make_context_current_cb_; | 477 MakeGLContextCurrentCallback make_context_current_cb_; |
480 | 478 |
481 // The codec we'll be decoding for. | 479 // The codec we'll be decoding for. |
482 media::VideoCodecProfile video_profile_; | 480 VideoCodecProfile video_profile_; |
483 // Chosen output format. | 481 // Chosen output format. |
484 uint32_t output_format_fourcc_; | 482 uint32_t output_format_fourcc_; |
485 | 483 |
486 // Image processor device, if one is in use. | 484 // Image processor device, if one is in use. |
487 scoped_refptr<V4L2Device> image_processor_device_; | 485 scoped_refptr<V4L2Device> image_processor_device_; |
488 // Image processor. Created and destroyed on child thread. | 486 // Image processor. Created and destroyed on child thread. |
489 std::unique_ptr<V4L2ImageProcessor> image_processor_; | 487 std::unique_ptr<V4L2ImageProcessor> image_processor_; |
490 | 488 |
491 // The V4L2Device EGLImage is created from. | 489 // The V4L2Device EGLImage is created from. |
492 scoped_refptr<V4L2Device> egl_image_device_; | 490 scoped_refptr<V4L2Device> egl_image_device_; |
(...skipping 14 matching lines...) Expand all Loading... |
507 | 505 |
508 // The WeakPtrFactory for |weak_this_|. | 506 // The WeakPtrFactory for |weak_this_|. |
509 base::WeakPtrFactory<V4L2VideoDecodeAccelerator> weak_this_factory_; | 507 base::WeakPtrFactory<V4L2VideoDecodeAccelerator> weak_this_factory_; |
510 | 508 |
511 DISALLOW_COPY_AND_ASSIGN(V4L2VideoDecodeAccelerator); | 509 DISALLOW_COPY_AND_ASSIGN(V4L2VideoDecodeAccelerator); |
512 }; | 510 }; |
513 | 511 |
514 } // namespace media | 512 } // namespace media |
515 | 513 |
516 #endif // MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ | 514 #endif // MEDIA_GPU_V4L2_VIDEO_DECODE_ACCELERATOR_H_ |
OLD | NEW |