1 /*
2 * Copyright 2016 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 // #define LOG_NDEBUG 0
18 #define LOG_TAG "RequestTracker"
19
20 #include "request_tracker.h"
21
22 #include <cutils/log.h>
23
24 namespace default_camera_hal {
25
RequestTracker()26 RequestTracker::RequestTracker() {}
27
~RequestTracker()28 RequestTracker::~RequestTracker() {}
29
SetStreamConfiguration(const camera3_stream_configuration_t & config)30 void RequestTracker::SetStreamConfiguration(
31 const camera3_stream_configuration_t& config) {
32 // Clear the old configuration.
33 ClearStreamConfiguration();
34 // Add an entry to the buffer tracking map for each configured stream.
35 for (size_t i = 0; i < config.num_streams; ++i) {
36 buffers_in_flight_.emplace(config.streams[i], 0);
37 }
38 }
39
ClearStreamConfiguration()40 void RequestTracker::ClearStreamConfiguration() {
41 // The keys of the in flight buffer map are the configured streams.
42 buffers_in_flight_.clear();
43 }
44
45 // Helper: get the streams used by a request.
RequestStreams(const CaptureRequest & request)46 std::set<camera3_stream_t*> RequestStreams(const CaptureRequest& request) {
47 std::set<camera3_stream_t*> result;
48 if (request.input_buffer) {
49 result.insert(request.input_buffer->stream);
50 }
51 for (const auto& output_buffer : request.output_buffers) {
52 result.insert(output_buffer.stream);
53 }
54 return result;
55 }
56
Add(std::shared_ptr<CaptureRequest> request)57 bool RequestTracker::Add(std::shared_ptr<CaptureRequest> request) {
58 if (!CanAddRequest(*request)) {
59 return false;
60 }
61
62 // Add to the count for each stream used.
63 for (const auto stream : RequestStreams(*request)) {
64 ++buffers_in_flight_[stream];
65 }
66
67 // Store the request.
68 frames_in_flight_[request->frame_number] = request;
69
70 return true;
71 }
72
Remove(std::shared_ptr<CaptureRequest> request)73 bool RequestTracker::Remove(std::shared_ptr<CaptureRequest> request) {
74 if (!request) {
75 return false;
76 }
77
78 // Get the request.
79 const auto frame_number_request =
80 frames_in_flight_.find(request->frame_number);
81 if (frame_number_request == frames_in_flight_.end()) {
82 ALOGE("%s: Frame %u is not in flight.", __func__, request->frame_number);
83 return false;
84 } else if (request != frame_number_request->second) {
85 ALOGE(
86 "%s: Request for frame %u cannot be removed: "
87 "does not matched the stored request.",
88 __func__,
89 request->frame_number);
90 return false;
91 }
92
93 frames_in_flight_.erase(frame_number_request);
94
95 // Decrement the counts of used streams.
96 for (const auto stream : RequestStreams(*request)) {
97 --buffers_in_flight_[stream];
98 }
99
100 return true;
101 }
102
Clear(std::set<std::shared_ptr<CaptureRequest>> * requests)103 void RequestTracker::Clear(
104 std::set<std::shared_ptr<CaptureRequest>>* requests) {
105 // If desired, extract all the currently in-flight requests.
106 if (requests) {
107 for (auto& frame_number_request : frames_in_flight_) {
108 requests->insert(frame_number_request.second);
109 }
110 }
111
112 // Clear out all tracking.
113 frames_in_flight_.clear();
114 // Maintain the configuration, but reset counts.
115 for (auto& stream_count : buffers_in_flight_) {
116 stream_count.second = 0;
117 }
118 }
119
CanAddRequest(const CaptureRequest & request) const120 bool RequestTracker::CanAddRequest(const CaptureRequest& request) const {
121 // Check that it's not a duplicate.
122 if (frames_in_flight_.count(request.frame_number) > 0) {
123 ALOGE("%s: Already tracking a request with frame number %d.",
124 __func__,
125 request.frame_number);
126 return false;
127 }
128
129 // Check that each stream has space
130 // (which implicitly checks if it is configured).
131 for (const auto stream : RequestStreams(request)) {
132 if (StreamFull(stream)) {
133 ALOGE("%s: Stream %p is full.", __func__, stream);
134 return false;
135 }
136 }
137 return true;
138 }
139
StreamFull(const camera3_stream_t * handle) const140 bool RequestTracker::StreamFull(const camera3_stream_t* handle) const {
141 const auto it = buffers_in_flight_.find(handle);
142 if (it == buffers_in_flight_.end()) {
143 // Unconfigured streams are implicitly full.
144 ALOGV("%s: Stream %p is not a configured stream.", __func__, handle);
145 return true;
146 } else {
147 return it->second >= it->first->max_buffers;
148 }
149 }
150
InFlight(uint32_t frame_number) const151 bool RequestTracker::InFlight(uint32_t frame_number) const {
152 return frames_in_flight_.count(frame_number) > 0;
153 }
154
Empty() const155 bool RequestTracker::Empty() const {
156 return frames_in_flight_.empty();
157 }
158
159 } // namespace default_camera_hal
160