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 26 RequestTracker::RequestTracker() {} 27 28 RequestTracker::~RequestTracker() {} 29 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 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. 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 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 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 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 120 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 140 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 151 bool RequestTracker::InFlight(uint32_t frame_number) const { 152 return frames_in_flight_.count(frame_number) > 0; 153 } 154 155 bool RequestTracker::Empty() const { 156 return frames_in_flight_.empty(); 157 } 158 159 } // namespace default_camera_hal 160