1 /*
2 * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd.
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 */
15
16 #include <algorithm>
17 #include <iterator>
18 #include "watchdog.h"
19 #include "stream_operator_vdi_impl.h"
20 #include "buffer_adapter.h"
21 #include "camera_device_vdi_impl.h"
22 #include "camera_host_config.h"
23 #include "metadata_utils.h"
24 #include "camera_dump.h"
25 #ifdef HITRACE_LOG_ENABLED
26 #include "hdf_trace.h"
27 #define HDF_CAMERA_TRACE HdfTrace trace(__func__, "HDI:CAM:")
28 #else
29 #define HDF_CAMERA_TRACE
30 #endif
31
32 namespace OHOS::Camera {
StreamOperatorVdiImpl(const OHOS::sptr<IStreamOperatorVdiCallback> & callback,const std::weak_ptr<ICameraDeviceVdi> & device)33 StreamOperatorVdiImpl::StreamOperatorVdiImpl(const OHOS::sptr<IStreamOperatorVdiCallback> &callback,
34 const std::weak_ptr<ICameraDeviceVdi> &device)
35 {
36 CAMERA_LOGV("enter");
37 callback_ = callback;
38 device_ = device;
39 }
40
~StreamOperatorVdiImpl()41 StreamOperatorVdiImpl::~StreamOperatorVdiImpl()
42 {
43 CAMERA_LOGV("enter");
44 }
45
Init()46 RetCode StreamOperatorVdiImpl::Init()
47 {
48 auto dev = std::static_pointer_cast<CameraDeviceVdiImpl>(device_.lock());
49 CHECK_IF_PTR_NULL_RETURN_VALUE(dev, RC_ERROR);
50 pipelineCore_ = dev->GetPipelineCore();
51 if (pipelineCore_ == nullptr) {
52 CAMERA_LOGE("get pipeline core failed.");
53 return RC_ERROR;
54 }
55
56 requestTimeoutCB_ = std::bind(&CameraDeviceVdiImpl::OnRequestTimeout, dev);
57 streamPipeline_ = pipelineCore_->GetStreamPipelineCore();
58 if (streamPipeline_ == nullptr) {
59 CAMERA_LOGE("get stream pipeline core failed.");
60 return RC_ERROR;
61 }
62
63 std::string cameraIds;
64 dev->GetCameraId(cameraIds);
65 RetCode rc = streamPipeline_->Init(cameraIds);
66 if (rc != RC_OK) {
67 CAMERA_LOGE("stream pipeline core init failed.");
68 return RC_ERROR;
69 }
70
71 auto cb = [this](MessageGroup &m) { HandleCallbackMessage(m); };
72 messenger_ = std::make_shared<CaptureMessageOperator>(cb);
73 CHECK_IF_PTR_NULL_RETURN_VALUE(messenger_, RC_ERROR);
74 messenger_->StartProcess();
75
76 return RC_OK;
77 }
78
GetStreamSupportType(std::set<int32_t> inputIDSet,DynamicStreamSwitchMode method,VdiStreamSupportType & type)79 void StreamOperatorVdiImpl::GetStreamSupportType(std::set<int32_t> inputIDSet,
80 DynamicStreamSwitchMode method, VdiStreamSupportType &type)
81 {
82 std::set<int32_t> currentIDSet = {};
83 {
84 std::lock_guard<std::mutex> l(streamLock_);
85 for (auto &it : streamMap_) {
86 currentIDSet.emplace(it.first);
87 }
88 }
89
90 // no streams are running
91 if (currentIDSet.empty()) {
92 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
93 type = DYNAMIC_SUPPORTED;
94 return;
95 }
96 type = NOT_SUPPORTED;
97 return;
98 }
99
100 // the difference of currentSet from inputIDSet
101 std::set<int32_t> cfiSet = {};
102 std::set_difference(inputIDSet.begin(), inputIDSet.end(), currentIDSet.begin(), currentIDSet.end(),
103 std::inserter(cfiSet, cfiSet.begin()));
104
105 // the difference of cfiSet from inputIDSet
106 std::set<int32_t> expectCurrentSet = {};
107 std::set_difference(inputIDSet.begin(), inputIDSet.end(), cfiSet.begin(), cfiSet.end(),
108 std::inserter(expectCurrentSet, expectCurrentSet.begin()));
109
110 bool isEqual =
111 std::equal(expectCurrentSet.begin(), expectCurrentSet.end(), currentIDSet.begin(), currentIDSet.end());
112 if (isEqual) {
113 // currentIDSet is subset of inputIDSet
114 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
115 type = DYNAMIC_SUPPORTED;
116 return;
117 }
118 type = NOT_SUPPORTED;
119 } else {
120 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
121 type = RE_CONFIGURED_REQUIRED;
122 return;
123 }
124 type = NOT_SUPPORTED;
125 }
126
127 return;
128 }
129
IsStreamsSupported(VdiOperationMode mode,const std::vector<uint8_t> & modeSetting,const std::vector<VdiStreamInfo> & infos,VdiStreamSupportType & type)130 int32_t StreamOperatorVdiImpl::IsStreamsSupported(VdiOperationMode mode, const std::vector<uint8_t> &modeSetting,
131 const std::vector<VdiStreamInfo> &infos, VdiStreamSupportType &type)
132 {
133 HDF_CAMERA_TRACE;
134 CHECK_IF_PTR_NULL_RETURN_VALUE(streamPipeline_, DEVICE_ERROR);
135 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
136 if (infos.empty() || modeSetting.empty()) {
137 CAMERA_LOGE("input vector is empty");
138 return INVALID_ARGUMENT;
139 }
140 DFX_LOCAL_HITRACE_BEGIN;
141
142 std::set<int32_t> inputIDSet = {};
143 std::vector<int32_t> checkStreamIdVec = {};
144 for (auto it : infos) {
145 CHECK_IF_NOT_EQUAL_RETURN_VALUE(CheckStreamInfo(it), true, INVALID_ARGUMENT);
146 inputIDSet.emplace(it.streamId_);
147 checkStreamIdVec.push_back(it.streamId_);
148 }
149 CHECK_IF_EQUAL_RETURN_VALUE(inputIDSet.empty(), true, INVALID_ARGUMENT);
150
151 auto uniqueIt = std::unique(checkStreamIdVec.begin(), checkStreamIdVec.end());
152 if (checkStreamIdVec.size() != (uint32_t)(std::distance(checkStreamIdVec.begin(), uniqueIt))) {
153 CAMERA_LOGE("stream id must be unique");
154 return INVALID_ARGUMENT;
155 }
156
157 std::shared_ptr<CameraMetadata> settings;
158 MetadataUtils::ConvertVecToMetadata(modeSetting, settings);
159 DynamicStreamSwitchMode method = CheckStreamsSupported(mode, settings, infos);
160 if (method == DYNAMIC_STREAM_SWITCH_SUPPORT) {
161 type = DYNAMIC_SUPPORTED;
162 return VDI::Camera::V1_0::NO_ERROR;
163 }
164
165 if (method == DYNAMIC_STREAM_SWITCH_NOT_SUPPORT) {
166 type = NOT_SUPPORTED;
167 return VDI::Camera::V1_0::NO_ERROR;
168 }
169
170 // change mode need to update pipeline, and caller must restart streams
171 if (mode != streamPipeline_->GetCurrentMode()) {
172 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
173 type = RE_CONFIGURED_REQUIRED;
174 return VDI::Camera::V1_0::NO_ERROR;
175 }
176 type = NOT_SUPPORTED;
177 return VDI::Camera::V1_0::NO_ERROR;
178 }
179
180 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
181 GetStreamSupportType(inputIDSet, method, type);
182 return VDI::Camera::V1_0::NO_ERROR;
183 }
184
185 DFX_LOCAL_HITRACE_END;
186 return VDI::Camera::V1_0::NO_ERROR;
187 }
188
CheckStreamsSupported(VdiOperationMode mode,const std::shared_ptr<CameraMetadata> & modeSetting,const std::vector<VdiStreamInfo> & infos)189 DynamicStreamSwitchMode StreamOperatorVdiImpl::CheckStreamsSupported(
190 VdiOperationMode mode,
191 const std::shared_ptr<CameraMetadata> &modeSetting,
192 const std::vector<VdiStreamInfo> &infos)
193 {
194 CHECK_IF_PTR_NULL_RETURN_VALUE(streamPipeline_, DYNAMIC_STREAM_SWITCH_NOT_SUPPORT);
195 std::vector<StreamConfiguration> configs = {};
196 for (auto &it : infos) {
197 StreamConfiguration config = {};
198 config.type = it.intent_;
199 config.width = it.width_;
200 config.height = it.height_;
201 PixelFormat pf = static_cast<PixelFormat>(it.format_);
202 config.format = BufferAdapter::PixelFormatToCameraFormat(pf);
203 config.dataspace = it.dataspace_; // fix spell error
204 config.tunnelMode = it.tunneledMode_;
205 config.minFrameDuration = it.minFrameDuration_;
206 config.encodeType = it.encodeType_;
207 configs.emplace_back(config);
208 }
209 // search device capability to check if this configuration is supported.
210 return streamPipeline_->CheckStreamsSupported(mode, modeSetting, configs);
211 }
212
StreamInfoToStreamConfiguration(StreamConfiguration & scg,const VdiStreamInfo info)213 void StreamOperatorVdiImpl::StreamInfoToStreamConfiguration(StreamConfiguration &scg, const VdiStreamInfo info)
214 {
215 scg.id = info.streamId_;
216 scg.type = info.intent_;
217 scg.width = info.width_;
218 scg.height = info.height_;
219 PixelFormat pf = static_cast<PixelFormat>(info.format_);
220 scg.format = BufferAdapter::PixelFormatToCameraFormat(pf);
221 scg.dataspace = info.dataspace_; // fix misspell
222 scg.tunnelMode = info.tunneledMode_;
223 scg.minFrameDuration = info.minFrameDuration_;
224 scg.encodeType = info.encodeType_;
225 }
226
CreateStreams(const std::vector<VdiStreamInfo> & streamInfos)227 int32_t StreamOperatorVdiImpl::CreateStreams(const std::vector<VdiStreamInfo> &streamInfos)
228 {
229 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
230 HDF_CAMERA_TRACE;
231 DFX_LOCAL_HITRACE_BEGIN;
232 for (const auto &it : streamInfos) {
233 CHECK_IF_NOT_EQUAL_RETURN_VALUE(CheckStreamInfo(it), true, INVALID_ARGUMENT);
234 CAMERA_LOGI("streamId:%{public}d and format:%{public}d and width:%{public}d and height:%{public}d",
235 it.streamId_, it.format_, it.width_, it.height_);
236 if (streamMap_.count(it.streamId_) > 0) {
237 CAMERA_LOGE("stream [id = %{public}d] has already been created.", it.streamId_);
238 return INVALID_ARGUMENT;
239 }
240 std::shared_ptr<IStream> stream = StreamFactory::Instance().CreateShared(
241 IStream::g_availableStreamType[it.intent_], it.streamId_, it.intent_, pipelineCore_, messenger_);
242
243 CHECK_IF_PTR_NULL_RETURN_VALUE(stream, INSUFFICIENT_RESOURCES);
244
245 StreamConfiguration scg;
246 StreamInfoToStreamConfiguration(scg, it);
247 RetCode rc = stream->ConfigStream(scg);
248 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
249 CHECK_IF_PTR_NULL_RETURN_VALUE(it.bufferQueue_, INVALID_ARGUMENT);
250
251 if (!scg.tunnelMode && (it.bufferQueue_)->producer_ != nullptr) {
252 CAMERA_LOGE("stream [id:%{public}d] is not tunnel mode, can't bind a buffer producer", it.streamId_);
253 return INVALID_ARGUMENT;
254 }
255 if ((it.bufferQueue_)->producer_ != nullptr) {
256 auto tunnel = std::make_shared<StreamTunnel>();
257 CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel, INSUFFICIENT_RESOURCES);
258 rc = tunnel->AttachBufferQueue((it.bufferQueue_)->producer_);
259 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
260 if (stream->AttachStreamTunnel(tunnel) != RC_OK) {
261 CAMERA_LOGE("attach buffer queue to stream [id = %{public}d] failed", it.streamId_);
262 return INVALID_ARGUMENT;
263 }
264 }
265 std::lock_guard<std::mutex> l(streamLock_);
266 streamMap_[stream->GetStreamId()] = stream;
267 CAMERA_LOGI("create stream success [id:%{public}d] [type:%{public}s]", stream->GetStreamId(),
268 IStream::g_availableStreamType[it.intent_].c_str());
269 }
270 DFX_LOCAL_HITRACE_END;
271 return VDI::Camera::V1_0::NO_ERROR;
272 }
273
ReleaseStreams(const std::vector<int32_t> & streamIds)274 int32_t StreamOperatorVdiImpl::ReleaseStreams(const std::vector<int32_t> &streamIds)
275 {
276 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
277 HDF_CAMERA_TRACE;
278 DFX_LOCAL_HITRACE_BEGIN;
279 for (auto id : streamIds) {
280 std::lock_guard<std::mutex> l(streamLock_);
281 auto it = streamMap_.find(id);
282 if (it == streamMap_.end()) {
283 continue;
284 }
285 if (it->second->IsRunning()) {
286 it->second->StopStream();
287 }
288 it->second->DumpStatsInfo();
289 it->second->ReleaseStreamBufferPool();
290 streamMap_.erase(it);
291 }
292
293 for (auto id : streamIds) {
294 CHECK_IF_EQUAL_RETURN_VALUE(id < 0, true, INVALID_ARGUMENT);
295 }
296
297 DFX_LOCAL_HITRACE_END;
298 return VDI::Camera::V1_0::NO_ERROR;
299 }
300
301
ReleaseStreams()302 RetCode StreamOperatorVdiImpl::ReleaseStreams()
303 {
304 std::vector<int32_t> ids = {};
305 for (auto it : streamMap_) {
306 ids.push_back(it.first);
307 }
308 ReleaseStreams(ids);
309 return RC_OK;
310 }
311
CommitStreams(VdiOperationMode mode,const std::vector<uint8_t> & modeSetting)312 int32_t StreamOperatorVdiImpl::CommitStreams(VdiOperationMode mode, const std::vector<uint8_t> &modeSetting)
313 {
314 HDF_CAMERA_TRACE;
315 CAMERA_LOGV("enter");
316 CHECK_IF_PTR_NULL_RETURN_VALUE(streamPipeline_, DEVICE_ERROR);
317 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
318 if (modeSetting.empty()) {
319 CAMERA_LOGE("input vector is empty");
320 return INVALID_ARGUMENT;
321 }
322 DFX_LOCAL_HITRACE_BEGIN;
323
324 std::vector<StreamConfiguration> configs = {};
325 {
326 std::lock_guard<std::mutex> l(streamLock_);
327 std::transform(streamMap_.begin(), streamMap_.end(), std::back_inserter(configs),
328 [](auto &iter) { return iter.second->GetStreamAttribute(); });
329 }
330
331 std::shared_ptr<CameraMetadata> setting;
332 MetadataUtils::ConvertVecToMetadata(modeSetting, setting);
333 DynamicStreamSwitchMode method = streamPipeline_->CheckStreamsSupported(mode, setting, configs);
334 CHECK_IF_EQUAL_RETURN_VALUE(method, DYNAMIC_STREAM_SWITCH_NOT_SUPPORT, INVALID_ARGUMENT);
335 {
336 std::lock_guard<std::mutex> l(streamLock_);
337 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
338 for (auto it : streamMap_) {
339 it.second->StopStream();
340 }
341 }
342
343 for (auto it : streamMap_) {
344 if (it.second->CommitStream() != RC_OK) {
345 CAMERA_LOGE("commit stream [id = %{public}d] failed.", it.first);
346 return DEVICE_ERROR;
347 }
348 }
349 }
350 RetCode rc = streamPipeline_->PreConfig(setting);
351 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, DEVICE_ERROR);
352
353 auto dev = std::static_pointer_cast<CameraDeviceVdiImpl>(device_.lock());
354 CHECK_IF_PTR_NULL_RETURN_VALUE(dev, RC_ERROR);
355 std::string cameraId;
356 dev->GetCameraId(cameraId);
357 // 2:uvc mode
358 int32_t mode1 = CameraHostConfig::GetInstance()->SearchUsbCameraId(cameraId) ? 2 : mode;
359
360 rc = streamPipeline_->CreatePipeline(mode1);
361 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
362
363 DFX_LOCAL_HITRACE_END;
364 return VDI::Camera::V1_0::NO_ERROR;
365 }
366
GetStreamAttributes(std::vector<VdiStreamAttribute> & attributes)367 int32_t StreamOperatorVdiImpl::GetStreamAttributes(std::vector<VdiStreamAttribute> &attributes)
368 {
369 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
370 HDF_CAMERA_TRACE;
371 DFX_LOCAL_HITRACE_BEGIN;
372
373 attributes.clear();
374 for (auto it : streamMap_) {
375 auto configuration = it.second->GetStreamAttribute();
376 VdiStreamAttribute attribute = {};
377 attribute.streamId_ = it.first;
378 attribute.width_ = configuration.width;
379 attribute.height_ = configuration.height;
380 attribute.overrideFormat_ = (int32_t)BufferAdapter::CameraFormatToPixelFormat(configuration.format);
381 attribute.overrideDataspace_ = configuration.dataspace;
382 attribute.producerUsage_ = BufferAdapter::CameraUsageToGrallocUsage(configuration.usage);
383 attribute.producerBufferCount_ = configuration.bufferCount;
384 attribute.maxBatchCaptureCount_ = configuration.maxCaptureCount;
385 attribute.maxCaptureCount_ = configuration.maxCaptureCount;
386 attributes.emplace_back(attribute);
387 }
388 DFX_LOCAL_HITRACE_END;
389 return VDI::Camera::V1_0::NO_ERROR;
390 }
391
AttachBufferQueue(int32_t streamId,const sptr<BufferProducerSequenceable> & bufferProducer)392 int32_t StreamOperatorVdiImpl::AttachBufferQueue(int32_t streamId,
393 const sptr<BufferProducerSequenceable> &bufferProducer)
394 {
395 CHECK_IF_EQUAL_RETURN_VALUE(streamId < 0, true, INVALID_ARGUMENT);
396 CHECK_IF_PTR_NULL_RETURN_VALUE(bufferProducer, INVALID_ARGUMENT);
397 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
398 HDF_CAMERA_TRACE;
399 DFX_LOCAL_HITRACE_BEGIN;
400
401 std::shared_ptr<IStream> stream = nullptr;
402 {
403 std::lock_guard<std::mutex> l(streamLock_);
404 auto it = streamMap_.find(streamId);
405 if (it == streamMap_.end()) {
406 return INVALID_ARGUMENT;
407 }
408 stream = it->second;
409 }
410
411 CHECK_IF_PTR_NULL_RETURN_VALUE(stream, INVALID_ARGUMENT);
412 CHECK_IF_EQUAL_RETURN_VALUE(stream->GetTunnelMode(), false, METHOD_NOT_SUPPORTED);
413
414 auto tunnel = std::make_shared<StreamTunnel>();
415 CHECK_IF_EQUAL_RETURN_VALUE(tunnel, nullptr, INSUFFICIENT_RESOURCES);
416 auto bufferQueue = const_cast<OHOS::sptr<OHOS::IBufferProducer>&>(bufferProducer->producer_);
417 RetCode rc = tunnel->AttachBufferQueue(bufferQueue);
418 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
419
420 rc = stream->AttachStreamTunnel(tunnel);
421 if (rc != RC_OK) {
422 CAMERA_LOGE("attach buffer queue to stream [id = %{public}d] failed", streamId);
423 return CAMERA_BUSY;
424 }
425 DFX_LOCAL_HITRACE_END;
426 return VDI::Camera::V1_0::NO_ERROR;
427 }
428
DetachBufferQueue(int32_t streamId)429 int32_t StreamOperatorVdiImpl::DetachBufferQueue(int32_t streamId)
430 {
431 CHECK_IF_EQUAL_RETURN_VALUE(streamId < 0, true, INVALID_ARGUMENT);
432 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
433 HDF_CAMERA_TRACE;
434 DFX_LOCAL_HITRACE_BEGIN;
435
436 std::shared_ptr<IStream> stream = nullptr;
437 {
438 std::lock_guard<std::mutex> l(streamLock_);
439 auto it = streamMap_.find(streamId);
440 if (it == streamMap_.end()) {
441 return INVALID_ARGUMENT;
442 }
443 stream = it->second;
444 }
445
446 CHECK_IF_PTR_NULL_RETURN_VALUE(stream, INVALID_ARGUMENT);
447 CHECK_IF_EQUAL_RETURN_VALUE(stream->GetTunnelMode(), false, METHOD_NOT_SUPPORTED);
448 RetCode rc = RC_ERROR;
449 if (stream->IsRunning()) {
450 rc = stream->StopStream();
451 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, DEVICE_ERROR);
452 }
453
454 rc = stream->DetachStreamTunnel();
455 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, DEVICE_ERROR);
456
457 DFX_LOCAL_HITRACE_END;
458 return VDI::Camera::V1_0::NO_ERROR;
459 }
460
Capture(int32_t captureId,const VdiCaptureInfo & info,bool isStreaming)461 int32_t StreamOperatorVdiImpl::Capture(int32_t captureId, const VdiCaptureInfo &info, bool isStreaming)
462 {
463 CAMERA_LOGI("--- start Capture captureId = [%{public}d] ---", captureId) ;
464 CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
465 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
466 HDF_CAMERA_TRACE;
467 DFX_LOCAL_HITRACE_BEGIN;
468
469 for (auto id : info.streamIds_) {
470 std::lock_guard<std::mutex> l(streamLock_);
471 auto it = streamMap_.find(id);
472 if (it == streamMap_.end()) {
473 return INVALID_ARGUMENT;
474 }
475 }
476
477 {
478 std::lock_guard<std::mutex> l(requestLock_);
479 auto itr = requestMap_.find(captureId);
480 if (itr != requestMap_.end()) {
481 return INVALID_ARGUMENT;
482 }
483 }
484
485 std::shared_ptr<CameraMetadata> captureSetting;
486 MetadataUtils::ConvertVecToMetadata(info.captureSetting_, captureSetting);
487
488 CameraDumper &dumper = CameraDumper::GetInstance();
489 dumper.DumpMetadata("capturesetting", ENABLE_METADATA, captureSetting);
490
491 auto request =
492 std::make_shared<CaptureRequest>(captureId, info.streamIds_.size(), captureSetting,
493 info.enableShutterCallback_, isStreaming);
494 for (auto id : info.streamIds_) {
495 RetCode rc = streamMap_[id]->AddRequest(request);
496 if (rc != RC_OK) {
497 return DEVICE_ERROR;
498 }
499 }
500
501 {
502 std::lock_guard<std::mutex> l(requestLock_);
503 requestMap_[captureId] = request;
504 }
505 return VDI::Camera::V1_0::NO_ERROR;
506 }
507
CancelCapture(int32_t captureId)508 int32_t StreamOperatorVdiImpl::CancelCapture(int32_t captureId)
509 {
510 CAMERA_LOGI("--- start CancelCapture captureId = [%{public}d] ---", captureId) ;
511 CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
512 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
513 HDF_CAMERA_TRACE;
514 DFX_LOCAL_HITRACE_BEGIN;
515
516 std::lock_guard<std::mutex> l(requestLock_);
517 auto itr = requestMap_.find(captureId);
518 if (itr == requestMap_.end()) {
519 CAMERA_LOGE("can't cancel capture [id = %{public}d], this capture doesn't exist", captureId);
520 return INVALID_ARGUMENT;
521 }
522
523 RetCode rc = itr->second->Cancel();
524 if (rc != RC_OK) {
525 return DEVICE_ERROR;
526 }
527 requestMap_.erase(itr);
528
529 DFX_LOCAL_HITRACE_END;
530 return VDI::Camera::V1_0::NO_ERROR;
531 }
532
ChangeToOfflineStream(const std::vector<int32_t> & streamIds,const sptr<IStreamOperatorVdiCallback> & callbackObj,sptr<IOfflineStreamOperatorVdi> & offlineOperator)533 int32_t StreamOperatorVdiImpl::ChangeToOfflineStream(const std::vector<int32_t> &streamIds,
534 const sptr<IStreamOperatorVdiCallback> &callbackObj, sptr<IOfflineStreamOperatorVdi> &offlineOperator)
535 {
536 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
537 HDF_CAMERA_TRACE;
538 DFX_LOCAL_HITRACE_BEGIN;
539 CHECK_IF_PTR_NULL_RETURN_VALUE(callbackObj, INVALID_ARGUMENT);
540 // offlineOperator should not be null
541 CHECK_IF_NOT_EQUAL_RETURN_VALUE(offlineOperator, nullptr, INVALID_ARGUMENT);
542 CHECK_IF_EQUAL_RETURN_VALUE(streamIds.empty(), true, INVALID_ARGUMENT);
543
544 #ifdef CAMERA_BUILT_ON_OHOS_LITE
545 oflstor_ = std::make_shared<OfflineStreamOperatorVdiImpl>();
546 #else
547 oflstor_ = new (std::nothrow) OfflineStreamOperatorVdiImpl();
548 #endif
549 CHECK_IF_PTR_NULL_RETURN_VALUE(oflstor_, INSUFFICIENT_RESOURCES);
550
551 for (auto it : streamIds) {
552 CHECK_IF_EQUAL_RETURN_VALUE(it < 0, true, INVALID_ARGUMENT);
553 std::lock_guard<std::mutex> l(streamLock_);
554 auto streamIt = streamMap_.find(it);
555 if (streamIt == streamMap_.end()) {
556 CAMERA_LOGE("stream id %{public}d doesn't exist, change to offline mode failed.", it);
557 return INVALID_ARGUMENT;
558 }
559 // only still-capture stream can be changed to offline mode
560 if (streamMap_[it]->GetStreamAttribute().type != STILL_CAPTURE) {
561 return METHOD_NOT_SUPPORTED;
562 }
563
564 auto offlineStream = std::make_shared<OfflineStream>(it, callbackObj);
565 CHECK_IF_PTR_NULL_RETURN_VALUE(offlineStream, INSUFFICIENT_RESOURCES);
566
567 RetCode rc = streamMap_[it]->ChangeToOfflineStream(offlineStream);
568 if (rc != RC_OK) {
569 CAMERA_LOGE("stream id %{public}d change to offline mode failed.", it);
570 return DEVICE_ERROR;
571 }
572 rc = oflstor_->CommitOfflineStream(offlineStream);
573 if (rc != RC_OK) {
574 CAMERA_LOGE("stream id %{public}d, commit offline stream failed.", it);
575 return DEVICE_ERROR;
576 }
577 CAMERA_LOGI("stream %{public}d switch to offline success.", it);
578 }
579
580 offlineOperator = oflstor_;
581 DFX_LOCAL_HITRACE_END;
582 return VDI::Camera::V1_0::NO_ERROR;
583 }
584
CheckStreamInfo(const VdiStreamInfo streamInfo)585 bool StreamOperatorVdiImpl::CheckStreamInfo(const VdiStreamInfo streamInfo)
586 {
587 if (streamInfo.streamId_ < 0 || streamInfo.width_ < 0 || streamInfo.height_ < 0 || streamInfo.format_ < 0 ||
588 streamInfo.dataspace_ < 0 || streamInfo.intent_ > CUSTOM || streamInfo.intent_ < PREVIEW ||
589 streamInfo.minFrameDuration_ < 0) {
590 return false;
591 }
592 return true;
593 }
594
HandleCallbackMessage(MessageGroup & message)595 void StreamOperatorVdiImpl::HandleCallbackMessage(MessageGroup &message)
596 {
597 if (message.empty()) {
598 return;
599 }
600 CHECK_IF_PTR_NULL_RETURN_VOID(message[0]);
601 CaptureMessageType type = message[0]->GetMessageType();
602 switch (type) {
603 case CAPTURE_MESSAGE_TYPE_ON_STARTED: {
604 std::vector<int32_t> ids = {};
605 for (auto cm : message) {
606 auto m = std::static_pointer_cast<CaptureStartedMessage>(cm);
607 CHECK_IF_PTR_NULL_RETURN_VOID(m);
608 ids.push_back(m->GetStreamId());
609 }
610 OnCaptureStarted(message[0]->GetCaptureId(), ids);
611 break;
612 }
613 case CAPTURE_MESSAGE_TYPE_ON_ERROR: {
614 std::vector<VdiCaptureErrorInfo> info = {};
615 for (auto cm : message) {
616 auto m = std::static_pointer_cast<CaptureErrorMessage>(cm);
617 CHECK_IF_PTR_NULL_RETURN_VOID(m);
618 VdiCaptureErrorInfo edi = {};
619 edi.streamId_ = m->GetStreamId();
620 edi.error_ = m->GetStreamError();
621 info.push_back(edi);
622 }
623 OnCaptureError(message[0]->GetCaptureId(), info);
624 break;
625 }
626 case CAPTURE_MESSAGE_TYPE_ON_ENDED: {
627 std::vector<VdiCaptureEndedInfo> info = {};
628 for (auto cm : message) {
629 auto m = std::static_pointer_cast<CaptureEndedMessage>(cm);
630 CHECK_IF_PTR_NULL_RETURN_VOID(m);
631 VdiCaptureEndedInfo edi = {};
632 edi.streamId_ = m->GetStreamId();
633 edi.frameCount_ = m->GetFrameCount();
634 info.push_back(edi);
635 }
636 OnCaptureEnded(message[0]->GetCaptureId(), info);
637 break;
638 }
639 case CAPTURE_MESSAGE_TYPE_ON_SHUTTER: {
640 std::vector<int32_t> ids = {};
641 for (auto cm : message) {
642 auto m = std::static_pointer_cast<FrameShutterMessage>(cm);
643 CHECK_IF_PTR_NULL_RETURN_VOID(m);
644 ids.push_back(m->GetStreamId());
645 }
646 OnFrameShutter(message[0]->GetCaptureId(), ids, message[0]->GetTimestamp());
647 break;
648 }
649 default:
650 break;
651 }
652 return;
653 }
654
OnCaptureStarted(int32_t captureId,const std::vector<int32_t> & streamIds)655 void StreamOperatorVdiImpl::OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamIds)
656 {
657 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
658 callback_->OnCaptureStarted(captureId, streamIds);
659 }
660
OnCaptureEnded(int32_t captureId,const std::vector<VdiCaptureEndedInfo> & infos)661 void StreamOperatorVdiImpl::OnCaptureEnded(int32_t captureId, const std::vector<VdiCaptureEndedInfo> &infos)
662 {
663 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
664 int32_t ret = callback_->OnCaptureEnded(captureId, infos);
665 if (ret != 0) {
666 CAMERA_LOGE("OnCaptureEnded captureId: %{public}d failed, ret = %{public}d", captureId, ret);
667 return;
668 }
669
670 std::lock_guard<std::mutex> l(requestLock_);
671 auto itr = requestMap_.find(captureId);
672 if (itr == requestMap_.end()) {
673 CAMERA_LOGE("OnCaptureEnded captureId: %{public}d not found request", captureId);
674 return;
675 }
676 requestMap_.erase(itr);
677 }
678
OnCaptureError(int32_t captureId,const std::vector<VdiCaptureErrorInfo> & infos)679 void StreamOperatorVdiImpl::OnCaptureError(int32_t captureId, const std::vector<VdiCaptureErrorInfo> &infos)
680 {
681 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
682 callback_->OnCaptureError(captureId, infos);
683 }
684
OnFrameShutter(int32_t captureId,const std::vector<int32_t> & streamIds,uint64_t timestamp)685 void StreamOperatorVdiImpl::OnFrameShutter(int32_t captureId,
686 const std::vector<int32_t> &streamIds, uint64_t timestamp)
687 {
688 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
689 callback_->OnFrameShutter(captureId, streamIds, timestamp);
690 }
691 } // end namespace OHOS::Camera
692