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 // #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