blob: 09f634d13d55239b9c2d9795beafff289117dd61 [file] [log] [blame]
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -07001/*
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#include "request_tracker.h"
18
19// #define LOG_NDEBUG 0
20#define LOG_TAG "RequestTracker"
21#include <cutils/log.h>
22
23namespace default_camera_hal {
24
25RequestTracker::RequestTracker() {}
26
27RequestTracker::~RequestTracker() {}
28
29void RequestTracker::SetStreamConfiguration(
30 const camera3_stream_configuration_t& config) {
31 // Clear the old configuration.
32 ClearStreamConfiguration();
33 // Add an entry to the buffer tracking map for each configured stream.
34 for (size_t i = 0; i < config.num_streams; ++i) {
35 buffers_in_flight_.emplace(config.streams[i], 0);
36 }
37}
38
39void RequestTracker::ClearStreamConfiguration() {
40 // The keys of the in flight buffer map are the configured streams.
41 buffers_in_flight_.clear();
42}
43
44// Helper: get the streams used by a request.
45std::set<camera3_stream_t*> RequestStreams(const CaptureRequest& request) {
46 std::set<camera3_stream_t*> result;
47 if (request.input_buffer) {
48 result.insert(request.input_buffer->stream);
49 }
50 for (const auto& output_buffer : request.output_buffers) {
51 result.insert(output_buffer.stream);
52 }
53 return std::move(result);
54}
55
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -070056bool RequestTracker::Add(std::shared_ptr<CaptureRequest> request) {
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -070057 if (!CanAddRequest(*request)) {
58 return false;
59 }
60
61 // Add to the count for each stream used.
62 for (const auto stream : RequestStreams(*request)) {
63 ++buffers_in_flight_[stream];
64 }
65
66 // Store the request.
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -070067 frames_in_flight_[request->frame_number] = request;
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -070068
69 return true;
70}
71
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -070072bool RequestTracker::Remove(std::shared_ptr<CaptureRequest> request) {
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -080073 if (!request) {
74 return false;
75 }
76
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -070077 // Get the request.
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -080078 const auto frame_number_request =
79 frames_in_flight_.find(request->frame_number);
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -070080 if (frame_number_request == frames_in_flight_.end()) {
81 ALOGE("%s: Frame %u is not in flight.", __func__, request->frame_number);
82 return false;
83 } else if (request != frame_number_request->second) {
84 ALOGE(
85 "%s: Request for frame %u cannot be removed: "
86 "does not matched the stored request.",
87 __func__,
88 request->frame_number);
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -070089 return false;
90 }
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -070091
92 frames_in_flight_.erase(frame_number_request);
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -070093
94 // Decrement the counts of used streams.
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -070095 for (const auto stream : RequestStreams(*request)) {
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -070096 --buffers_in_flight_[stream];
97 }
98
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -070099 return true;
100}
101
102void RequestTracker::Clear(
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -0700103 std::set<std::shared_ptr<CaptureRequest>>* requests) {
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -0700104 // If desired, extract all the currently in-flight requests.
105 if (requests) {
106 for (auto& frame_number_request : frames_in_flight_) {
Ari Hausman-Cohen0b2113c2016-10-03 13:43:13 -0700107 requests->insert(frame_number_request.second);
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -0700108 }
109 }
110
111 // Clear out all tracking.
112 frames_in_flight_.clear();
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800113 // Maintain the configuration, but reset counts.
114 for (auto& stream_count : buffers_in_flight_) {
115 stream_count.second = 0;
116 }
Ari Hausman-Cohencb11a4d2016-09-19 17:57:37 -0700117}
118
119bool RequestTracker::CanAddRequest(const CaptureRequest& request) const {
120 // Check that it's not a duplicate.
121 if (frames_in_flight_.count(request.frame_number) > 0) {
122 ALOGE("%s: Already tracking a request with frame number %d.",
123 __func__,
124 request.frame_number);
125 return false;
126 }
127
128 // Check that each stream has space
129 // (which implicitly checks if it is configured).
130 bool result = true;
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
140bool 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
151bool RequestTracker::InFlight(uint32_t frame_number) const {
152 return frames_in_flight_.count(frame_number) > 0;
153}
154
155bool RequestTracker::Empty() const {
156 return frames_in_flight_.empty();
157}
158
159} // namespace default_camera_hal