You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.5 KiB
159 lines
4.5 KiB
/* |
|
* Copyright 2016 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#include "request_tracker.h" |
|
|
|
// #define LOG_NDEBUG 0 |
|
#define LOG_TAG "RequestTracker" |
|
#include <cutils/log.h> |
|
|
|
namespace default_camera_hal { |
|
|
|
RequestTracker::RequestTracker() {} |
|
|
|
RequestTracker::~RequestTracker() {} |
|
|
|
void RequestTracker::SetStreamConfiguration( |
|
const camera3_stream_configuration_t& config) { |
|
// Clear the old configuration. |
|
ClearStreamConfiguration(); |
|
// Add an entry to the buffer tracking map for each configured stream. |
|
for (size_t i = 0; i < config.num_streams; ++i) { |
|
buffers_in_flight_.emplace(config.streams[i], 0); |
|
} |
|
} |
|
|
|
void RequestTracker::ClearStreamConfiguration() { |
|
// The keys of the in flight buffer map are the configured streams. |
|
buffers_in_flight_.clear(); |
|
} |
|
|
|
// Helper: get the streams used by a request. |
|
std::set<camera3_stream_t*> RequestStreams(const CaptureRequest& request) { |
|
std::set<camera3_stream_t*> result; |
|
if (request.input_buffer) { |
|
result.insert(request.input_buffer->stream); |
|
} |
|
for (const auto& output_buffer : request.output_buffers) { |
|
result.insert(output_buffer.stream); |
|
} |
|
return std::move(result); |
|
} |
|
|
|
bool RequestTracker::Add(std::shared_ptr<CaptureRequest> request) { |
|
if (!CanAddRequest(*request)) { |
|
return false; |
|
} |
|
|
|
// Add to the count for each stream used. |
|
for (const auto stream : RequestStreams(*request)) { |
|
++buffers_in_flight_[stream]; |
|
} |
|
|
|
// Store the request. |
|
frames_in_flight_[request->frame_number] = request; |
|
|
|
return true; |
|
} |
|
|
|
bool RequestTracker::Remove(std::shared_ptr<CaptureRequest> request) { |
|
if (!request) { |
|
return false; |
|
} |
|
|
|
// Get the request. |
|
const auto frame_number_request = |
|
frames_in_flight_.find(request->frame_number); |
|
if (frame_number_request == frames_in_flight_.end()) { |
|
ALOGE("%s: Frame %u is not in flight.", __func__, request->frame_number); |
|
return false; |
|
} else if (request != frame_number_request->second) { |
|
ALOGE( |
|
"%s: Request for frame %u cannot be removed: " |
|
"does not matched the stored request.", |
|
__func__, |
|
request->frame_number); |
|
return false; |
|
} |
|
|
|
frames_in_flight_.erase(frame_number_request); |
|
|
|
// Decrement the counts of used streams. |
|
for (const auto stream : RequestStreams(*request)) { |
|
--buffers_in_flight_[stream]; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
void RequestTracker::Clear( |
|
std::set<std::shared_ptr<CaptureRequest>>* requests) { |
|
// If desired, extract all the currently in-flight requests. |
|
if (requests) { |
|
for (auto& frame_number_request : frames_in_flight_) { |
|
requests->insert(frame_number_request.second); |
|
} |
|
} |
|
|
|
// Clear out all tracking. |
|
frames_in_flight_.clear(); |
|
// Maintain the configuration, but reset counts. |
|
for (auto& stream_count : buffers_in_flight_) { |
|
stream_count.second = 0; |
|
} |
|
} |
|
|
|
bool RequestTracker::CanAddRequest(const CaptureRequest& request) const { |
|
// Check that it's not a duplicate. |
|
if (frames_in_flight_.count(request.frame_number) > 0) { |
|
ALOGE("%s: Already tracking a request with frame number %d.", |
|
__func__, |
|
request.frame_number); |
|
return false; |
|
} |
|
|
|
// Check that each stream has space |
|
// (which implicitly checks if it is configured). |
|
bool result = true; |
|
for (const auto stream : RequestStreams(request)) { |
|
if (StreamFull(stream)) { |
|
ALOGE("%s: Stream %p is full.", __func__, stream); |
|
return false; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
bool RequestTracker::StreamFull(const camera3_stream_t* handle) const { |
|
const auto it = buffers_in_flight_.find(handle); |
|
if (it == buffers_in_flight_.end()) { |
|
// Unconfigured streams are implicitly full. |
|
ALOGV("%s: Stream %p is not a configured stream.", __func__, handle); |
|
return true; |
|
} else { |
|
return it->second >= it->first->max_buffers; |
|
} |
|
} |
|
|
|
bool RequestTracker::InFlight(uint32_t frame_number) const { |
|
return frames_in_flight_.count(frame_number) > 0; |
|
} |
|
|
|
bool RequestTracker::Empty() const { |
|
return frames_in_flight_.empty(); |
|
} |
|
|
|
} // namespace default_camera_hal
|
|
|