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 #include "request_tracker.h" 18 19 // #define LOG_NDEBUG 0 20 #define LOG_TAG "RequestTracker" 21 #include <cutils/log.h> 22 23 namespace default_camera_hal { 24 25 RequestTracker::RequestTracker() {} 26 27 RequestTracker::~RequestTracker() {} 28 29 void 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 39 void 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. 45 std::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 56 bool RequestTracker::Add(std::shared_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] = request; 68 69 return true; 70 } 71 72 bool RequestTracker::Remove(std::shared_ptr<CaptureRequest> request) { 73 if (!request) { 74 return false; 75 } 76 77 // Get the request. 78 const auto frame_number_request = 79 frames_in_flight_.find(request->frame_number); 80 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); 89 return false; 90 } 91 92 frames_in_flight_.erase(frame_number_request); 93 94 // Decrement the counts of used streams. 95 for (const auto stream : RequestStreams(*request)) { 96 --buffers_in_flight_[stream]; 97 } 98 99 return true; 100 } 101 102 void RequestTracker::Clear( 103 std::set<std::shared_ptr<CaptureRequest>>* requests) { 104 // If desired, extract all the currently in-flight requests. 105 if (requests) { 106 for (auto& frame_number_request : frames_in_flight_) { 107 requests->insert(frame_number_request.second); 108 } 109 } 110 111 // Clear out all tracking. 112 frames_in_flight_.clear(); 113 // Maintain the configuration, but reset counts. 114 for (auto& stream_count : buffers_in_flight_) { 115 stream_count.second = 0; 116 } 117 } 118 119 bool 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 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