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