summaryrefslogtreecommitdiff
path: root/modules/camera/3_4/request_tracker.cpp
blob: 09f634d13d55239b9c2d9795beafff289117dd61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * 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