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