blob: 60715b52cd441e3afe5931dc022a343a95de7928 [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
56bool RequestTracker::Add(std::unique_ptr<CaptureRequest> request) {
57 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.
67 frames_in_flight_[request->frame_number] = std::move(request);
68
69 return true;
70}
71
72bool RequestTracker::Remove(uint32_t frame_number,
73 std::unique_ptr<CaptureRequest>* request) {
74 // Get the request.
75 std::unique_ptr<CaptureRequest> stored_request =
76 std::move(frames_in_flight_[frame_number]);
77 if (!stored_request) {
78 ALOGE("%s: Frame %u is not in flight.", __func__, frame_number);
79 return false;
80 }
81 frames_in_flight_.erase(frame_number);
82
83 // Decrement the counts of used streams.
84 for (const auto stream : RequestStreams(*stored_request)) {
85 --buffers_in_flight_[stream];
86 }
87
88 // Return the request if requested.
89 if (request) {
90 *request = std::move(stored_request);
91 }
92 return true;
93}
94
95void RequestTracker::Clear(
96 std::set<std::unique_ptr<CaptureRequest>>* requests) {
97 // If desired, extract all the currently in-flight requests.
98 if (requests) {
99 for (auto& frame_number_request : frames_in_flight_) {
100 requests->insert(std::move(frame_number_request.second));
101 }
102 }
103
104 // Clear out all tracking.
105 frames_in_flight_.clear();
106 buffers_in_flight_.clear();
107}
108
109bool RequestTracker::CanAddRequest(const CaptureRequest& request) const {
110 // Check that it's not a duplicate.
111 if (frames_in_flight_.count(request.frame_number) > 0) {
112 ALOGE("%s: Already tracking a request with frame number %d.",
113 __func__,
114 request.frame_number);
115 return false;
116 }
117
118 // Check that each stream has space
119 // (which implicitly checks if it is configured).
120 bool result = true;
121 for (const auto stream : RequestStreams(request)) {
122 if (StreamFull(stream)) {
123 ALOGE("%s: Stream %p is full.", __func__, stream);
124 return false;
125 }
126 }
127 return true;
128}
129
130bool RequestTracker::StreamFull(const camera3_stream_t* handle) const {
131 const auto it = buffers_in_flight_.find(handle);
132 if (it == buffers_in_flight_.end()) {
133 // Unconfigured streams are implicitly full.
134 ALOGV("%s: Stream %p is not a configured stream.", __func__, handle);
135 return true;
136 } else {
137 return it->second >= it->first->max_buffers;
138 }
139}
140
141bool RequestTracker::InFlight(uint32_t frame_number) const {
142 return frames_in_flight_.count(frame_number) > 0;
143}
144
145bool RequestTracker::Empty() const {
146 return frames_in_flight_.empty();
147}
148
149} // namespace default_camera_hal