| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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_V4L2_VIDEO_ENCODE_ACCELERATOR_H_ | |
| 6 #define CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_ENCODE_ACCELERATOR_H_ | |
| 7 | |
| 8 #include <linux/videodev2.h> | |
| 9 #include <stddef.h> | |
| 10 #include <stdint.h> | |
| 11 | |
| 12 #include <list> | |
| 13 #include <memory> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/files/scoped_file.h" | |
| 17 #include "base/macros.h" | |
| 18 #include "base/memory/linked_ptr.h" | |
| 19 #include "base/memory/weak_ptr.h" | |
| 20 #include "base/threading/thread.h" | |
| 21 #include "base/time/time.h" | |
| 22 #include "content/common/content_export.h" | |
| 23 #include "content/common/gpu/media/v4l2_device.h" | |
| 24 #include "content/common/gpu/media/v4l2_image_processor.h" | |
| 25 #include "media/video/video_encode_accelerator.h" | |
| 26 #include "ui/gfx/geometry/size.h" | |
| 27 | |
| 28 namespace media { | |
| 29 | |
| 30 class BitstreamBuffer; | |
| 31 | |
| 32 } // namespace media | |
| 33 | |
| 34 namespace content { | |
| 35 | |
| 36 // This class handles video encode acceleration by interfacing with a V4L2 | |
| 37 // device exposed by the codec hardware driver. The threading model of this | |
| 38 // class is the same as in the V4L2VideoDecodeAccelerator (from which class this | |
| 39 // was designed). | |
| 40 // This class may try to instantiate and use a V4L2ImageProcessor for input | |
| 41 // format conversion, if the input format requested via Initialize() is not | |
| 42 // accepted by the hardware codec. | |
| 43 class CONTENT_EXPORT V4L2VideoEncodeAccelerator | |
| 44 : public media::VideoEncodeAccelerator { | |
| 45 public: | |
| 46 explicit V4L2VideoEncodeAccelerator(const scoped_refptr<V4L2Device>& device); | |
| 47 ~V4L2VideoEncodeAccelerator() override; | |
| 48 | |
| 49 // media::VideoEncodeAccelerator implementation. | |
| 50 media::VideoEncodeAccelerator::SupportedProfiles GetSupportedProfiles() | |
| 51 override; | |
| 52 bool Initialize(media::VideoPixelFormat format, | |
| 53 const gfx::Size& input_visible_size, | |
| 54 media::VideoCodecProfile output_profile, | |
| 55 uint32_t initial_bitrate, | |
| 56 Client* client) override; | |
| 57 void Encode(const scoped_refptr<media::VideoFrame>& frame, | |
| 58 bool force_keyframe) override; | |
| 59 void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer) | |
| 60 override; | |
| 61 void RequestEncodingParametersChange(uint32_t bitrate, | |
| 62 uint32_t framerate) override; | |
| 63 void Destroy() override; | |
| 64 | |
| 65 private: | |
| 66 // Auto-destroy reference for BitstreamBuffer, for tracking buffers passed to | |
| 67 // this instance. | |
| 68 struct BitstreamBufferRef; | |
| 69 | |
| 70 // Record for codec input buffers. | |
| 71 struct InputRecord { | |
| 72 InputRecord(); | |
| 73 ~InputRecord(); | |
| 74 bool at_device; | |
| 75 scoped_refptr<media::VideoFrame> frame; | |
| 76 }; | |
| 77 | |
| 78 // Record for output buffers. | |
| 79 struct OutputRecord { | |
| 80 OutputRecord(); | |
| 81 ~OutputRecord(); | |
| 82 bool at_device; | |
| 83 linked_ptr<BitstreamBufferRef> buffer_ref; | |
| 84 void* address; | |
| 85 size_t length; | |
| 86 }; | |
| 87 | |
| 88 struct ImageProcessorInputRecord { | |
| 89 ImageProcessorInputRecord(); | |
| 90 ~ImageProcessorInputRecord(); | |
| 91 scoped_refptr<media::VideoFrame> frame; | |
| 92 bool force_keyframe; | |
| 93 }; | |
| 94 | |
| 95 enum { | |
| 96 kInitialFramerate = 30, | |
| 97 // These are rather subjectively tuned. | |
| 98 kInputBufferCount = 2, | |
| 99 kOutputBufferCount = 2, | |
| 100 kImageProcBufferCount = 2, | |
| 101 kOutputBufferSize = (2 * 1024 * 1024), | |
| 102 }; | |
| 103 | |
| 104 // Internal state of the encoder. | |
| 105 enum State { | |
| 106 kUninitialized, // Initialize() not yet called. | |
| 107 kInitialized, // Initialize() returned true; ready to start encoding. | |
| 108 kEncoding, // Encoding frames. | |
| 109 kError, // Error in encoder state. | |
| 110 }; | |
| 111 | |
| 112 // | |
| 113 // Callbacks for the image processor, if one is used. | |
| 114 // | |
| 115 | |
| 116 // Callback run by the image processor when a frame is ready for us to encode. | |
| 117 void FrameProcessed(bool force_keyframe, | |
| 118 base::TimeDelta timestamp, | |
| 119 int output_buffer_index); | |
| 120 | |
| 121 // Error callback for handling image processor errors. | |
| 122 void ImageProcessorError(); | |
| 123 | |
| 124 // | |
| 125 // Encoding tasks, to be run on encode_thread_. | |
| 126 // | |
| 127 | |
| 128 void EncodeTask(const scoped_refptr<media::VideoFrame>& frame, | |
| 129 bool force_keyframe); | |
| 130 | |
| 131 // Add a BitstreamBuffer to the queue of buffers ready to be used for encoder | |
| 132 // output. | |
| 133 void UseOutputBitstreamBufferTask( | |
| 134 std::unique_ptr<BitstreamBufferRef> buffer_ref); | |
| 135 | |
| 136 // Device destruction task. | |
| 137 void DestroyTask(); | |
| 138 | |
| 139 // Service I/O on the V4L2 devices. This task should only be scheduled from | |
| 140 // DevicePollTask(). | |
| 141 void ServiceDeviceTask(); | |
| 142 | |
| 143 // Handle the device queues. | |
| 144 void Enqueue(); | |
| 145 void Dequeue(); | |
| 146 // Enqueue a buffer on the corresponding queue. Returns false on fatal error. | |
| 147 bool EnqueueInputRecord(); | |
| 148 bool EnqueueOutputRecord(); | |
| 149 | |
| 150 // Attempt to start/stop device_poll_thread_. | |
| 151 bool StartDevicePoll(); | |
| 152 bool StopDevicePoll(); | |
| 153 | |
| 154 // | |
| 155 // Device tasks, to be run on device_poll_thread_. | |
| 156 // | |
| 157 | |
| 158 // The device task. | |
| 159 void DevicePollTask(bool poll_device); | |
| 160 | |
| 161 // | |
| 162 // Safe from any thread. | |
| 163 // | |
| 164 | |
| 165 // Error notification (using PostTask() to child thread, if necessary). | |
| 166 void NotifyError(Error error); | |
| 167 | |
| 168 // Set the encoder_state_ to kError and notify the client (if necessary). | |
| 169 void SetErrorState(Error error); | |
| 170 | |
| 171 // | |
| 172 // Other utility functions. Called on encoder_thread_, unless | |
| 173 // encoder_thread_ is not yet started, in which case the child thread can call | |
| 174 // these (e.g. in Initialize() or Destroy()). | |
| 175 // | |
| 176 | |
| 177 // Change encoding parameters. | |
| 178 void RequestEncodingParametersChangeTask(uint32_t bitrate, | |
| 179 uint32_t framerate); | |
| 180 | |
| 181 // Set up formats and initialize the device for them. | |
| 182 bool SetFormats(media::VideoPixelFormat input_format, | |
| 183 media::VideoCodecProfile output_profile); | |
| 184 | |
| 185 // Try to set up the device to the input format we were Initialized() with, | |
| 186 // or if the device doesn't support it, use one it can support, so that we | |
| 187 // can later instantiate a V4L2ImageProcessor to convert to it. | |
| 188 bool NegotiateInputFormat(media::VideoPixelFormat input_format); | |
| 189 | |
| 190 // Set up the device to the output format requested in Initialize(). | |
| 191 bool SetOutputFormat(media::VideoCodecProfile output_profile); | |
| 192 | |
| 193 // Initialize device controls with default values. | |
| 194 bool InitControls(); | |
| 195 | |
| 196 // Create the buffers we need. | |
| 197 bool CreateInputBuffers(); | |
| 198 bool CreateOutputBuffers(); | |
| 199 | |
| 200 // Destroy these buffers. | |
| 201 void DestroyInputBuffers(); | |
| 202 void DestroyOutputBuffers(); | |
| 203 | |
| 204 // Set controls in |ctrls| and return true if successful. | |
| 205 bool SetExtCtrls(std::vector<struct v4l2_ext_control> ctrls); | |
| 206 | |
| 207 // Recycle output buffer of image processor with |output_buffer_index|. | |
| 208 void ReuseImageProcessorOutputBuffer(int output_buffer_index); | |
| 209 | |
| 210 // Our original calling task runner for the child thread. | |
| 211 const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_; | |
| 212 | |
| 213 gfx::Size visible_size_; | |
| 214 // Input allocated size required by the device. | |
| 215 gfx::Size input_allocated_size_; | |
| 216 size_t output_buffer_byte_size_; | |
| 217 | |
| 218 // Formats for input frames and the output stream. | |
| 219 media::VideoPixelFormat device_input_format_; | |
| 220 size_t input_planes_count_; | |
| 221 uint32_t output_format_fourcc_; | |
| 222 | |
| 223 // | |
| 224 // Encoder state, owned and operated by encoder_thread_. | |
| 225 // Before encoder_thread_ has started, the encoder state is managed by | |
| 226 // the child (main) thread. After encoder_thread_ has started, the encoder | |
| 227 // thread should be the only one managing these. | |
| 228 // | |
| 229 | |
| 230 // Encoder state. | |
| 231 State encoder_state_; | |
| 232 | |
| 233 // We need to provide the stream header with every keyframe, to allow | |
| 234 // midstream decoding restarts. Store it here. | |
| 235 std::unique_ptr<uint8_t[]> stream_header_; | |
| 236 size_t stream_header_size_; | |
| 237 | |
| 238 // Video frames ready to be encoded. | |
| 239 std::queue<scoped_refptr<media::VideoFrame>> encoder_input_queue_; | |
| 240 | |
| 241 // Encoder device. | |
| 242 scoped_refptr<V4L2Device> device_; | |
| 243 | |
| 244 // Input queue state. | |
| 245 bool input_streamon_; | |
| 246 // Input buffers enqueued to device. | |
| 247 int input_buffer_queued_count_; | |
| 248 // Input buffers ready to use; LIFO since we don't care about ordering. | |
| 249 std::vector<int> free_input_buffers_; | |
| 250 // Mapping of int index to input buffer record. | |
| 251 std::vector<InputRecord> input_buffer_map_; | |
| 252 v4l2_memory input_memory_type_; | |
| 253 | |
| 254 // Output queue state. | |
| 255 bool output_streamon_; | |
| 256 // Output buffers enqueued to device. | |
| 257 int output_buffer_queued_count_; | |
| 258 // Output buffers ready to use; LIFO since we don't care about ordering. | |
| 259 std::vector<int> free_output_buffers_; | |
| 260 // Mapping of int index to output buffer record. | |
| 261 std::vector<OutputRecord> output_buffer_map_; | |
| 262 | |
| 263 // Bitstream buffers ready to be used to return encoded output, as a LIFO | |
| 264 // since we don't care about ordering. | |
| 265 std::vector<linked_ptr<BitstreamBufferRef> > encoder_output_queue_; | |
| 266 | |
| 267 // Image processor, if one is in use. | |
| 268 std::unique_ptr<V4L2ImageProcessor> image_processor_; | |
| 269 // Indexes of free image processor output buffers. Only accessed on child | |
| 270 // thread. | |
| 271 std::vector<int> free_image_processor_output_buffers_; | |
| 272 // Video frames ready to be processed. Only accessed on child thread. | |
| 273 std::queue<ImageProcessorInputRecord> image_processor_input_queue_; | |
| 274 // Mapping of int index to fds of image processor output buffer. | |
| 275 std::vector<std::vector<base::ScopedFD>> image_processor_output_buffer_map_; | |
| 276 | |
| 277 // This thread services tasks posted from the VEA API entry points by the | |
| 278 // child thread and device service callbacks posted from the device thread. | |
| 279 base::Thread encoder_thread_; | |
| 280 | |
| 281 // The device polling thread handles notifications of V4L2 device changes. | |
| 282 // TODO(sheu): replace this thread with an TYPE_IO encoder_thread_. | |
| 283 base::Thread device_poll_thread_; | |
| 284 | |
| 285 // To expose client callbacks from VideoEncodeAccelerator. | |
| 286 // NOTE: all calls to these objects *MUST* be executed on | |
| 287 // child_task_runner_. | |
| 288 base::WeakPtr<Client> client_; | |
| 289 std::unique_ptr<base::WeakPtrFactory<Client>> client_ptr_factory_; | |
| 290 | |
| 291 // WeakPtr<> pointing to |this| for use in posting tasks from the | |
| 292 // image_processor_ back to the child thread. | |
| 293 // Tasks posted onto encoder and poll threads can use base::Unretained(this), | |
| 294 // as both threads will not outlive this object. | |
| 295 base::WeakPtr<V4L2VideoEncodeAccelerator> weak_this_; | |
| 296 base::WeakPtrFactory<V4L2VideoEncodeAccelerator> weak_this_ptr_factory_; | |
| 297 | |
| 298 DISALLOW_COPY_AND_ASSIGN(V4L2VideoEncodeAccelerator); | |
| 299 }; | |
| 300 | |
| 301 } // namespace content | |
| 302 | |
| 303 #endif // CONTENT_COMMON_GPU_MEDIA_V4L2_VIDEO_ENCODE_ACCELERATOR_H_ | |
| OLD | NEW |