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 explicit ExynosVideoEncodeAccelerator( | |
38 media::VideoEncodeAccelerator::Client* client); | |
39 virtual ~ExynosVideoEncodeAccelerator(); | |
40 | |
41 // media::VideoEncodeAccelerator implementation. | |
42 virtual void Initialize(media::VideoFrame::Format format, | |
43 const gfx::Size& input_visible_size, | |
44 media::VideoCodecProfile output_profile, | |
45 uint32 initial_bitrate) OVERRIDE; | |
46 virtual void Encode(const scoped_refptr<media::VideoFrame>& frame, | |
47 bool force_keyframe) OVERRIDE; | |
48 virtual void UseOutputBitstreamBuffer( | |
49 const media::BitstreamBuffer& buffer) OVERRIDE; | |
50 virtual void RequestEncodingParametersChange(uint32 bitrate, | |
51 uint32 framerate) 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 encoder state. | |
106 }; | |
107 | |
108 // | |
109 // Encoding tasks, to be run on encode_thread_. | |
110 // | |
111 | |
112 // Encode a GSC input buffer. | |
113 void EncodeTask(const scoped_refptr<media::VideoFrame>& frame, | |
114 bool force_keyframe); | |
115 | |
116 // Add a BitstreamBuffer to the queue of buffers ready to be used for encoder | |
117 // output. | |
118 void UseOutputBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref); | |
119 | |
120 // Device destruction task. | |
121 void DestroyTask(); | |
122 | |
123 // Service I/O on the V4L2 devices. This task should only be scheduled from | |
124 // DevicePollTask(). | |
125 void ServiceDeviceTask(); | |
126 | |
127 // Handle the various device queues. | |
128 void EnqueueGsc(); | |
129 void DequeueGsc(); | |
130 void EnqueueMfc(); | |
131 void DequeueMfc(); | |
132 // Enqueue a buffer on the corresponding queue. Returns false on fatal error. | |
133 bool EnqueueGscInputRecord(); | |
134 bool EnqueueGscOutputRecord(); | |
135 bool EnqueueMfcInputRecord(); | |
136 bool EnqueueMfcOutputRecord(); | |
137 | |
138 // Attempt to start/stop device_poll_thread_. | |
139 bool StartDevicePoll(); | |
140 bool StopDevicePoll(); | |
141 // Set/clear the device poll interrupt (using device_poll_interrupt_fd_). | |
142 bool SetDevicePollInterrupt(); | |
143 bool ClearDevicePollInterrupt(); | |
144 | |
145 // | |
146 // Device tasks, to be run on device_poll_thread_. | |
147 // | |
148 | |
149 // The device task. | |
150 void DevicePollTask(unsigned int poll_fds); | |
151 | |
152 // | |
153 // Safe from any thread. | |
154 // | |
155 | |
156 // Error notification (using PostTask() to child thread, if necessary). | |
157 void NotifyError(Error error); | |
158 | |
159 // Set the encoder_thread_ state (using PostTask to encoder thread, if | |
160 // necessary). | |
161 void SetEncoderState(State state); | |
162 | |
163 // | |
164 // Other utility functions. Called on encoder_thread_, unless | |
165 // encoder_thread_ is not yet started, in which case the child thread can call | |
166 // these (e.g. in Initialize() or Destroy()). | |
167 // | |
168 | |
169 // Change the parameters of encoding. | |
170 void RequestEncodingParametersChangeTask(uint32 bitrate, uint32 framerate); | |
171 | |
172 // Create the buffers we need. | |
173 bool CreateGscInputBuffers(); | |
174 bool CreateGscOutputBuffers(); | |
175 bool SetMfcFormats(); | |
176 bool CreateMfcInputBuffers(); | |
177 bool CreateMfcOutputBuffers(); | |
178 | |
179 // Destroy these buffers. | |
180 void DestroyGscInputBuffers(); | |
181 void DestroyGscOutputBuffers(); | |
182 void DestroyMfcInputBuffers(); | |
183 void DestroyMfcOutputBuffers(); | |
184 | |
185 // Our original calling message loop for the child thread. | |
186 const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_; | |
187 | |
188 // WeakPtr<> pointing to |this| for use in posting tasks from the encoder or | |
189 // device worker threads back to the child thread. Because the worker threads | |
190 // are members of this class, any task running on those threads is guaranteed | |
191 // that this object is still alive. As a result, tasks posted from the child | |
192 // thread to the encoder or device thread should use base::Unretained(this), | |
193 // and tasks posted the other way should use |weak_this_|. | |
194 base::WeakPtrFactory<ExynosVideoEncodeAccelerator> weak_this_ptr_factory_; | |
195 base::WeakPtr<ExynosVideoEncodeAccelerator> weak_this_; | |
196 | |
197 // To expose client callbacks from VideoEncodeAccelerator. | |
198 // NOTE: all calls to these objects *MUST* be executed on | |
199 // child_message_loop_proxy_. | |
200 base::WeakPtrFactory<Client> client_ptr_factory_; | |
201 base::WeakPtr<Client> client_; | |
202 | |
203 // | |
204 // Encoder state, owned and operated by encoder_thread_. | |
205 // Before encoder_thread_ has started, the encoder state is managed by | |
206 // the child (main) thread. After encoder_thread_ has started, the encoder | |
207 // thread should be the only one managing these. | |
208 // | |
209 | |
210 // This thread services tasks posted from the VEA API entry points by the | |
211 // child thread and device service callbacks posted from the device thread. | |
212 base::Thread encoder_thread_; | |
213 // Encoder state. | |
214 State encoder_state_; | |
215 // The visible/allocated sizes of the input frame. | |
216 gfx::Size input_visible_size_; | |
217 gfx::Size input_allocated_size_; | |
218 // The visible/allocated sizes of the color-converted intermediate frame. | |
219 gfx::Size converted_visible_size_; | |
220 gfx::Size converted_allocated_size_; | |
221 // The logical visible size of the output frame. | |
222 gfx::Size output_visible_size_; | |
223 // The required byte size of output BitstreamBuffers. | |
224 size_t output_buffer_byte_size_; | |
225 | |
226 // We need to provide the stream header with every keyframe, to allow | |
227 // midstream decoding restarts. Store it here. | |
228 scoped_ptr<uint8[]> stream_header_; | |
229 size_t stream_header_size_; | |
230 | |
231 // V4L2 formats for input frames and the output stream. | |
232 uint32 input_format_fourcc_; | |
233 uint32 output_format_fourcc_; | |
234 | |
235 // Video frames ready to be encoded. | |
236 std::list<scoped_refptr<media::VideoFrame> > encoder_input_queue_; | |
237 | |
238 // GSC color conversion device. | |
239 int gsc_fd_; | |
240 // GSC input queue state. | |
241 bool gsc_input_streamon_; | |
242 // GSC input buffers enqueued to device. | |
243 int gsc_input_buffer_queued_count_; | |
244 // GSC input buffers ready to use; LIFO since we don't care about ordering. | |
245 std::vector<int> gsc_free_input_buffers_; | |
246 // Mapping of int index to GSC input buffer record. | |
247 std::vector<GscInputRecord> gsc_input_buffer_map_; | |
248 | |
249 // GSC output queue state. | |
250 bool gsc_output_streamon_; | |
251 // GSC output buffers enqueued to device. | |
252 int gsc_output_buffer_queued_count_; | |
253 // GSC output buffers ready to use; LIFO since we don't care about ordering. | |
254 std::vector<int> gsc_free_output_buffers_; | |
255 // Mapping of int index to GSC output buffer record. | |
256 std::vector<GscOutputRecord> gsc_output_buffer_map_; | |
257 | |
258 // MFC input buffers filled by GSC, waiting to be queued to MFC. | |
259 std::list<int> mfc_ready_input_buffers_; | |
260 | |
261 // MFC video encoding device. | |
262 int mfc_fd_; | |
263 | |
264 // MFC input queue state. | |
265 bool mfc_input_streamon_; | |
266 // MFC input buffers enqueued to device. | |
267 int mfc_input_buffer_queued_count_; | |
268 // MFC input buffers ready to use; LIFO since we don't care about ordering. | |
269 std::vector<int> mfc_free_input_buffers_; | |
270 // Mapping of int index to MFC input buffer record. | |
271 std::vector<MfcInputRecord> mfc_input_buffer_map_; | |
272 | |
273 // MFC output queue state. | |
274 bool mfc_output_streamon_; | |
275 // MFC output buffers enqueued to device. | |
276 int mfc_output_buffer_queued_count_; | |
277 // MFC output buffers ready to use; LIFO since we don't care about ordering. | |
278 std::vector<int> mfc_free_output_buffers_; | |
279 // Mapping of int index to MFC output buffer record. | |
280 std::vector<MfcOutputRecord> mfc_output_buffer_map_; | |
281 | |
282 // Bitstream buffers ready to be used to return encoded output, as a LIFO | |
283 // since we don't care about ordering. | |
284 std::vector<linked_ptr<BitstreamBufferRef> > encoder_output_queue_; | |
285 | |
286 // | |
287 // The device polling thread handles notifications of V4L2 device changes. | |
288 // TODO(sheu): replace this thread with an TYPE_IO decoder_thread_. | |
Ami GONE FROM CHROMIUM
2013/08/13 18:13:19
s/decoder/encoder/
sheu
2013/08/14 01:00:42
Done.
| |
289 // | |
290 | |
291 // The thread. | |
292 base::Thread device_poll_thread_; | |
293 // eventfd fd to signal device poll thread when its poll() should be | |
294 // interrupted. | |
295 int device_poll_interrupt_fd_; | |
296 | |
297 DISALLOW_COPY_AND_ASSIGN(ExynosVideoEncodeAccelerator); | |
298 }; | |
299 | |
300 } // namespace content | |
301 | |
302 #endif // CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_ | |
OLD | NEW |