• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef HARDWARE_GOOGLE_CAMERA_HAL_UTILS_RESULT_DISPATCHER_H_
18 #define HARDWARE_GOOGLE_CAMERA_HAL_UTILS_RESULT_DISPATCHER_H_
19 
20 #include <android-base/thread_annotations.h>
21 
22 #include <map>
23 #include <string>
24 #include <string_view>
25 #include <thread>
26 
27 #include "hal_types.h"
28 
29 namespace android {
30 namespace google_camera_hal {
31 
32 // ResultDispatcher dispatches capture results in the order of frame numbers,
33 // including result metadata, shutters, and stream buffers.
34 //
35 // The client can add results and shutters via AddResult() (or AddBatchResult())
36 // and AddShutter() in any order. ResultDispatcher will invoke
37 // ProcessCaptureResultFunc (or ProcessBatchCaptureResultFunc) and NotifyFunc to
38 // notify result metadata, shutters, and stream buffers in the in the order of
39 // increasing frame numbers.
40 class ResultDispatcher {
41  public:
42   // Create a ResultDispatcher.
43   // partial_result_count is the partial result count.
44   // process_capture_result is the callback to notify a capture result.
45   // process_batch_capture_result is the callback to notify multiple capture
46   // results at once.
47   // stream_config is the session stream configuration.
48   // notify is the function to notify shutter messages.
49   // notify_batch is the function to notify multiple shutter messages at once.
50   // If process_batch_capture_result is not null, it has the priority over
51   // process_capture_result.
52   static std::unique_ptr<ResultDispatcher> Create(
53       uint32_t partial_result_count,
54       ProcessCaptureResultFunc process_capture_result,
55       ProcessBatchCaptureResultFunc process_batch_capture_result,
56       NotifyFunc notify, NotifyBatchFunc notify_batch,
57       const StreamConfiguration& stream_config,
58       std::string_view name = "ResultDispatcher");
59 
60   virtual ~ResultDispatcher();
61 
62   // Add a pending request. This tells ResultDispatcher to watch for
63   // the shutter, result metadata, and stream buffers for this request,
64   // that will be added later via AddResult() and AddShutter().
65   status_t AddPendingRequest(const CaptureRequest& pending_request)
66       EXCLUDES(result_lock_);
67 
68   // Add a ready result. If the result doesn't belong to a pending request that
69   // was previously added via AddPendingRequest(), an error will be returned.
70   status_t AddResult(std::unique_ptr<CaptureResult> result);
71 
72   // Add a batch of results which contains multiple ready results.
73   status_t AddBatchResult(std::vector<std::unique_ptr<CaptureResult>> results);
74 
75   // Add a shutter for a frame number. If the frame number doesn't belong to a
76   // pending request that was previously added via AddPendingRequest(), an error
77   // will be returned.
78   status_t AddShutter(const ShutterMessage& shutter) EXCLUDES(result_lock_);
79 
80   // Add multiple shutters for frames.  If the frame number of any frame doesn't
81   // belong to a pending request that was previously added via
82   // AddPendingRequest(), an error will be returned.
83   status_t AddBatchShutter(const std::vector<ShutterMessage>& shutters)
84       EXCLUDES(result_lock_);
85 
86   // Add an error notification for a frame number. When this is called, we no
87   // longer wait for a shutter message or result metadata for the given frame.
88   status_t AddError(const ErrorMessage& error) EXCLUDES(result_lock_);
89 
90   // Remove a pending request.
91   void RemovePendingRequest(uint32_t frame_number) EXCLUDES(result_lock_);
92 
93   ResultDispatcher(uint32_t partial_result_count,
94                    ProcessCaptureResultFunc process_capture_result,
95                    ProcessBatchCaptureResultFunc process_batch_capture_result,
96                    NotifyFunc notify, NotifyBatchFunc notify_batch,
97                    const StreamConfiguration& stream_config,
98                    std::string_view name = "ResultDispatcher");
99 
100  private:
101   static constexpr uint32_t kCallbackThreadTimeoutMs = 500;
102   const uint32_t kPartialResultCount;
103 
104   // Define the request types. Normal is for general application.
105   // Reprocess is for reprocessing requests.
106   enum class RequestType : uint32_t {
107     kNormal = 0,
108     kReprocess,
109   };
110 
111   // Define the stream key types. Single stream type is for normal streams.
112   // Group stream type is for the group streams of multi-resolution streams.
113   enum class StreamKeyType : uint32_t {
114     kSingleStream = 0,
115     kGroupStream,
116   };
117 
118   // The key of the stream_pending_buffers_map_, which has different types.
119   // Type kSingleStream indicates the StreamKey represents a single stream, and
120   // the id will be the stream id.
121   // Type kGroupStream indicates the StreamKey represents a stream group, and
122   // the id will be the stream group id. All of the buffers of certain stream
123   // group will be tracked together, as there's only one buffer from the group
124   // streams should be returned each request.
125   typedef std::pair</*id=*/int32_t, StreamKeyType> StreamKey;
126 
127   // Define a pending shutter that will be ready later when AddShutter() is
128   // called.
129   struct PendingShutter {
130     int64_t timestamp_ns = 0;
131     int64_t readout_timestamp_ns = 0;
132     bool ready = false;
133   };
134 
135   // Define a pending buffer that will be ready later when AddResult() is
136   // called.
137   struct PendingBuffer {
138     StreamBuffer buffer = {};
139     bool is_input = false;
140     bool ready = false;
141   };
142 
143   // Define a pending result metadata that will be ready later when AddResult()
144   // is called.
145   struct PendingResultMetadata {
146     std::unique_ptr<HalCameraMetadata> metadata;
147     std::vector<PhysicalCameraMetadata> physical_metadata;
148     uint32_t partial_result_count = 0;
149     bool ready = false;
150   };
151 
152   // Template class for pending data queues.
153   // Pending data can be shutter, early/final result metadata, buffer, and each
154   // type of data has its own queue. Handles having multiple queues per request
155   // type, adds to the appropriate queue and checks all queues for ready data.
156   template <typename FrameData>
157   class DispatchQueue {
158    public:
159     DispatchQueue(std::string_view dispatcher_name = "DefaultDispatcher",
160                   std::string_view data_name = "DefaultData");
161 
162     // Add a request to the dispatch queue that will later be populated with
163     // results.
164     status_t AddRequest(uint32_t frame_number, RequestType request_type);
165 
166     // Remove request for frame number from data queue
167     void RemoveRequest(uint32_t frame_number);
168 
169     // Add results for the request in the queue of the same frame number
170     status_t AddResult(uint32_t frame_number, FrameData result);
171 
172     // Move ready data to caller, returns failure status if no data is ready
173     // Data is ready if its result has been added and is the first in its queue
174     status_t GetReadyData(uint32_t& frame_number, FrameData& ready_data);
175 
176     void PrintTimeoutMessages();
177 
178    private:
179     // Name of the dispatcher for debug messages
180     std::string_view dispatcher_name_;
181     // Name of the data (shutter, metadata, buffer + stream key) for debug
182     // messages
183     std::string data_name_;
184 
185     // Queue for data of reprocess request types
186     std::map<uint32_t, FrameData> reprocess_request_map_;
187     // Queue for data of normal request types
188     std::map<uint32_t, FrameData> normal_request_map_;
189   };
190 
191   // Add a pending shutter, result metadata, and buffers for a frame number.
192   status_t AddPendingRequestLocked(const CaptureRequest& pending_request)
193       EXCLUSIVE_LOCKS_REQUIRED(result_lock_);
194 
195   // Add a pending buffer for the associated stream
196   status_t AddPendingBufferLocked(uint32_t frame_number,
197                                   const StreamBuffer& buffer,
198                                   RequestType request_type)
199       EXCLUSIVE_LOCKS_REQUIRED(result_lock_);
200 
201   // Remove pending shutter, result metadata, and buffers for a frame number.
202   void RemovePendingRequestLocked(uint32_t frame_number)
203       EXCLUSIVE_LOCKS_REQUIRED(result_lock_);
204 
205   // Add result metadata and buffers to the storage to send them from the notify
206   // callback thread.
207   status_t AddResultImpl(std::unique_ptr<CaptureResult> result);
208 
209   // Add a shutter to `pending_shutters_`.
210   status_t AddShutterLocked(uint32_t frame_number, int64_t timestamp_ns,
211                             int64_t readout_timestamp_ns) REQUIRES(result_lock_);
212 
213   // Compose a capture result which contains a result metadata.
214   std::unique_ptr<CaptureResult> MakeResultMetadata(
215       uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
216       std::vector<PhysicalCameraMetadata> physical_metadata,
217       uint32_t partial_result);
218 
219   // Invoke the capture result callback to notify capture results.
220   void NotifyCaptureResults(std::vector<std::unique_ptr<CaptureResult>> results);
221 
222   status_t AddResultMetadata(
223       uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
224       std::vector<PhysicalCameraMetadata> physical_metadata,
225       uint32_t partial_result) EXCLUDES(result_lock_);
226   ;
227 
228   status_t AddBuffer(uint32_t frame_number, StreamBuffer buffer, bool is_input)
229       EXCLUDES(result_lock_);
230 
231   // Check all pending shutters and invoke notify_ with shutters that are ready.
232   void NotifyShutters() EXCLUDES(result_lock_);
233 
234   // Check all pending shutters and invoke notify_batch_ with shutters that are ready.
235   void NotifyBatchShutters() EXCLUDES(result_lock_);
236 
237   // Check all pending result metadata and invoke the capture result callback
238   // with the result metadata that are ready.
239   void NotifyResultMetadata() EXCLUDES(result_lock_);
240 
241   // Get a result with a buffer that is ready to be notified via the capture
242   // result callback.
243   status_t GetReadyBufferResult(std::unique_ptr<CaptureResult>* result)
244       EXCLUDES(result_lock_);
245 
246   // Check all pending buffers and invoke notify_ with buffers that are ready.
247   void NotifyBuffers();
248 
249   // Thread loop to check pending shutters, result metadata, and buffers. It
250   // notifies the client when one is ready.
251   void NotifyCallbackThreadLoop();
252 
253   void PrintTimeoutMessages() EXCLUDES(result_lock_);
254 
255   // Initialize the group stream ids map if needed. Must be protected with
256   // result_lock_.
257   void InitializeGroupStreamIdsMap(const StreamConfiguration& stream_config)
258       EXCLUDES(result_lock_);
259 
260   // Gets the shutter data  from `pending_shutters_`, and fills out `message` with it.
261   status_t GetPendingShutterNotificationLocked(NotifyMessage& message)
262       REQUIRES(result_lock_);
263 
264   // Name used for debugging purpose to disambiguate multiple ResultDispatchers.
265   std::string name_;
266 
267   std::mutex result_lock_;
268 
269   // Queue for shutter data.
270   DispatchQueue<PendingShutter> pending_shutters_ GUARDED_BY(result_lock_);
271   // Queue for early result metadata.
272   DispatchQueue<PendingResultMetadata> pending_early_metadata_
273       GUARDED_BY(result_lock_);
274   // Queue for final result metadata.
275   DispatchQueue<PendingResultMetadata> pending_final_metadata_
276       GUARDED_BY(result_lock_);
277 
278   // Maps from a stream or stream group to a queue for buffer data.
279   // Protected by result_lock_.
280   // For single streams, pending buffers would be tracked by streams.
281   // For multi-resolution streams, camera HAL can return only one stream buffer
282   // within the same stream group each request. So all of the buffers of certain
283   // stream group will be tracked together via a single map.
284   // TODO: b/347771069 - Update to use unordered_map
285   std::map<StreamKey, DispatchQueue<PendingBuffer>> stream_pending_buffers_map_
286       GUARDED_BY(result_lock_);
287 
288   // Create a StreamKey for a stream
289   inline StreamKey CreateStreamKey(int32_t stream_id) const;
290 
291   // Dump a StreamKey to a debug string
292   inline std::string DumpStreamKey(const StreamKey& stream_key) const;
293 
294   std::mutex process_capture_result_lock_;
295   ProcessCaptureResultFunc process_capture_result_;
296   ProcessBatchCaptureResultFunc process_batch_capture_result_;
297   NotifyFunc notify_;
298   NotifyBatchFunc notify_batch_;
299 
300   // A thread to run NotifyCallbackThreadLoop().
301   std::thread notify_callback_thread_;
302 
303   std::mutex notify_callback_lock_;
304 
305   // Condition to wake up notify_callback_thread_. Used with
306   // notify_callback_lock.
307   std::condition_variable notify_callback_condition_;
308 
309   // Protected by notify_callback_lock.
310   bool notify_callback_thread_exiting_ = false;
311 
312   // State of callback thread is notified or not.
313   volatile bool is_result_shutter_updated_ = false;
314 
315   // A map of group streams only, from stream ID to the group ID it belongs.
316   std::map</*stream id=*/int32_t, /*group id=*/int32_t> group_stream_map_;
317 };
318 
319 }  // namespace google_camera_hal
320 }  // namespace android
321 
322 #endif  // HARDWARE_GOOGLE_CAMERA_HAL_UTILS_RESULT_DISPATCHER_H_
323