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