Chromium Code Reviews| 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 |