• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "EvsInputManager.h"
15 
16 #include <chrono>
17 #include <map>
18 #include <shared_mutex>
19 #include <string>
20 #include <thread>
21 
22 #include "AnalyzeUseCase.h"
23 #include "BaseAnalyzeCallback.h"
24 #include "InputConfig.pb.h"
25 #include "InputEngineInterface.h"
26 #include "Options.pb.h"
27 
28 using ::android::automotive::evs::support::AnalyzeUseCase;
29 using ::android::automotive::evs::support::BaseAnalyzeCallback;
30 
31 namespace android {
32 namespace automotive {
33 namespace computepipe {
34 namespace runner {
35 namespace input_manager {
36 
analyze(const::android::automotive::evs::support::Frame & frame)37 void AnalyzeCallback::analyze(const ::android::automotive::evs::support::Frame& frame) {
38     std::shared_lock lock(mEngineInterfaceLock);
39     if (mInputEngineInterface != nullptr) {
40         auto time_point = std::chrono::system_clock::now();
41         int64_t timestamp = std::chrono::time_point_cast<std::chrono::microseconds>(time_point)
42                                 .time_since_epoch()
43                                 .count();
44         // Stride for hardware buffers is specified in pixels whereas for
45         // InputFrame, it is specified in bytes. We therefore need to multiply
46         // the stride by 4 for an RGBA frame.
47         InputFrame inputFrame(frame.height, frame.width, PixelFormat::RGBA, frame.stride * 4,
48                               frame.data);
49         mInputEngineInterface->dispatchInputFrame(mInputStreamId, timestamp, inputFrame);
50     }
51 }
52 
setEngineInterface(std::shared_ptr<InputEngineInterface> inputEngineInterface)53 void AnalyzeCallback::setEngineInterface(
54         std::shared_ptr<InputEngineInterface> inputEngineInterface) {
55     std::lock_guard lock(mEngineInterfaceLock);
56     mInputEngineInterface = inputEngineInterface;
57 }
58 
EvsInputManager(const proto::InputConfig & inputConfig,std::shared_ptr<InputEngineInterface> inputEngineInterface)59 EvsInputManager::EvsInputManager(const proto::InputConfig& inputConfig,
60                                  std::shared_ptr<InputEngineInterface> inputEngineInterface) :
61       mInputEngineInterface(inputEngineInterface),
62       mInputConfig(inputConfig) {}
63 
createEvsInputManager(const proto::InputConfig & inputConfig,const proto::InputConfig &,std::shared_ptr<InputEngineInterface> inputEngineInterface)64 std::unique_ptr<EvsInputManager> EvsInputManager::createEvsInputManager(
65         const proto::InputConfig& inputConfig, const proto::InputConfig& /*overrideConfig*/,
66         std::shared_ptr<InputEngineInterface> inputEngineInterface) {
67     auto evsManager = std::make_unique<EvsInputManager>(inputConfig, inputEngineInterface);
68     if (evsManager->initializeCameras() == Status::SUCCESS) {
69         return evsManager;
70     }
71 
72     return nullptr;
73 }
74 
initializeCameras()75 Status EvsInputManager::initializeCameras() {
76     for (int i = 0; i < mInputConfig.input_stream_size(); i++) {
77         // Verify that the stream type specified is a camera stream which is necessary for evs
78         // manager.
79         if (mInputConfig.input_stream(i).type() != proto::InputStreamConfig_InputType_CAMERA) {
80             ALOGE("Evs stream manager expects the input stream type to be camera.");
81             return Status::INVALID_ARGUMENT;
82         }
83         const std::string& cameraId = mInputConfig.input_stream(i).cam_config().cam_id();
84         std::unique_ptr<AnalyzeCallback> analyzeCallback =
85             std::make_unique<AnalyzeCallback>(mInputConfig.input_stream(i).stream_id());
86         AnalyzeUseCase analyzeUseCase =
87             AnalyzeUseCase::createDefaultUseCase(cameraId, analyzeCallback.get());
88         mAnalyzeCallbacks.push_back(std::move(analyzeCallback));
89 
90         int streamId = mInputConfig.input_stream(i).stream_id();
91         auto [it, result] = mEvsUseCases.try_emplace(std::move(streamId),
92                                                      std::move(analyzeUseCase));
93         if (!result) {
94             // Multiple camera streams found to have the same camera id.
95             ALOGE("Multiple camera streams have the same stream id.");
96             return Status::INVALID_ARGUMENT;
97         }
98     }
99 
100     return Status::SUCCESS;
101 }
102 
handleExecutionPhase(const RunnerEvent & e)103 Status EvsInputManager::handleExecutionPhase(const RunnerEvent& e) {
104     // Starting execution cannot be stopped in between. handleStopImmediate needs to be called.
105     if (e.isAborted()) {
106         return Status::INVALID_ARGUMENT;
107     } else if (e.isTransitionComplete()) {
108         return Status::SUCCESS;
109     }
110 
111     if (mEvsUseCases.empty()) {
112         ALOGE("No evs use cases configured. Verify that handleConfigPhase has been called");
113         return Status::ILLEGAL_STATE;
114     }
115 
116     // Start all the video streams.
117     bool successfullyStartedAllCameras = true;
118     for (auto& [streamId, evsUseCase] : mEvsUseCases) {
119         if (!evsUseCase.startVideoStream()) {
120             successfullyStartedAllCameras = false;
121             ALOGE("Unable to successfully start all cameras");
122             break;
123         }
124     }
125 
126     // If not all video streams have started successfully, stop the streams.
127     if (!successfullyStartedAllCameras) {
128         for (auto& [streamId, evsUseCase] : mEvsUseCases) {
129             evsUseCase.stopVideoStream();
130         }
131         return Status::INTERNAL_ERROR;
132     }
133 
134     // Set the input to engine interface for callbacks only when all the streams have successfully
135     // started. This prevents any callback from going out unless all of the streams have started.
136     for (auto& analyzeCallback : mAnalyzeCallbacks) {
137         analyzeCallback->setEngineInterface(mInputEngineInterface);
138     }
139 
140     return Status::SUCCESS;
141 }
142 
handleStopImmediatePhase(const RunnerEvent & e)143 Status EvsInputManager::handleStopImmediatePhase(const RunnerEvent& e) {
144     if (e.isAborted()) {
145         ALOGE(
146             "Unable to abort immediate stopping of EVS cameras. Please start the video streams "
147             "again if "
148             "needed.");
149     } else if (e.isTransitionComplete()) {
150         return Status::SUCCESS;
151     }
152 
153     // Reset all input engine interfaces so that callbacks stop going out even if there are evs
154     // frames in flux.
155     for (auto& analyzeCallback : mAnalyzeCallbacks) {
156         analyzeCallback->setEngineInterface(nullptr);
157     }
158 
159     for (auto& [streamId, evsUseCase] : mEvsUseCases) {
160         evsUseCase.stopVideoStream();
161     }
162 
163     return Status::SUCCESS;
164 }
165 
handleStopWithFlushPhase(const RunnerEvent & e)166 Status EvsInputManager::handleStopWithFlushPhase(const RunnerEvent& e) {
167     if (e.isAborted()) {
168         ALOGE(
169             "Unable to abort stopping and flushing of EVS cameras. Please start the video streams "
170             "again if "
171             "needed.");
172     } else if (e.isTransitionComplete()) {
173         return Status::SUCCESS;
174     }
175 
176     for (auto& [streamId, evsUseCase] : mEvsUseCases) {
177         evsUseCase.stopVideoStream();
178     }
179     return Status::SUCCESS;
180 }
181 
handleResetPhase(const RunnerEvent & e)182 Status EvsInputManager::handleResetPhase(const RunnerEvent& e) {
183     if (e.isAborted()) {
184         ALOGE("Unable to abort reset.");
185         return Status::INVALID_ARGUMENT;
186     }
187     mEvsUseCases.clear();
188     mAnalyzeCallbacks.clear();
189     return Status::SUCCESS;
190 }
191 
192 }  // namespace input_manager
193 }  // namespace runner
194 }  // namespace computepipe
195 }  // namespace automotive
196 }  // namespace android
197