summaryrefslogtreecommitdiff
path: root/common/hal/utils/result_dispatcher.h
blob: d61024963d4640e44818964de6bbd02c30184edc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef HARDWARE_GOOGLE_CAMERA_HAL_UTILS_RESULT_DISPATCHER_H_
#define HARDWARE_GOOGLE_CAMERA_HAL_UTILS_RESULT_DISPATCHER_H_

#include <map>
#include <string>
#include <string_view>
#include <thread>

#include "hal_types.h"

namespace android {
namespace google_camera_hal {

// ResultDispatcher dispatches capture results in the order of frame numbers,
// including result metadata, shutters, and stream buffers.
//
// The client can add results and shutters via AddResult() and AddShutter() in
// any order. ResultDispatcher will invoke ProcessCaptureResultFunc and
// NotifyFunc to notify result metadata, shutters, and stream buffers in the
// in the order of increasing frame numbers.
class ResultDispatcher {
 public:
  // Create a ResultDispatcher.
  // partial_result_count is the partial result count.
  // process_capture_result is the function to notify capture results.
  // notify is the function to notify shutter messages.
  static std::unique_ptr<ResultDispatcher> Create(
      uint32_t partial_result_count,
      ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
      std::string_view name = "ResultDispatcher");

  virtual ~ResultDispatcher();

  // Add a pending request. This tells ResultDispatcher to watch for
  // the shutter, result metadata, and stream buffers for this request,
  // that will be added later via AddResult() and AddShutter().
  status_t AddPendingRequest(const CaptureRequest& pending_request);

  // Add a ready result. If the result doesn't belong to a pending request that
  // was previously added via AddPendingRequest(), an error will be returned.
  status_t AddResult(std::unique_ptr<CaptureResult> result);

  // Add a shutter for a frame number. If the frame number doesn't belong to a
  // pending request that was previously added via AddPendingRequest(), an error
  // will be returned.
  status_t AddShutter(uint32_t frame_number, int64_t timestamp_ns,
                      int64_t readout_timestamp_ns);

  // Add an error notification for a frame number. When this is called, we no
  // longer wait for a shutter message or result metadata for the given frame.
  status_t AddError(const ErrorMessage& error);

  // Remove a pending request.
  void RemovePendingRequest(uint32_t frame_number);

  ResultDispatcher(uint32_t partial_result_count,
                   ProcessCaptureResultFunc process_capture_result,
                   NotifyFunc notify,
                   std::string_view name = "ResultDispatcher");

 private:
  static constexpr uint32_t kCallbackThreadTimeoutMs = 500;
  const uint32_t kPartialResultCount;

  // Define a pending shutter that will be ready later when AddShutter() is
  // called.
  struct PendingShutter {
    int64_t timestamp_ns = 0;
    int64_t readout_timestamp_ns = 0;
    bool ready = false;
  };

  // Define a pending buffer that will be ready later when AddResult() is called.
  struct PendingBuffer {
    StreamBuffer buffer = {};
    bool is_input = false;
    bool ready = false;
  };

  // Define a pending final result metadata that will be ready later when
  // AddResult() is called.
  struct PendingFinalResultMetadata {
    std::unique_ptr<HalCameraMetadata> metadata;
    std::vector<PhysicalCameraMetadata> physical_metadata;
    bool ready = false;
  };

  // Add a pending request for a frame. Must be protected with result_lock_.
  status_t AddPendingRequestLocked(const CaptureRequest& pending_request);

  // Add a pending shutter for a frame. Must be protected with result_lock_.
  status_t AddPendingShutterLocked(uint32_t frame_number);

  // Add a pending final metadata for a frame. Must be protected with
  // result_lock_.
  status_t AddPendingFinalResultMetadataLocked(uint32_t frame_number);

  // Add a pending buffer for a frame. Must be protected with result_lock_.
  status_t AddPendingBufferLocked(uint32_t frame_number,
                                  const StreamBuffer& buffer, bool is_input);

  // Remove pending shutter, result metadata, and buffers for a frame number.
  void RemovePendingRequestLocked(uint32_t frame_number);

  // Invoke process_capture_result_ to notify metadata.
  void NotifyResultMetadata(uint32_t frame_number,
                            std::unique_ptr<HalCameraMetadata> metadata,
                            std::vector<PhysicalCameraMetadata> physical_metadata,
                            uint32_t partial_result);

  status_t AddFinalResultMetadata(
      uint32_t frame_number, std::unique_ptr<HalCameraMetadata> final_metadata,
      std::vector<PhysicalCameraMetadata> physical_metadata);

  status_t AddResultMetadata(
      uint32_t frame_number, std::unique_ptr<HalCameraMetadata> metadata,
      std::vector<PhysicalCameraMetadata> physical_metadata,
      uint32_t partial_result);

  status_t AddBuffer(uint32_t frame_number, StreamBuffer buffer);

  // Get a shutter message that is ready to be notified via notify_.
  status_t GetReadyShutterMessage(NotifyMessage* message);

  // Get a final metadata that is ready to be notified via
  // process_capture_result_.
  status_t GetReadyFinalMetadata(
      uint32_t* frame_number, std::unique_ptr<HalCameraMetadata>* final_metadata,
      std::vector<PhysicalCameraMetadata>* physical_metadata);

  // Get a result with a buffer that is ready to be notified via
  // process_capture_result_.
  status_t GetReadyBufferResult(std::unique_ptr<CaptureResult>* result);

  // Check all pending shutters and invoke notify_ with shutters that are ready.
  void NotifyShutters();

  // Check all pending final result metadata and invoke process_capture_result_
  // with final result metadata that are ready.
  void NotifyFinalResultMetadata();

  // Check all pending buffers and invoke notify_ with buffers that are ready.
  void NotifyBuffers();

  // Thread loop to check pending shutters, result metadata, and buffers. It
  // notifies the client when one is ready.
  void NotifyCallbackThreadLoop();

  void PrintTimeoutMessages();

  // Name used for debugging purpose to disambiguate multiple ResultDispatchers.
  std::string name_;

  std::mutex result_lock_;

  // Maps from frame numbers to pending shutters.
  // Protected by result_lock_.
  std::map<uint32_t, PendingShutter> pending_shutters_;

  // Maps from a stream ID to "a map from a frame number to a pending buffer."
  // Protected by result_lock_.
  std::map<uint32_t, std::map<uint32_t, PendingBuffer>> stream_pending_buffers_map_;

  // Maps from a stream ID to pending result metadata.
  // Protected by result_lock_.
  std::map<uint32_t, PendingFinalResultMetadata> pending_final_metadata_;

  std::mutex process_capture_result_lock_;
  ProcessCaptureResultFunc process_capture_result_;
  NotifyFunc notify_;

  // A thread to run NotifyCallbackThreadLoop().
  std::thread notify_callback_thread_;

  std::mutex notify_callback_lock_;

  // Condition to wake up notify_callback_thread_. Used with notify_callback_lock.
  std::condition_variable notify_callback_condition_;

  // Protected by notify_callback_lock.
  bool notify_callback_thread_exiting_ = false;

  // State of callback thread is notified or not.
  volatile bool is_result_shutter_updated_ = false;
};

}  // namespace google_camera_hal
}  // namespace android

#endif  // HARDWARE_GOOGLE_CAMERA_HAL_UTILS_RESULT_DISPATCHER_H_