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_ | |
6 #define CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_ | |
7 | |
8 #include <list> | |
9 #include <vector> | |
10 | |
11 #include "base/memory/linked_ptr.h" | |
12 #include "base/memory/weak_ptr.h" | |
13 #include "base/threading/thread.h" | |
14 #include "media/video/video_encode_accelerator.h" | |
15 #include "ui/gfx/size.h" | |
16 | |
17 namespace base { | |
18 | |
19 class MessageLoopProxy; | |
20 | |
21 } // namespace base | |
22 | |
23 namespace media { | |
24 | |
25 class BitstreamBuffer; | |
26 | |
27 } // namespace media | |
28 | |
29 namespace content { | |
30 | |
31 // This class handles Exynos video encode acceleration by interfacing with the | |
32 // V4L2 devices exported by the Multi Format Codec and GScaler hardware blocks | |
33 // on the Exynos platform. The threading model of this class is the same as the | |
34 // ExynosVideoDecodeAccelerator (from which class this was designed). | |
35 class ExynosVideoEncodeAccelerator : public media::VideoEncodeAccelerator { | |
36 public: | |
37 ExynosVideoEncodeAccelerator(media::VideoEncodeAccelerator::Client* client); | |
38 ~ExynosVideoEncodeAccelerator(); | |
39 | |
40 // media::VideoEncodeAccelerator implementation. | |
41 virtual void Initialize(media::VideoFrame::Format format, | |
42 const gfx::Size& input_visible_size, | |
43 media::VideoCodecProfile output_profile, | |
44 int32 initial_bitrate) OVERRIDE; | |
45 virtual void Encode(const scoped_refptr<media::VideoFrame>& frame, | |
46 bool force_keyframe) OVERRIDE; | |
47 virtual void UseOutputBitstreamBuffer( | |
48 const media::BitstreamBuffer& buffer) OVERRIDE; | |
49 virtual void RequestEncodingParametersChange(int32 bitrate, | |
50 uint32 framerate_num, | |
51 uint32 framerate_denom) OVERRIDE; | |
52 virtual void Destroy() OVERRIDE; | |
53 | |
54 static std::vector<media::VideoEncodeAccelerator::SupportedProfile> | |
55 GetSupportedProfiles(); | |
56 | |
57 private: | |
58 // Auto-destroy reference for BitstreamBuffer, for tracking buffers passed to | |
59 // this instance. | |
60 struct BitstreamBufferRef; | |
61 | |
62 // Record for GSC input buffers. | |
63 struct GscInputRecord { | |
64 GscInputRecord(); | |
65 bool at_device; | |
66 scoped_refptr<media::VideoFrame> frame; | |
67 }; | |
68 | |
69 // Record for GSC output buffers. | |
70 struct GscOutputRecord { | |
71 GscOutputRecord(); | |
72 bool at_device; | |
73 int mfc_input; | |
74 }; | |
75 | |
76 // Record for MFC input buffers. | |
77 struct MfcInputRecord { | |
78 MfcInputRecord(); | |
79 bool at_device; | |
80 int fd[2]; | |
81 }; | |
82 | |
83 // Record for MFC output buffers. | |
84 struct MfcOutputRecord { | |
85 MfcOutputRecord(); | |
86 bool at_device; | |
87 linked_ptr<BitstreamBufferRef> buffer_ref; | |
88 }; | |
89 | |
90 enum { | |
91 // These are rather subjectively tuned. | |
92 kGscInputBufferCount = 2, | |
93 kGscOutputBufferCount = 2, | |
94 kMfcOutputBufferCount = 2, | |
95 // MFC hardware does not report required output buffer size correctly. | |
96 // Use maximum theoretical size to avoid hanging the hardware. | |
97 kMfcOutputBufferSize = (2 * 1024 * 1024), | |
98 }; | |
99 | |
100 // Internal state of the encoder. | |
101 enum State { | |
102 kUninitialized, // Initialize() not yet called. | |
103 kInitialized, // Initialize() returned true; ready to start encoding. | |
104 kEncoding, // Encoding frames. | |
105 kError, // Error in kEncoding state. | |
106 }; | |
107 | |
108 // File descriptors we need to poll. | |
109 enum PollFds { | |
110 kPollGsc = (1 << 0), | |
111 kPollMfc = (1 << 1), | |
112 }; | |
113 | |
114 // | |
115 // Encoding tasks, to be run on encode_thread_. | |
116 // | |
117 | |
118 // Encode a GSC input buffer. | |
119 void EncodeTask(const scoped_refptr<media::VideoFrame>& frame, | |
120 bool force_keyframe); | |
121 | |
122 // Add a BitstreamBuffer to the queue of buffers ready to be used for encoder | |
123 // output. | |
124 void UseOutputBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref); | |
125 | |
126 // Device destruction task. | |
127 void DestroyTask(); | |
128 | |
129 // Service I/O on the V4L2 devices. This task should only be scheduled from | |
130 // DevicePollTask(). | |
131 void ServiceDeviceTask(); | |
132 | |
133 // Handle the various device queues. | |
134 void EnqueueGsc(); | |
135 void DequeueGsc(); | |
136 void EnqueueMfc(); | |
137 void DequeueMfc(); | |
138 // Enqueue a buffer on the corresponding queue. | |
139 bool EnqueueGscInputRecord(); | |
140 bool EnqueueGscOutputRecord(); | |
141 bool EnqueueMfcInputRecord(); | |
142 bool EnqueueMfcOutputRecord(); | |
143 | |
144 // Attempt to start/stop device_poll_thread_. | |
145 bool StartDevicePoll(); | |
146 bool StopDevicePoll(); | |
147 // Set/clear the device poll interrupt (using device_ooll_interrupt_fd_). | |
Pawel Osciak
2013/08/09 13:40:02
s/ooll/poll/
sheu
2013/08/12 20:23:59
Done.
| |
148 bool SetDevicePollInterrupt(); | |
149 bool ClearDevicePollInterrupt(); | |
150 | |
151 // | |
152 // Device tasks, to be run on device_poll_thread_. | |
153 // | |
154 | |
155 // The device task. | |
156 void DevicePollTask(unsigned int poll_fds); | |
157 | |
158 // | |
159 // Safe from any thread. | |
160 // | |
161 | |
162 // Error notification (using PostTask() to child thread, if necessary). | |
163 void NotifyError(Error error); | |
164 | |
165 // Set the encoder_thread_ state (using PostTask to encoder thread, if | |
166 // necessary). | |
167 void SetEncoderState(State state); | |
168 | |
169 // | |
170 // Other utility functions. Called on encoder_thread_, unless | |
171 // encoder_thread_ is not yet started, in which case the child thread can call | |
172 // these (e.g. in Initialize() or Destroy()). | |
173 // | |
174 | |
175 // Change the parameters of encoding. | |
176 void RequestEncodingParametersChangeTask(int32 bitrate, | |
177 uint32 framerate_num, | |
178 uint32 framerate_denom); | |
179 | |
180 // Create the buffers we need. | |
181 bool CreateGscInputBuffers(); | |
182 bool CreateGscOutputBuffers(); | |
183 bool SetMfcFormats(); | |
184 bool CreateMfcInputBuffers(); | |
185 bool CreateMfcOutputBuffers(); | |
186 | |
187 // Destroy these buffers. | |
188 void DestroyGscInputBuffers(); | |
189 void DestroyGscOutputBuffers(); | |
190 void DestroyMfcInputBuffers(); | |
191 void DestroyMfcOutputBuffers(); | |
192 | |
193 // Our original calling message loop for the child thread. | |
194 const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_; | |
195 | |
196 // WeakPtr<> pointing to |this| for use in posting tasks from the encoder or | |
197 // device worker threads back to the child thread. Because the worker threads | |
198 // are members of this class, any task running on those threads is guaranteed | |
199 // that this object is still alive. As a result, tasks posted from the child | |
200 // thread to the encoder or device thread should use base::Unretained(this), | |
201 // and tasks posted the other way should use |weak_this_|. | |
202 base::WeakPtrFactory<ExynosVideoEncodeAccelerator> weak_this_ptr_factory_; | |
203 base::WeakPtr<ExynosVideoEncodeAccelerator> weak_this_; | |
204 | |
205 // To expose client callbacks from VideoEncodeAccelerator. | |
206 // NOTE: all calls to these objects *MUST* be executed on | |
207 // child_message_loop_proxy_. | |
208 base::WeakPtrFactory<Client> client_ptr_factory_; | |
209 base::WeakPtr<Client> client_; | |
210 | |
211 // | |
212 // Encoder state, owned and operated by encoder_thread_. | |
213 // Before encoder_thread_ has started, the encoder state is managed by | |
214 // the child (main) thread. After encoder_thread_ has started, the encoder | |
215 // thread should be the only one managing these. | |
216 // | |
217 | |
218 // This thread services tasks posted from the VEA API entry points by the | |
219 // child thread and device service callbacks posted from the device thread. | |
220 base::Thread encoder_thread_; | |
221 // Encoder state machine state. | |
222 State encoder_state_; | |
223 // The visible/allocated sizes of the input frame. | |
224 gfx::Size input_visible_size_; | |
225 gfx::Size input_allocated_size_; | |
226 // The visible/allocated sizes of the color-converted intermediate frame. | |
227 gfx::Size converted_visible_size_; | |
228 gfx::Size converted_allocated_size_; | |
229 // The logical visible size of the output frame. | |
230 gfx::Size output_visible_size_; | |
231 // The required byte size of output BitstreamBuffers. | |
232 size_t output_buffer_byte_size_; | |
233 | |
234 // We need to provide the stream header with every keyframe, to allow | |
235 // midstream decoding restarts. Store it here. | |
236 scoped_ptr<uint8[]> stream_header_; | |
237 size_t stream_header_size_; | |
238 | |
239 // V4L2 formats for input frames and the output stream. | |
240 uint32 input_format_fourcc_; | |
241 uint32 output_format_fourcc_; | |
242 | |
243 // Bitstream buffers ready to be encoded. | |
244 std::list<scoped_refptr<media::VideoFrame> > encoder_input_queue_; | |
245 | |
246 // GSC color conversion device. | |
247 int gsc_fd_; | |
248 // GSC input queue state. | |
249 bool gsc_input_streamon_; | |
250 // GSC input buffers enqueued to device. | |
251 int gsc_input_buffer_queued_count_; | |
252 // GSC input buffers ready to use; LIFO since we don't care about ordering. | |
253 std::vector<int> gsc_free_input_buffers_; | |
254 // Mapping of int index to GSC input buffer record. | |
255 std::vector<GscInputRecord> gsc_input_buffer_map_; | |
256 | |
257 // GSC output queue state. | |
258 bool gsc_output_streamon_; | |
259 // GSC output buffers enqueued to device. | |
260 int gsc_output_buffer_queued_count_; | |
261 // GSC output buffers ready to use; LIFO since we don't care about ordering. | |
262 std::vector<int> gsc_free_output_buffers_; | |
263 // Mapping of int index to GSC output buffer record. | |
264 std::vector<GscOutputRecord> gsc_output_buffer_map_; | |
265 | |
266 // MFC input buffers filled by GSC, waiting to be queued to MFC. | |
267 std::list<int> mfc_ready_input_buffers_; | |
268 | |
269 // MFC video encoding device. | |
270 int mfc_fd_; | |
271 | |
272 // MFC input queue state. | |
273 bool mfc_input_streamon_; | |
274 // MFC input buffers enqueued to device. | |
275 int mfc_input_buffer_queued_count_; | |
276 // MFC input buffers ready to use; LIFO since we don't care about ordering. | |
277 std::vector<int> mfc_free_input_buffers_; | |
278 // Mapping of int index to MFC input buffer record. | |
279 std::vector<MfcInputRecord> mfc_input_buffer_map_; | |
280 | |
281 // MFC output queue state. | |
282 bool mfc_output_streamon_; | |
283 // MFC output buffers enqueued to device. | |
284 int mfc_output_buffer_queued_count_; | |
285 // MFC output buffers ready to use; LIFO since we don't care about ordering. | |
286 std::vector<int> mfc_free_output_buffers_; | |
287 // Mapping of int index to MFC output buffer record. | |
288 std::vector<MfcOutputRecord> mfc_output_buffer_map_; | |
289 | |
290 // Bitstream buffers ready to be used to return encoded output, as a LIFO | |
291 // since we don't care about ordering. | |
292 std::vector<linked_ptr<BitstreamBufferRef> > encoder_output_queue_; | |
293 | |
294 // | |
295 // The device polling thread handles notifications of V4L2 device changes. | |
296 // | |
297 | |
298 // The thread. | |
299 base::Thread device_poll_thread_; | |
300 // eventfd fd to signal device poll thread when its poll() should be | |
301 // interrupted. | |
302 int device_poll_interrupt_fd_; | |
303 | |
304 DISALLOW_COPY_AND_ASSIGN(ExynosVideoEncodeAccelerator); | |
305 }; | |
306 | |
307 } // namespace content | |
308 | |
309 #endif // CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_ | |
OLD | NEW |