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