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_RealtimeProcessBlock"
19 #define ATRACE_TAG ATRACE_TAG_CAMERA
20 #include <log/log.h>
21 #include <utils/Trace.h>
22 
23 #include "hal_utils.h"
24 #include "realtime_process_block.h"
25 #include "result_processor.h"
26 
27 namespace android {
28 namespace google_camera_hal {
29 
Create(CameraDeviceSessionHwl * device_session_hwl)30 std::unique_ptr<RealtimeProcessBlock> RealtimeProcessBlock::Create(
31     CameraDeviceSessionHwl* device_session_hwl) {
32   ATRACE_CALL();
33   if (!IsSupported(device_session_hwl)) {
34     ALOGE("%s: Not supported.", __FUNCTION__);
35     return nullptr;
36   }
37 
38   auto block = std::unique_ptr<RealtimeProcessBlock>(
39       new RealtimeProcessBlock(device_session_hwl));
40   if (block == nullptr) {
41     ALOGE("%s: Creating RealtimeProcessBlock failed.", __FUNCTION__);
42     return nullptr;
43   }
44 
45   return block;
46 }
47 
IsSupported(CameraDeviceSessionHwl * device_session_hwl)48 bool RealtimeProcessBlock::IsSupported(
49     CameraDeviceSessionHwl* device_session_hwl) {
50   if (device_session_hwl == nullptr) {
51     ALOGE("%s: device_session_hwl is nullptr", __FUNCTION__);
52     return false;
53   }
54 
55   return true;
56 }
57 
RealtimeProcessBlock(CameraDeviceSessionHwl * device_session_hwl)58 RealtimeProcessBlock::RealtimeProcessBlock(
59     CameraDeviceSessionHwl* device_session_hwl)
60     : kCameraId(device_session_hwl->GetCameraId()),
61       device_session_hwl_(device_session_hwl) {
62   hwl_pipeline_callback_.process_pipeline_result = HwlProcessPipelineResultFunc(
63       [this](std::unique_ptr<HwlPipelineResult> result) {
64         NotifyHwlPipelineResult(std::move(result));
65       });
66 
67   hwl_pipeline_callback_.notify = NotifyHwlPipelineMessageFunc(
68       [this](uint32_t pipeline_id, const NotifyMessage& message) {
69         NotifyHwlPipelineMessage(pipeline_id, message);
70       });
71 }
72 
SetResultProcessor(std::unique_ptr<ResultProcessor> result_processor)73 status_t RealtimeProcessBlock::SetResultProcessor(
74     std::unique_ptr<ResultProcessor> result_processor) {
75   ATRACE_CALL();
76   if (result_processor == nullptr) {
77     ALOGE("%s: result_processor is nullptr", __FUNCTION__);
78     return BAD_VALUE;
79   }
80 
81   std::lock_guard<std::mutex> lock(result_processor_lock_);
82   if (result_processor_ != nullptr) {
83     ALOGE("%s: result_processor_ was already set.", __FUNCTION__);
84     return ALREADY_EXISTS;
85   }
86 
87   result_processor_ = std::move(result_processor);
88   return OK;
89 }
90 
ConfigureStreams(const StreamConfiguration & stream_config,const StreamConfiguration & overall_config)91 status_t RealtimeProcessBlock::ConfigureStreams(
92     const StreamConfiguration& stream_config,
93     const StreamConfiguration& overall_config) {
94   ATRACE_CALL();
95   std::lock_guard lock(configure_shared_mutex_);
96   if (is_configured_) {
97     ALOGE("%s: Already configured.", __FUNCTION__);
98     return ALREADY_EXISTS;
99   }
100 
101   status_t res = device_session_hwl_->ConfigurePipeline(
102       kCameraId, hwl_pipeline_callback_, stream_config, overall_config,
103       &pipeline_id_);
104   if (res != OK) {
105     ALOGE("%s: Configuring a pipeline failed: %s(%d)", __FUNCTION__,
106           strerror(-res), res);
107     return res;
108   }
109 
110   is_configured_ = true;
111   return OK;
112 }
113 
GetConfiguredHalStreams(std::vector<HalStream> * hal_streams) const114 status_t RealtimeProcessBlock::GetConfiguredHalStreams(
115     std::vector<HalStream>* hal_streams) const {
116   ATRACE_CALL();
117   std::lock_guard lock(configure_shared_mutex_);
118   if (hal_streams == nullptr) {
119     ALOGE("%s: hal_streams is nullptr.", __FUNCTION__);
120     return BAD_VALUE;
121   }
122 
123   if (!is_configured_) {
124     ALOGE("%s: Not configured yet.", __FUNCTION__);
125     return NO_INIT;
126   }
127 
128   return device_session_hwl_->GetConfiguredHalStream(pipeline_id_, hal_streams);
129 }
130 
ProcessRequests(const std::vector<ProcessBlockRequest> & process_block_requests,const CaptureRequest & remaining_session_request)131 status_t RealtimeProcessBlock::ProcessRequests(
132     const std::vector<ProcessBlockRequest>& process_block_requests,
133     const CaptureRequest& remaining_session_request) {
134   ATRACE_CALL();
135   if (process_block_requests.size() != 1) {
136     ALOGE("%s: Only a single request is supported but there are %zu",
137           __FUNCTION__, process_block_requests.size());
138     return BAD_VALUE;
139   }
140 
141   {
142     std::lock_guard<std::mutex> lock(result_processor_lock_);
143     if (result_processor_ == nullptr) {
144       ALOGE("%s: result processor was not set.", __FUNCTION__);
145       return NO_INIT;
146     }
147 
148     status_t res = result_processor_->AddPendingRequests(
149         process_block_requests, remaining_session_request);
150     if (res != OK) {
151       ALOGE("%s: Adding a pending request to result processor failed: %s(%d)",
152             __FUNCTION__, strerror(-res), res);
153       return res;
154     }
155   }
156 
157   std::shared_lock lock(configure_shared_mutex_);
158   if (!is_configured_) {
159     ALOGE("%s: block is not configured.", __FUNCTION__);
160     return NO_INIT;
161   }
162 
163   std::vector<HwlPipelineRequest> hwl_requests(1);
164   status_t res = hal_utils::CreateHwlPipelineRequest(
165       &hwl_requests[0], pipeline_id_, process_block_requests[0].request);
166   if (res != OK) {
167     ALOGE("%s: Creating HWL pipeline request failed: %s(%d)", __FUNCTION__,
168           strerror(-res), res);
169     return res;
170   }
171 
172   return device_session_hwl_->SubmitRequests(
173       process_block_requests[0].request.frame_number, hwl_requests);
174 }
175 
Flush()176 status_t RealtimeProcessBlock::Flush() {
177   ATRACE_CALL();
178   std::shared_lock lock(configure_shared_mutex_);
179   if (!is_configured_) {
180     return OK;
181   }
182 
183   return device_session_hwl_->Flush();
184 }
185 
NotifyHwlPipelineResult(std::unique_ptr<HwlPipelineResult> hwl_result)186 void RealtimeProcessBlock::NotifyHwlPipelineResult(
187     std::unique_ptr<HwlPipelineResult> hwl_result) {
188   ATRACE_CALL();
189   std::lock_guard<std::mutex> lock(result_processor_lock_);
190   if (result_processor_ == nullptr) {
191     ALOGE("%s: result processor is nullptr. Dropping a result", __FUNCTION__);
192     return;
193   }
194 
195   auto capture_result = hal_utils::ConvertToCaptureResult(std::move(hwl_result));
196   if (capture_result == nullptr) {
197     ALOGE("%s: Converting to capture result failed.", __FUNCTION__);
198     return;
199   }
200 
201   ProcessBlockResult result = {.result = std::move(capture_result)};
202   result_processor_->ProcessResult(std::move(result));
203 }
204 
NotifyHwlPipelineMessage(uint32_t,const NotifyMessage & message)205 void RealtimeProcessBlock::NotifyHwlPipelineMessage(
206     uint32_t /*pipeline_id*/, const NotifyMessage& message) {
207   ATRACE_CALL();
208   std::lock_guard<std::mutex> lock(result_processor_lock_);
209   if (result_processor_ == nullptr) {
210     ALOGE("%s: result processor is nullptr. Dropping a message", __FUNCTION__);
211     return;
212   }
213 
214   ProcessBlockNotifyMessage block_message = {.message = message};
215   result_processor_->Notify(block_message);
216 }
217 
218 }  // namespace google_camera_hal
219 }  // namespace android
220