Home | History | Annotate | Download | only in 3_4
      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