• 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 
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