1 // Copyright 2020 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 ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_ENCODE_COMPONENT_H 6 #define ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_ENCODE_COMPONENT_H 7 8 #include <atomic> 9 #include <memory> 10 #include <optional> 11 12 #include <C2Component.h> 13 #include <C2ComponentFactory.h> 14 #include <C2Config.h> 15 #include <C2Enum.h> 16 #include <C2Param.h> 17 #include <C2ParamDef.h> 18 #include <SimpleC2Interface.h> 19 #include <base/memory/scoped_refptr.h> 20 #include <base/single_thread_task_runner.h> 21 #include <base/synchronization/waitable_event.h> 22 #include <base/threading/thread.h> 23 #include <util/C2InterfaceHelper.h> 24 25 #include <size.h> 26 #include <v4l2_codec2/common/FormatConverter.h> 27 #include <v4l2_codec2/components/V4L2EncodeInterface.h> 28 #include <video_frame_layout.h> 29 30 namespace media { 31 class V4L2Device; 32 class V4L2ReadableBuffer; 33 class V4L2Queue; 34 } // namespace media 35 36 namespace android { 37 38 struct VideoFramePlane; 39 40 class V4L2EncodeComponent : public C2Component, 41 public std::enable_shared_from_this<V4L2EncodeComponent> { 42 public: 43 // Create a new instance of the V4L2EncodeComponent. 44 static std::shared_ptr<C2Component> create(C2String name, c2_node_id_t id, 45 std::shared_ptr<C2ReflectorHelper> helper, 46 C2ComponentFactory::ComponentDeleter deleter); 47 48 virtual ~V4L2EncodeComponent() override; 49 50 // Implementation of the C2Component interface. 51 c2_status_t start() override; 52 c2_status_t stop() override; 53 c2_status_t reset() override; 54 c2_status_t release() override; 55 c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override; 56 c2_status_t drain_nb(drain_mode_t mode) override; 57 c2_status_t flush_sm(flush_mode_t mode, 58 std::list<std::unique_ptr<C2Work>>* const flushedWork) override; 59 c2_status_t announce_nb(const std::vector<C2WorkOutline>& items) override; 60 c2_status_t setListener_vb(const std::shared_ptr<Listener>& listener, 61 c2_blocking_t mayBlock) override; 62 std::shared_ptr<C2ComponentInterface> intf() override; 63 64 private: 65 class InputFrame { 66 public: 67 // Create an input frame from a C2GraphicBlock. 68 static std::unique_ptr<InputFrame> Create(const C2ConstGraphicBlock& block); 69 ~InputFrame() = default; 70 getFDs()71 const std::vector<int>& getFDs() const { return mFds; } 72 73 private: InputFrame(std::vector<int> fds)74 InputFrame(std::vector<int> fds) : mFds(std::move(fds)) {} 75 const std::vector<int> mFds; 76 }; 77 78 // Possible component states. 79 enum class ComponentState { 80 UNLOADED, // Initial state of component. 81 LOADED, // The component is stopped, ready to start running. 82 RUNNING, // The component is currently running. 83 ERROR, // An error occurred. 84 }; 85 86 // Possible encoder states. 87 enum class EncoderState { 88 UNINITIALIZED, // Not initialized yet or initialization failed. 89 WAITING_FOR_INPUT, // Waiting for work to be queued. 90 WAITING_FOR_INPUT_BUFFERS, // Waiting for V4L2 input queue buffers. 91 ENCODING, // Queuing input buffers. 92 DRAINING, // Flushing encoder. 93 ERROR, // encoder encountered an error. 94 }; 95 96 V4L2EncodeComponent(C2String name, c2_node_id_t id, 97 std::shared_ptr<V4L2EncodeInterface> interface); 98 99 V4L2EncodeComponent(const V4L2EncodeComponent&) = delete; 100 V4L2EncodeComponent& operator=(const V4L2EncodeComponent&) = delete; 101 102 // Initialize the encoder on the encoder thread. 103 void startTask(bool* success, ::base::WaitableEvent* done); 104 // Destroy the encoder on the encoder thread. 105 void stopTask(::base::WaitableEvent* done); 106 // Queue a new encode work item on the encoder thread. 107 void queueTask(std::unique_ptr<C2Work> work); 108 // Drain all currently scheduled work on the encoder thread. The encoder will process all 109 // scheduled work and mark the last item as EOS, before processing any new work. 110 void drainTask(drain_mode_t drainMode); 111 // Called on the encoder thread when a drain is completed. 112 void onDrainDone(bool done); 113 // Flush all currently scheduled work on the encoder thread. The encoder will abort all 114 // scheduled work items, work that can be immediately aborted will be placed in |flushedWork|. 115 void flushTask(::base::WaitableEvent* done, 116 std::list<std::unique_ptr<C2Work>>* const flushedWork); 117 // Set the component listener on the encoder thread. 118 void setListenerTask(const std::shared_ptr<Listener>& listener, ::base::WaitableEvent* done); 119 120 // Initialize the V4L2 device for encoding with the requested configuration. 121 bool initializeEncoder(); 122 // Configure input format on the V4L2 device. 123 bool configureInputFormat(media::VideoPixelFormat inputFormat); 124 // Configure output format on the V4L2 device. 125 bool configureOutputFormat(media::VideoCodecProfile outputProfile); 126 // Configure required and optional controls on the V4L2 device. 127 bool configureDevice(media::VideoCodecProfile outputProfile, 128 std::optional<const uint8_t> outputH264Level); 129 // Update the |mBitrate| and |mFramerate| currently configured on the V4L2 device, to match the 130 // values requested by the codec 2.0 framework. 131 bool updateEncodingParameters(); 132 133 // Schedule the next encode operation on the V4L2 device. 134 void scheduleNextEncodeTask(); 135 // Encode the specified |block| with corresponding |index| and |timestamp|. 136 bool encode(C2ConstGraphicBlock block, uint64_t index, int64_t timestamp); 137 // Drain the encoder. 138 void drain(); 139 // Flush the encoder. 140 void flush(); 141 142 // Fetch a new output buffer from the output block pool. 143 std::shared_ptr<C2LinearBlock> fetchOutputBlock(); 144 145 // Called on the encoder thread when the encoder is done using an input buffer. 146 void onInputBufferDone(uint64_t index); 147 // Called on the encoder thread when an output buffer is ready. 148 void onOutputBufferDone(uint32_t payloadSize, bool keyFrame, int64_t timestamp, 149 std::shared_ptr<C2LinearBlock> outputBlock); 150 151 // Helper function to find a work item in the output work queue by index. 152 C2Work* getWorkByIndex(uint64_t index); 153 // Helper function to find a work item in the output work queue by timestamp. 154 C2Work* getWorkByTimestamp(int64_t timestamp); 155 // Helper function to determine if the specified |work| item is finished. 156 bool isWorkDone(const C2Work& work) const; 157 // Notify the listener the specified |work| item is finished. 158 void reportWork(std::unique_ptr<C2Work> work); 159 160 // Attempt to start the V4L2 device poller. 161 bool startDevicePoll(); 162 // Attempt to stop the V4L2 device poller. 163 bool stopDevicePoll(); 164 // Called by the V4L2 device poller on the |mEncoderTaskRunner| whenever an error occurred. 165 void onPollError(); 166 // Service I/O on the V4L2 device, called by the V4L2 device poller on the |mEncoderTaskRunner|. 167 void serviceDeviceTask(bool event); 168 169 // Enqueue an input buffer to be encoded on the device input queue. Returns whether the 170 // operation was successful. 171 bool enqueueInputBuffer(std::unique_ptr<InputFrame> frame, media::VideoPixelFormat format, 172 const std::vector<VideoFramePlane>& planes, int64_t index, 173 int64_t timestamp); 174 // Enqueue an output buffer to store the encoded bitstream on the device output queue. Returns 175 // whether the operation was successful. 176 bool enqueueOutputBuffer(); 177 // Dequeue an input buffer the V4L2 device has finished encoding on the device input queue. 178 // Returns whether a buffer could be dequeued. 179 bool dequeueInputBuffer(); 180 // Dequeue an output buffer containing the encoded bitstream from the device output queue. The 181 // bitstream is copied into another buffer that is sent to the client, after which the output 182 // buffer is returned to the queue. Returns whether the operation was successful. 183 bool dequeueOutputBuffer(); 184 185 // Create input buffers on the V4L2 device input queue. 186 bool createInputBuffers(); 187 // Create output buffers on the V4L2 device output queue. 188 bool createOutputBuffers(); 189 // Destroy the input buffers on the V4L2 device input queue. 190 void destroyInputBuffers(); 191 // Destroy the output buffers on the V4L2 device output queue. 192 void destroyOutputBuffers(); 193 194 // Notify the client an error occurred and switch to the error state. 195 void reportError(c2_status_t error); 196 197 // Change the state of the component. 198 void setComponentState(ComponentState state); 199 // Change the state of the encoder, only called on the encoder thread. 200 void setEncoderState(EncoderState state); 201 // Get the specified component |state| as string. 202 static const char* componentStateToString(ComponentState state); 203 // Get the specified encoder |state| as string. 204 static const char* encoderStateToString(EncoderState state); 205 206 // The component's registered name. 207 const C2String mName; 208 // The component's id, provided by the C2 framework upon initialization. 209 const c2_node_id_t mId = 0; 210 // The component's interface implementation. 211 const std::shared_ptr<V4L2EncodeInterface> mInterface; 212 213 // Mutex used by the component to synchronize start/stop/reset/release calls, as the codec 2.0 214 // API can be accessed from any thread. 215 std::mutex mComponentLock; 216 217 // The component's listener to be notified when events occur, only accessed on encoder thread. 218 std::shared_ptr<Listener> mListener; 219 220 // The V4L2 device used to interact with the driver, only accessed on encoder thread. 221 scoped_refptr<media::V4L2Device> mDevice; 222 scoped_refptr<media::V4L2Queue> mInputQueue; 223 scoped_refptr<media::V4L2Queue> mOutputQueue; 224 225 // The video stream's visible size. 226 media::Size mVisibleSize; 227 // The video stream's coded size. 228 media::Size mInputCodedSize; 229 // The input layout configured on the V4L2 device. 230 std::optional<media::VideoFrameLayout> mInputLayout; 231 // An input format convertor will be used if the device doesn't support the video's format. 232 std::unique_ptr<FormatConverter> mInputFormatConverter; 233 // Required output buffer byte size. 234 uint32_t mOutputBufferSize = 0; 235 236 // The bitrate currently configured on the v4l2 device. 237 uint32_t mBitrate = 0; 238 // The framerate currently configured on the v4l2 device. 239 uint32_t mFramerate = 0; 240 241 // How often we want to request the V4L2 device to create a key frame. 242 uint32_t mKeyFramePeriod = 0; 243 // Key frame counter, a key frame will be requested each time it reaches zero. 244 uint32_t mKeyFrameCounter = 0; 245 246 // Whether we extracted and submitted CSD (codec-specific data, e.g. H.264 SPS) to the framework. 247 bool mCSDSubmitted = false; 248 249 // The queue of encode work items to be processed. 250 std::queue<std::unique_ptr<C2Work>> mInputWorkQueue; 251 // The queue of encode work items currently being processed. 252 std::deque<std::unique_ptr<C2Work>> mOutputWorkQueue; 253 254 // List of work item indices and frames associated with each buffer in the device input queue. 255 std::vector<std::pair<int64_t, std::unique_ptr<InputFrame>>> mInputBuffersMap; 256 257 // Map of buffer indices and output blocks associated with each buffer in the output queue. This 258 // map keeps the C2LinearBlock buffers alive so we can avoid duplicated fds. 259 std::vector<std::shared_ptr<C2LinearBlock>> mOutputBuffersMap; 260 // The output block pool. 261 std::shared_ptr<C2BlockPool> mOutputBlockPool; 262 263 // The component state, accessible from any thread as C2Component interface is not thread-safe. 264 std::atomic<ComponentState> mComponentState; 265 // The current state of the encoder, only accessed on the encoder thread. 266 EncoderState mEncoderState = EncoderState::UNINITIALIZED; 267 268 // The encoder thread on which all interaction with the V4L2 device is performed. 269 ::base::Thread mEncoderThread{"V4L2EncodeComponentThread"}; 270 // The task runner on the encoder thread. 271 scoped_refptr<::base::SequencedTaskRunner> mEncoderTaskRunner; 272 273 // The WeakPtrFactory used to get weak pointers of this. 274 ::base::WeakPtr<V4L2EncodeComponent> mWeakThis; 275 ::base::WeakPtrFactory<V4L2EncodeComponent> mWeakThisFactory{this}; 276 }; 277 278 } // namespace android 279 280 #endif // ANDROID_V4L2_CODEC2_COMPONENTS_V4L2_ENCODE_COMPONENT_H 281