1 // Copyright 2023 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_ENCODE_COMPONENT_H 6 #define ANDROID_V4L2_CODEC2_COMPONENTS_ENCODE_COMPONENT_H 7 8 #include <atomic> 9 #include <limits> 10 #include <memory> 11 #include <optional> 12 #include <unordered_map> 13 #include <vector> 14 15 #include <C2Component.h> 16 #include <C2ComponentFactory.h> 17 #include <C2Config.h> 18 #include <C2Enum.h> 19 #include <C2Param.h> 20 #include <C2ParamDef.h> 21 #include <SimpleC2Interface.h> 22 #include <base/memory/scoped_refptr.h> 23 #include <base/single_thread_task_runner.h> 24 #include <base/synchronization/waitable_event.h> 25 #include <base/threading/thread.h> 26 #include <util/C2InterfaceHelper.h> 27 #include <v4l2_codec2/common/Common.h> 28 #include <v4l2_codec2/common/VideoPixelFormat.h> 29 30 namespace android { 31 32 struct BitstreamBuffer; 33 class FormatConverter; 34 class VideoEncoder; 35 class EncodeInterface; 36 37 std::optional<std::vector<VideoFramePlane>> getVideoFrameLayout(const C2ConstGraphicBlock& block, 38 VideoPixelFormat* format); 39 40 std::optional<uint32_t> getVideoFrameStride(VideoPixelFormat format, ui::Size size); 41 42 class EncodeComponent : public C2Component, public std::enable_shared_from_this<EncodeComponent> { 43 public: 44 virtual ~EncodeComponent() override; 45 46 // Implementation of the C2Component interface. 47 c2_status_t start() override; 48 c2_status_t stop() override; 49 c2_status_t reset() override; 50 c2_status_t release() override; 51 c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override; 52 c2_status_t drain_nb(drain_mode_t mode) override; 53 c2_status_t flush_sm(flush_mode_t mode, 54 std::list<std::unique_ptr<C2Work>>* const flushedWork) override; 55 c2_status_t announce_nb(const std::vector<C2WorkOutline>& items) override; 56 c2_status_t setListener_vb(const std::shared_ptr<Listener>& listener, 57 c2_blocking_t mayBlock) override; 58 std::shared_ptr<C2ComponentInterface> intf() override; 59 60 protected: 61 // Possible component states. 62 enum class ComponentState { 63 UNLOADED, // Initial state of component. 64 LOADED, // The component is stopped, ready to start running. 65 RUNNING, // The component is currently running. 66 ERROR, // An error occurred. 67 }; 68 69 EncodeComponent(C2String name, c2_node_id_t id, std::shared_ptr<EncodeInterface> interface); 70 71 EncodeComponent(const EncodeComponent&) = delete; 72 EncodeComponent& operator=(const EncodeComponent&) = delete; 73 74 // Initialize the V4L2 device for encoding with the requested configuration. 75 virtual bool initializeEncoder() = 0; 76 77 // Initialize the encoder on the encoder thread. 78 void startTask(bool* success, ::base::WaitableEvent* done); 79 // Destroy the encoder on the encoder thread. 80 void stopTask(::base::WaitableEvent* done); 81 // Queue a new encode work item on the encoder thread. 82 void queueTask(std::unique_ptr<C2Work> work); 83 // Drain all currently scheduled work on the encoder thread. The encoder will process all 84 // scheduled work and mark the last item as EOS, before processing any new work. 85 void drainTask(drain_mode_t drainMode); 86 // Called on the encoder thread when a drain is completed. 87 void onDrainDone(bool success); 88 // Flush all currently scheduled work on the encoder thread. The encoder will abort all 89 // scheduled work items, work that can be immediately aborted will be placed in |flushedWork|. 90 void flushTask(::base::WaitableEvent* done, 91 std::list<std::unique_ptr<C2Work>>* const flushedWork); 92 // Set the component listener on the encoder thread. 93 void setListenerTask(const std::shared_ptr<Listener>& listener, ::base::WaitableEvent* done); 94 95 // Update the |mBitrate| and |mFramerate| currently configured on the V4L2 device, to match the 96 // values requested by the codec 2.0 framework. 97 bool updateEncodingParameters(); 98 99 // Schedule the next encode operation on the V4L2 device. 100 void scheduleNextEncodeTask(); 101 // Encode the specified |block| with corresponding |index| and |timestamp|. 102 bool encode(C2ConstGraphicBlock block, uint64_t index, int64_t timestamp); 103 // Flush the encoder. 104 void flush(); 105 106 // Fetch a new output buffer from the output block pool with specified |size|. 107 void fetchOutputBlock(uint32_t size, std::unique_ptr<BitstreamBuffer>* buffer); 108 109 // Called on the encoder thread when the encoder is done using an input buffer. 110 void onInputBufferDone(uint64_t index); 111 // Called on the encoder thread when an output buffer is ready. 112 void onOutputBufferDone(size_t dataSize, int64_t timestamp, bool keyFrame, 113 std::unique_ptr<BitstreamBuffer> buffer); 114 115 // Helper function to find a work item in the output work queue by index. 116 C2Work* getWorkByIndex(uint64_t index); 117 // Helper function to find a work item in the output work queue by timestamp. 118 C2Work* getWorkByTimestamp(int64_t timestamp); 119 // Helper function to determine if the specified |work| item is finished. 120 bool isWorkDone(const C2Work& work) const; 121 // Notify the listener the specified |work| item is finished. 122 void reportWork(std::unique_ptr<C2Work> work); 123 124 // Configure the c2 block pool that will be used to create output buffers. 125 bool getBlockPool(); 126 127 // Notify the client an error occurred and switch to the error state. 128 void reportError(c2_status_t error); 129 130 // Change the state of the component. 131 void setComponentState(ComponentState state); 132 // Get the specified component |state| as string. 133 static const char* componentStateToString(ComponentState state); 134 135 // The underlying V4L2 encoder. 136 std::unique_ptr<VideoEncoder> mEncoder; 137 138 // The component's registered name. 139 const C2String mName; 140 // The component's id, provided by the C2 framework upon initialization. 141 const c2_node_id_t mId = 0; 142 // The component's interface implementation. 143 const std::shared_ptr<EncodeInterface> mInterface; 144 145 // Mutex used by the component to synchronize start/stop/reset/release calls, as the codec 2.0 146 // API can be accessed from any thread. 147 std::mutex mComponentLock; 148 149 // The component's listener to be notified when events occur, only accessed on encoder thread. 150 std::shared_ptr<Listener> mListener; 151 152 // The queue of encode work items waiting for free buffers in the input convertor. 153 std::queue<std::unique_ptr<C2Work>> mInputConverterQueue; 154 // An input format convertor will be used if the device doesn't support the video's format. 155 std::unique_ptr<FormatConverter> mInputFormatConverter; 156 157 // Pixel format of frames sent to V4L2 encoder, determined when the first input frame is queued. 158 VideoPixelFormat mInputPixelFormat = VideoPixelFormat::UNKNOWN; 159 // Layout of frames sent to V4L2 encoder, determined when the first input frame is queued. 160 std::vector<VideoFramePlane> mInputLayout; 161 162 // The bitrate currently configured on the v4l2 device. 163 uint32_t mBitrate = 0; 164 // The bitrate mode currently configured on the v4l2 device. 165 C2Config::bitrate_mode_t mBitrateMode = C2Config::BITRATE_CONST; 166 // The framerate currently configured on the v4l2 device. 167 uint32_t mFramerate = 0; 168 // Maximum valid framerate for current output level and input frame size. 169 uint32_t mMaxFramerate = std::numeric_limits<uint32_t>::max(); 170 // The timestamp of the last frame encoded, used to dynamically adjust the framerate. 171 std::optional<int64_t> mLastFrameTime; 172 173 // Whether we need to extract and submit CSD (codec-specific data, e.g. H.264 SPS). 174 bool mExtractCSD = false; 175 176 // The queue of encode work items currently being processed. 177 std::deque<std::unique_ptr<C2Work>> mWorkQueue; 178 179 // The output block pool. 180 std::shared_ptr<C2BlockPool> mOutputBlockPool; 181 182 // The component state, accessible from any thread as C2Component interface is not thread-safe. 183 std::atomic<ComponentState> mComponentState; 184 185 // The encoder thread on which all interaction with the V4L2 device is performed. 186 ::base::Thread mEncoderThread{"EncodeComponentThread"}; 187 // The task runner on the encoder thread. 188 scoped_refptr<::base::SequencedTaskRunner> mEncoderTaskRunner; 189 190 // The WeakPtrFactory used to get weak pointers of this. 191 ::base::WeakPtr<EncodeComponent> mWeakThis; 192 ::base::WeakPtrFactory<EncodeComponent> mWeakThisFactory{this}; 193 }; 194 195 } // namespace android 196 197 #endif // ANDROID_V4L2_CODEC2_COMPONENTS_ENCODE_COMPONENT_H 198