1 /*
2  * Copyright (C) 2019 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 "GCH_BasicCaptureSession"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include <log/log.h>
21 #include <utils/Trace.h>
22 
23 #include "basic_capture_session.h"
24 #include "basic_request_processor.h"
25 #include "basic_result_processor.h"
26 #include "realtime_process_block.h"
27 
28 namespace android {
29 namespace google_camera_hal {
30 
IsStreamConfigurationSupported(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration &)31 bool BasicCaptureSession::IsStreamConfigurationSupported(
32     CameraDeviceSessionHwl* device_session_hwl,
33     const StreamConfiguration& /*stream_config*/) {
34   ATRACE_CALL();
35   if (device_session_hwl == nullptr) {
36     ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
37     return false;
38   }
39 
40   ALOGD("%s: BasicCaptureSession supports the stream config", __FUNCTION__);
41   return true;
42 }
43 
Create(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,HwlSessionCallback,std::vector<HalStream> * hal_configured_streams,CameraBufferAllocatorHwl *)44 std::unique_ptr<CaptureSession> BasicCaptureSession::Create(
45     CameraDeviceSessionHwl* device_session_hwl,
46     const StreamConfiguration& stream_config,
47     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
48     HwlSessionCallback /*session_callback*/,
49     std::vector<HalStream>* hal_configured_streams,
50     CameraBufferAllocatorHwl* /*camera_allocator_hwl*/) {
51   ATRACE_CALL();
52   auto session = std::unique_ptr<BasicCaptureSession>(new BasicCaptureSession());
53   if (session == nullptr) {
54     ALOGE("%s: Creating BasicCaptureSession failed.", __FUNCTION__);
55     return nullptr;
56   }
57 
58   status_t res = session->Initialize(device_session_hwl, stream_config,
59                                      process_capture_result, notify,
60                                      hal_configured_streams);
61   if (res != OK) {
62     ALOGE("%s: Initializing BasicCaptureSession failed: %s (%d).", __FUNCTION__,
63           strerror(-res), res);
64     return nullptr;
65   }
66 
67   return session;
68 }
69 
~BasicCaptureSession()70 BasicCaptureSession::~BasicCaptureSession() {
71   if (device_session_hwl_ != nullptr) {
72     device_session_hwl_->DestroyPipelines();
73   }
74 }
75 
ConfigureStreams(const StreamConfiguration & stream_config,RequestProcessor * request_processor,ProcessBlock * process_block)76 status_t BasicCaptureSession::ConfigureStreams(
77     const StreamConfiguration& stream_config,
78     RequestProcessor* request_processor, ProcessBlock* process_block) {
79   ATRACE_CALL();
80   if (request_processor == nullptr || process_block == nullptr) {
81     ALOGE("%s: request_processor (%p) or process_block (%p) is nullptr",
82           __FUNCTION__, request_processor, process_block);
83     return BAD_VALUE;
84   }
85 
86   // Configure streams for request processor
87   StreamConfiguration process_block_stream_config;
88   status_t res = request_processor->ConfigureStreams(
89       internal_stream_manager_.get(), stream_config,
90       &process_block_stream_config);
91   if (res != OK) {
92     ALOGE("%s: Configuring stream for request processor failed.", __FUNCTION__);
93     return res;
94   }
95 
96   // Check all streams are configured.
97   if (stream_config.streams.size() !=
98       process_block_stream_config.streams.size()) {
99     ALOGE("%s: stream_config has %zu streams but only configured %zu streams",
100           __FUNCTION__, stream_config.streams.size(),
101           process_block_stream_config.streams.size());
102     return UNKNOWN_ERROR;
103   }
104 
105   for (auto& stream : stream_config.streams) {
106     bool found = false;
107     for (auto& configured_stream : process_block_stream_config.streams) {
108       if (stream.id == configured_stream.id) {
109         found = true;
110         break;
111       }
112     }
113 
114     if (!found) {
115       ALOGE("%s: Cannot find stream %u in configured streams.", __FUNCTION__,
116             stream.id);
117       return UNKNOWN_ERROR;
118     }
119   }
120 
121   // Configure streams for process block.
122   res = process_block->ConfigureStreams(process_block_stream_config,
123                                         stream_config);
124   if (res != OK) {
125     ALOGE("%s: Configuring stream for process block failed.", __FUNCTION__);
126     return res;
127   }
128 
129   return OK;
130 }
131 
BuildPipelines(ProcessBlock * process_block,std::vector<HalStream> * hal_configured_streams)132 status_t BasicCaptureSession::BuildPipelines(
133     ProcessBlock* process_block,
134     std::vector<HalStream>* hal_configured_streams) {
135   ATRACE_CALL();
136   if (process_block == nullptr || hal_configured_streams == nullptr) {
137     ALOGE("%s: process_block (%p) or hal_configured_streams (%p) is nullptr",
138           __FUNCTION__, process_block, hal_configured_streams);
139     return BAD_VALUE;
140   }
141 
142   status_t res = device_session_hwl_->BuildPipelines();
143   if (res != OK) {
144     ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res),
145           res);
146     return res;
147   }
148 
149   res = process_block->GetConfiguredHalStreams(hal_configured_streams);
150   if (res != OK) {
151     ALOGE("%s: Getting HAL streams failed: %s(%d)", __FUNCTION__,
152           strerror(-res), res);
153     return res;
154   }
155 
156   return OK;
157 }
158 
ConnectProcessChain(RequestProcessor * request_processor,std::unique_ptr<ProcessBlock> process_block,std::unique_ptr<ResultProcessor> result_processor)159 status_t BasicCaptureSession::ConnectProcessChain(
160     RequestProcessor* request_processor,
161     std::unique_ptr<ProcessBlock> process_block,
162     std::unique_ptr<ResultProcessor> result_processor) {
163   ATRACE_CALL();
164   if (request_processor == nullptr) {
165     ALOGE("%s: request_processor is nullptr", __FUNCTION__);
166     return BAD_VALUE;
167   }
168 
169   status_t res = process_block->SetResultProcessor(std::move(result_processor));
170   if (res != OK) {
171     ALOGE("%s: Setting result process in process block failed.", __FUNCTION__);
172     return res;
173   }
174 
175   res = request_processor->SetProcessBlock(std::move(process_block));
176   if (res != OK) {
177     ALOGE("%s: Setting process block for BasicRequestProcessor failed: %s(%d)",
178           __FUNCTION__, strerror(-res), res);
179     return res;
180   }
181 
182   return OK;
183 }
184 
Initialize(CameraDeviceSessionHwl * device_session_hwl,const StreamConfiguration & stream_config,ProcessCaptureResultFunc process_capture_result,NotifyFunc notify,std::vector<HalStream> * hal_configured_streams)185 status_t BasicCaptureSession::Initialize(
186     CameraDeviceSessionHwl* device_session_hwl,
187     const StreamConfiguration& stream_config,
188     ProcessCaptureResultFunc process_capture_result, NotifyFunc notify,
189     std::vector<HalStream>* hal_configured_streams) {
190   ATRACE_CALL();
191   if (!IsStreamConfigurationSupported(device_session_hwl, stream_config)) {
192     ALOGE("%s: stream configuration is not supported.", __FUNCTION__);
193     return BAD_VALUE;
194   }
195 
196   device_session_hwl_ = device_session_hwl;
197   internal_stream_manager_ = InternalStreamManager::Create();
198   if (internal_stream_manager_ == nullptr) {
199     ALOGE("%s: Cannot create internal stream manager.", __FUNCTION__);
200     return UNKNOWN_ERROR;
201   }
202 
203   // Create result processor.
204   auto result_processor = BasicResultProcessor::Create();
205   if (result_processor == nullptr) {
206     ALOGE("%s: Creating BasicResultProcessor failed.", __FUNCTION__);
207     return UNKNOWN_ERROR;
208   }
209 
210   result_processor->SetResultCallback(process_capture_result, notify);
211 
212   // Create process block.
213   auto process_block = RealtimeProcessBlock::Create(device_session_hwl_);
214   if (process_block == nullptr) {
215     ALOGE("%s: Creating RealtimeProcessBlock failed.", __FUNCTION__);
216     return UNKNOWN_ERROR;
217   }
218 
219   // Create request processor.
220   request_processor_ = BasicRequestProcessor::Create(device_session_hwl_);
221   if (request_processor_ == nullptr) {
222     ALOGE("%s: Creating BasicRequestProcessor failed.", __FUNCTION__);
223     return UNKNOWN_ERROR;
224   }
225 
226   status_t res = ConfigureStreams(stream_config, request_processor_.get(),
227                                   process_block.get());
228   if (res != OK) {
229     ALOGE("%s: Configuring stream failed: %s(%d)", __FUNCTION__, strerror(-res),
230           res);
231     return res;
232   }
233 
234   res = BuildPipelines(process_block.get(), hal_configured_streams);
235   if (res != OK) {
236     ALOGE("%s: Building pipelines failed: %s(%d)", __FUNCTION__, strerror(-res),
237           res);
238     return res;
239   }
240 
241   res = ConnectProcessChain(request_processor_.get(), std::move(process_block),
242                             std::move(result_processor));
243   if (res != OK) {
244     ALOGE("%s: Connecting process chain failed: %s(%d)", __FUNCTION__,
245           strerror(-res), res);
246     return res;
247   }
248 
249   return OK;
250 }
251 
ProcessRequest(const CaptureRequest & request)252 status_t BasicCaptureSession::ProcessRequest(const CaptureRequest& request) {
253   ATRACE_CALL();
254   return request_processor_->ProcessRequest(request);
255 }
256 
Flush()257 status_t BasicCaptureSession::Flush() {
258   ATRACE_CALL();
259   return request_processor_->Flush();
260 }
261 
262 }  // namespace google_camera_hal
263 }  // namespace android
264