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/callback_forward.h" |
| 12 #include "base/memory/linked_ptr.h" |
| 13 #include "base/memory/weak_ptr.h" |
| 14 #include "base/threading/thread.h" |
| 15 #include "content/common/gpu/gl_surface_encoder.h" |
| 16 #include "media/base/video_decoder_config.h" |
| 17 #include "media/video/video_encode_accelerator.h" |
| 18 #include "ui/gfx/size.h" |
| 19 #include "ui/gl/gl_bindings.h" |
| 20 |
| 21 namespace base { |
| 22 |
| 23 class MessageLoopProxy; |
| 24 |
| 25 } // namespace base |
| 26 |
| 27 namespace gfx { |
| 28 |
| 29 class GLSurface; |
| 30 |
| 31 } // namespace gfx |
| 32 |
| 33 namespace media { |
| 34 |
| 35 class BitstreamBuffer; |
| 36 |
| 37 } // namespace media |
| 38 |
| 39 namespace content { |
| 40 |
| 41 // This class handles Exynos video encode acceleration by interfacing with the |
| 42 // V4L2 devices exported by the Multi Format Codec and GScaler hardware blocks |
| 43 // on the Exynos platform. |
| 44 // |
| 45 // The threading model of this class is the same as the |
| 46 // ExynosVideoDecodeAccelerator (from which class this was designed). The one |
| 47 // notable difference is in the thread "ownership" of the GSC free input buffers |
| 48 // queue (gsc_free_input_buffers_). As this queue needs to be queried and |
| 49 // dequeued from the child thread (to obtain a texture to copy the backbuffer |
| 50 // to in Encode()), it is owned by the child thread. |
| 51 class ExynosVideoEncodeAccelerator : public media::VideoEncodeAccelerator { |
| 52 public: |
| 53 ExynosVideoEncodeAccelerator( |
| 54 EGLDisplay egl_display, |
| 55 media::VideoEncodeAccelerator::Client* client, |
| 56 const base::Callback<bool(void)>& make_context_current, |
| 57 bool encode_from_backbuffer); |
| 58 ~ExynosVideoEncodeAccelerator(); |
| 59 |
| 60 // media::VideoEncodeAccelerator implementation. |
| 61 virtual void Initialize(media::VideoCodecProfile profile, |
| 62 const gfx::Size& input_resolution, |
| 63 const gfx::Size& output_resolution, |
| 64 int32 initial_bitrate) OVERRIDE; |
| 65 virtual void Encode( |
| 66 const scoped_refptr<media::VideoFrame>& frame, |
| 67 int32 frame_id, |
| 68 bool force_keyframe) OVERRIDE; |
| 69 virtual void UseBitstreamBuffer( |
| 70 const media::BitstreamBuffer& buffer) OVERRIDE; |
| 71 virtual void RequestEncodingParameterChange(int32 bitrate) OVERRIDE; |
| 72 virtual void Destroy() OVERRIDE; |
| 73 |
| 74 private: |
| 75 // Auto-destroy reference for BitstreamBuffer, for tracking buffers passed as |
| 76 // input to UseBitstreamBuffer. |
| 77 struct BitstreamBufferRef; |
| 78 |
| 79 // Record for GSC input buffers. |
| 80 struct GscInputRecord { |
| 81 GscInputRecord(); |
| 82 bool at_device; |
| 83 int frame_id; |
| 84 EGLSyncKHR egl_sync; |
| 85 EGLImageKHR egl_image; |
| 86 GLuint texture_id; |
| 87 void* address; |
| 88 size_t length; |
| 89 }; |
| 90 |
| 91 // Record for GSC output buffers. |
| 92 struct GscOutputRecord { |
| 93 GscOutputRecord(); |
| 94 bool at_device; |
| 95 int mfc_input; |
| 96 void* address[3]; |
| 97 size_t length[3]; |
| 98 size_t bytes_used[3]; |
| 99 }; |
| 100 |
| 101 // Record for MFC input buffers. |
| 102 struct MfcInputRecord { |
| 103 MfcInputRecord(); |
| 104 bool at_device; |
| 105 int fd[2]; |
| 106 }; |
| 107 |
| 108 // Record for MFC output buffers. |
| 109 struct MfcOutputRecord { |
| 110 MfcOutputRecord(); |
| 111 bool at_device; |
| 112 void* address; |
| 113 size_t length; |
| 114 size_t bytes_used; |
| 115 }; |
| 116 |
| 117 enum { |
| 118 // These are rather subjectively tuned. |
| 119 kGscInputBufferCount = 2, |
| 120 kGscOutputBufferCount = 2, |
| 121 kMfcOutputBufferCount = 3, |
| 122 // MFC hardware does not report required output buffer size correctly. |
| 123 // Use maximum theoretical size to avoid hanging the hardware. |
| 124 kMfcOutputBufferSize = (2 * 1024 * 1024), |
| 125 }; |
| 126 |
| 127 // Internal state of the encoder. |
| 128 enum State { |
| 129 kUninitialized, // Initialize() not yet called. |
| 130 kInitialized, // Initialize() returned true; ready to start decoding. |
| 131 kEncoding, // Encoding frames. |
| 132 kError, // Error in kEncoding state. |
| 133 }; |
| 134 |
| 135 // File descriptors we need to poll. |
| 136 enum PollFds { |
| 137 kPollGsc = (1 << 0), |
| 138 kPollMfc = (1 << 1), |
| 139 }; |
| 140 |
| 141 // |
| 142 // Child thread utility functions, supporting API entry points. |
| 143 // |
| 144 |
| 145 // Return a buffer to gsc_free_input_buffers_. |
| 146 void ReturnFreeGscInputBuffer(int index); |
| 147 |
| 148 // |
| 149 // Decoding tasks, to be run on encode_thread_. |
| 150 // |
| 151 |
| 152 // Encode a GSC input buffer. |
| 153 void EncodeTask(int gsc_input_index); |
| 154 |
| 155 // Copy a media::VideoFrame to the GSC input buffer, then encode it. |
| 156 void CopyFrameAndEncodeTask(const scoped_refptr<media::VideoFrame>& frame, |
| 157 int gsc_input_index); |
| 158 |
| 159 // Add a BitstreamBuffer to out queue of buffers ready to be used for client |
| 160 // output. |
| 161 void UseBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref); |
| 162 |
| 163 // Device destruction task. |
| 164 void DestroyTask(); |
| 165 |
| 166 // Service I/O on the V4L2 devices. This task should only be scheduled from |
| 167 // DevicePollTask(). |
| 168 void ServiceDeviceTask(); |
| 169 // Handle the various device queues. |
| 170 void EnqueueGsc(); |
| 171 void DequeueGsc(); |
| 172 void EnqueueMfc(); |
| 173 void DequeueMfc(); |
| 174 // Enqueue a buffer on the corresponding queue. |
| 175 bool EnqueueGscInputRecord(); |
| 176 bool EnqueueGscOutputRecord(); |
| 177 bool EnqueueMfcInputRecord(); |
| 178 bool EnqueueMfcOutputRecord(); |
| 179 // Return completed buffers to the client. |
| 180 void ReturnCompleteBuffers(); |
| 181 |
| 182 // Attempt to start/stop device_poll_thread_. |
| 183 bool StartDevicePoll(); |
| 184 bool StopDevicePoll(); |
| 185 // Set/clear the device poll interrupt (using device_ooll_interrupt_fd_). |
| 186 bool SetDevicePollInterrupt(); |
| 187 bool ClearDevicePollInterrupt(); |
| 188 |
| 189 // |
| 190 // Device tasks, to be run on device_poll_thread_. |
| 191 // |
| 192 |
| 193 // The device task. |
| 194 void DevicePollTask(unsigned int poll_fds); |
| 195 |
| 196 // |
| 197 // Safe from any thread. |
| 198 // |
| 199 |
| 200 // Error notification (using PostTask() to child thread, if necessary). |
| 201 void NotifyError(Error error); |
| 202 |
| 203 // Set the encoder_thread_ state (using PostTask to encoder thread, if |
| 204 // necessary). |
| 205 void SetEncoderState(State state); |
| 206 |
| 207 // |
| 208 // Other utility functions. Called on encoder_thread_, unless |
| 209 // encoder_thread_ is not yet started, in which case the child thread can call |
| 210 // these (e.g. in Initialize() or Destroy()). |
| 211 // |
| 212 |
| 213 // Create the buffers we need. |
| 214 bool CreateGscInputBuffers(); |
| 215 bool CreateGscOutputBuffers(); |
| 216 bool SetMfcFormats(); |
| 217 bool CreateMfcInputBuffers(); |
| 218 bool CreateMfcOutputBuffers(); |
| 219 |
| 220 // Set encoding parameters. |
| 221 void SetBitrate(int32 bitrate); |
| 222 |
| 223 // Destroy these buffers. |
| 224 void DestroyGscInputBuffers(); |
| 225 void DestroyGscOutputBuffers(); |
| 226 void DestroyMfcInputBuffers(); |
| 227 void DestroyMfcOutputBuffers(); |
| 228 |
| 229 // Our original calling message loop for the child thread. |
| 230 const scoped_refptr<base::MessageLoopProxy> child_message_loop_proxy_; |
| 231 |
| 232 // WeakPtr<> pointing to |this| for use in posting tasks from the encoder or |
| 233 // device worker threads back to the child thread. Because the worker threads |
| 234 // are members of this class, any task running on those threads is guaranteed |
| 235 // that this object is still alive. As a result, tasks posted from the child |
| 236 // thread to the encoder or device thread should use base::Unretained(this), |
| 237 // and tasks posted the other way should use |weak_this_|. |
| 238 base::WeakPtrFactory<ExynosVideoEncodeAccelerator> weak_this_ptr_factory_; |
| 239 base::WeakPtr<ExynosVideoEncodeAccelerator> weak_this_; |
| 240 |
| 241 // To expose client callbacks from VideoEncodeAccelerator. |
| 242 // NOTE: all calls to these objects *MUST* be executed on |
| 243 // child_message_loop_proxy_. |
| 244 base::WeakPtrFactory<Client> client_ptr_factory_; |
| 245 base::WeakPtr<Client> client_; |
| 246 |
| 247 // |
| 248 // Encoder state, owned and operated by encoder_thread_. |
| 249 // Before encoder_thread_ has started, the encoder state is managed by |
| 250 // the child (main) thread. After encoder_thread_ has started, the encoder |
| 251 // thread should be the only one managing these. |
| 252 // |
| 253 |
| 254 // This thread services tasks posted from the VEA API entry points by the |
| 255 // child thread and device service callbacks posted from the device thread. |
| 256 base::Thread encoder_thread_; |
| 257 // Encoder state machine state. |
| 258 State encoder_state_; |
| 259 // The visible/allocated sizes of the input frame. |
| 260 gfx::Size input_visible_size_; |
| 261 gfx::Size input_allocated_size_; |
| 262 // The visible/allocated sizes of the color-converted frame. |
| 263 gfx::Size converted_visible_size_; |
| 264 gfx::Size converted_allocated_size_; |
| 265 // The visible/allocated sizes of the output frame. |
| 266 gfx::Size output_visible_size_; |
| 267 // The required byte size of output BitstreamBuffers. |
| 268 size_t output_buffer_byte_size_; |
| 269 |
| 270 // Cached stream header. |
| 271 scoped_ptr<uint8[]> stream_header_; |
| 272 size_t stream_header_size_; |
| 273 |
| 274 // Bitstream buffers ready to be used to return encoded output. |
| 275 std::vector<linked_ptr<BitstreamBufferRef> > encoder_bitstream_buffers_; |
| 276 |
| 277 // Buffers ready to be encoded. |
| 278 std::list<int> encoder_input_queue_; |
| 279 |
| 280 // Encoded buffers ready to return to the client. |
| 281 std::list<int> encoder_output_queue_; |
| 282 |
| 283 // Flag if we are encoding the output (and using MFC). |
| 284 bool do_output_encoding_; |
| 285 |
| 286 // Flag if we are encoding from the backbuffer (instead of a CPU allocation). |
| 287 const bool do_encode_from_backbuffer_; |
| 288 |
| 289 // GSC color conversion device. |
| 290 int gsc_fd_; |
| 291 // GSC input buffer state. |
| 292 bool gsc_input_streamon_; |
| 293 // GSC input buffers enqueued to device. |
| 294 int gsc_input_buffer_queued_count_; |
| 295 // Mapping of int index to GSC input buffer record. |
| 296 std::vector<GscInputRecord> gsc_input_buffer_map_; |
| 297 |
| 298 // GSC output buffer state. |
| 299 bool gsc_output_streamon_; |
| 300 // GSC output buffers enqueued to device. |
| 301 int gsc_output_buffer_queued_count_; |
| 302 // Output buffers ready to use, as a LIFO since we don't care about ordering. |
| 303 std::vector<int> gsc_free_output_buffers_; |
| 304 // Mapping of int index to GSC output buffer record. |
| 305 std::vector<GscOutputRecord> gsc_output_buffer_map_; |
| 306 |
| 307 // Completed GSC outputs, waiting for GSC. |
| 308 std::list<int> gsc_output_mfc_input_queue_; |
| 309 |
| 310 // MFC video encoding device. |
| 311 int mfc_fd_; |
| 312 |
| 313 // MFC input buffer state. |
| 314 bool mfc_input_streamon_; |
| 315 // MFC input buffers enqueued to device. |
| 316 int mfc_input_buffer_queued_count_; |
| 317 // Input buffers ready to use, as a LIFO since we don't care about ordering. |
| 318 std::vector<int> mfc_free_input_buffers_; |
| 319 // Mapping of int index to MFC input buffer record. |
| 320 std::vector<MfcInputRecord> mfc_input_buffer_map_; |
| 321 |
| 322 // MFC output buffer state. |
| 323 bool mfc_output_streamon_; |
| 324 // MFC output buffers enqueued to device. |
| 325 int mfc_output_buffer_queued_count_; |
| 326 // Output buffers ready to use, as a LIFO since we don't care about ordering. |
| 327 std::vector<int> mfc_free_output_buffers_; |
| 328 // Mapping of int index to MFC output buffer record. |
| 329 std::vector<MfcOutputRecord> mfc_output_buffer_map_; |
| 330 |
| 331 // |
| 332 // The device polling thread handles notifications of V4L2 device changes. |
| 333 // |
| 334 |
| 335 // The thread. |
| 336 base::Thread device_poll_thread_; |
| 337 // eventfd fd to signal device poll thread when its poll() should be |
| 338 // interrupted. |
| 339 int device_poll_interrupt_fd_; |
| 340 |
| 341 // |
| 342 // Other state, held by child (main) thread. |
| 343 // |
| 344 |
| 345 // Make our context current before running any EGL entry points. |
| 346 base::Callback<bool(void)> make_context_current_; |
| 347 |
| 348 // Input buffers ready to use, as a LIFO since we don't care about ordering. |
| 349 std::vector<int> gsc_free_input_buffers_; |
| 350 |
| 351 // EGL state |
| 352 const EGLDisplay egl_display_; |
| 353 |
| 354 // The codec we'll be decoding for. |
| 355 media::VideoCodecProfile video_profile_; |
| 356 }; |
| 357 |
| 358 } // namespace content |
| 359 |
| 360 #endif // CONTENT_COMMON_GPU_MEDIA_EXYNOS_VIDEO_ENCODE_ACCELERATOR_H_ |
OLD | NEW |