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 CameraHalTimeSysevent::WriteCameraParameterEvent(CameraHalTimeSysevent::GetEventName(PARAMS_OFCAPTURE_OR_VEDIO),
335 setting->get());
336 CHECK_IF_EQUAL_RETURN_VALUE(method, DYNAMIC_STREAM_SWITCH_NOT_SUPPORT, INVALID_ARGUMENT);
337 {
338 std::lock_guard<std::mutex> l(streamLock_);
339 if (method == DYNAMIC_STREAM_SWITCH_NEED_INNER_RESTART) {
340 for (auto it : streamMap_) {
341 it.second->StopStream();
342 }
343 }
344
345 for (auto it : streamMap_) {
346 if (it.second->CommitStream() != RC_OK) {
347 CAMERA_LOGE("commit stream [id = %{public}d] failed.", it.first);
348 return DEVICE_ERROR;
349 }
350 }
351 }
352 RetCode rc = streamPipeline_->PreConfig(setting);
353 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, DEVICE_ERROR);
354
355 auto dev = std::static_pointer_cast<CameraDeviceVdiImpl>(device_.lock());
356 CHECK_IF_PTR_NULL_RETURN_VALUE(dev, RC_ERROR);
357 std::string cameraId;
358 dev->GetCameraId(cameraId);
359 // 2:uvc mode
360 int32_t mode1 = CameraHostConfig::GetInstance()->SearchUsbCameraId(cameraId) ? 2 : mode;
361
362 rc = streamPipeline_->CreatePipeline(mode1);
363 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
364
365 DFX_LOCAL_HITRACE_END;
366 return VDI::Camera::V1_0::NO_ERROR;
367 }
368
GetStreamAttributes(std::vector<VdiStreamAttribute> & attributes)369 int32_t StreamOperatorVdiImpl::GetStreamAttributes(std::vector<VdiStreamAttribute> &attributes)
370 {
371 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
372 HDF_CAMERA_TRACE;
373 DFX_LOCAL_HITRACE_BEGIN;
374
375 attributes.clear();
376 for (auto it : streamMap_) {
377 auto configuration = it.second->GetStreamAttribute();
378 VdiStreamAttribute attribute = {};
379 attribute.streamId_ = it.first;
380 attribute.width_ = configuration.width;
381 attribute.height_ = configuration.height;
382 attribute.overrideFormat_ = (int32_t)BufferAdapter::CameraFormatToPixelFormat(configuration.format);
383 attribute.overrideDataspace_ = configuration.dataspace;
384 attribute.producerUsage_ = BufferAdapter::CameraUsageToGrallocUsage(configuration.usage);
385 attribute.producerBufferCount_ = configuration.bufferCount;
386 attribute.maxBatchCaptureCount_ = configuration.maxCaptureCount;
387 attribute.maxCaptureCount_ = configuration.maxCaptureCount;
388 attributes.emplace_back(attribute);
389 }
390 DFX_LOCAL_HITRACE_END;
391 return VDI::Camera::V1_0::NO_ERROR;
392 }
393
AttachBufferQueue(int32_t streamId,const sptr<BufferProducerSequenceable> & bufferProducer)394 int32_t StreamOperatorVdiImpl::AttachBufferQueue(int32_t streamId,
395 const sptr<BufferProducerSequenceable> &bufferProducer)
396 {
397 CHECK_IF_EQUAL_RETURN_VALUE(streamId < 0, true, INVALID_ARGUMENT);
398 CHECK_IF_PTR_NULL_RETURN_VALUE(bufferProducer, INVALID_ARGUMENT);
399 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
400 HDF_CAMERA_TRACE;
401 DFX_LOCAL_HITRACE_BEGIN;
402
403 std::shared_ptr<IStream> stream = nullptr;
404 {
405 std::lock_guard<std::mutex> l(streamLock_);
406 auto it = streamMap_.find(streamId);
407 if (it == streamMap_.end()) {
408 return INVALID_ARGUMENT;
409 }
410 stream = it->second;
411 }
412
413 CHECK_IF_PTR_NULL_RETURN_VALUE(stream, INVALID_ARGUMENT);
414 CHECK_IF_EQUAL_RETURN_VALUE(stream->GetTunnelMode(), false, METHOD_NOT_SUPPORTED);
415
416 auto tunnel = std::make_shared<StreamTunnel>();
417 CHECK_IF_EQUAL_RETURN_VALUE(tunnel, nullptr, INSUFFICIENT_RESOURCES);
418 auto bufferQueue = const_cast<OHOS::sptr<OHOS::IBufferProducer>&>(bufferProducer->producer_);
419 RetCode rc = tunnel->AttachBufferQueue(bufferQueue);
420 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, INVALID_ARGUMENT);
421
422 rc = stream->AttachStreamTunnel(tunnel);
423 if (rc != RC_OK) {
424 CAMERA_LOGE("attach buffer queue to stream [id = %{public}d] failed", streamId);
425 return CAMERA_BUSY;
426 }
427 DFX_LOCAL_HITRACE_END;
428 return VDI::Camera::V1_0::NO_ERROR;
429 }
430
DetachBufferQueue(int32_t streamId)431 int32_t StreamOperatorVdiImpl::DetachBufferQueue(int32_t streamId)
432 {
433 CHECK_IF_EQUAL_RETURN_VALUE(streamId < 0, true, INVALID_ARGUMENT);
434 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
435 HDF_CAMERA_TRACE;
436 DFX_LOCAL_HITRACE_BEGIN;
437
438 std::shared_ptr<IStream> stream = nullptr;
439 {
440 std::lock_guard<std::mutex> l(streamLock_);
441 auto it = streamMap_.find(streamId);
442 if (it == streamMap_.end()) {
443 return INVALID_ARGUMENT;
444 }
445 stream = it->second;
446 }
447
448 CHECK_IF_PTR_NULL_RETURN_VALUE(stream, INVALID_ARGUMENT);
449 CHECK_IF_EQUAL_RETURN_VALUE(stream->GetTunnelMode(), false, METHOD_NOT_SUPPORTED);
450 RetCode rc = RC_ERROR;
451 if (stream->IsRunning()) {
452 rc = stream->StopStream();
453 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, DEVICE_ERROR);
454 }
455
456 rc = stream->DetachStreamTunnel();
457 CHECK_IF_NOT_EQUAL_RETURN_VALUE(rc, RC_OK, DEVICE_ERROR);
458
459 DFX_LOCAL_HITRACE_END;
460 return VDI::Camera::V1_0::NO_ERROR;
461 }
462
Capture(int32_t captureId,const VdiCaptureInfo & info,bool isStreaming)463 int32_t StreamOperatorVdiImpl::Capture(int32_t captureId, const VdiCaptureInfo &info, bool isStreaming)
464 {
465 CAMERA_LOGI("--- start Capture captureId = [%{public}d] ---", captureId) ;
466 CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
467 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
468 HDF_CAMERA_TRACE;
469 DFX_LOCAL_HITRACE_BEGIN;
470
471 for (auto id : info.streamIds_) {
472 std::lock_guard<std::mutex> l(streamLock_);
473 auto it = streamMap_.find(id);
474 if (it == streamMap_.end()) {
475 return INVALID_ARGUMENT;
476 }
477 }
478
479 {
480 std::lock_guard<std::mutex> l(requestLock_);
481 auto itr = requestMap_.find(captureId);
482 if (itr != requestMap_.end()) {
483 return INVALID_ARGUMENT;
484 }
485 }
486
487 std::shared_ptr<CameraMetadata> captureSetting;
488 MetadataUtils::ConvertVecToMetadata(info.captureSetting_, captureSetting);
489
490 CameraDumper &dumper = CameraDumper::GetInstance();
491 dumper.DumpMetadata("capturesetting", ENABLE_METADATA, captureSetting);
492
493 auto request =
494 std::make_shared<CaptureRequest>(captureId, info.streamIds_.size(), captureSetting,
495 info.enableShutterCallback_, isStreaming);
496 request->SetFirstRequest(!isStreaming);
497 for (auto id : info.streamIds_) {
498 std::lock_guard<std::mutex> l(streamLock_);
499 if (streamMap_.find(id) == streamMap_.end()) {
500 return DEVICE_ERROR;
501 }
502 RetCode rc = streamMap_[id]->AddRequest(request);
503 if (rc != RC_OK) {
504 return DEVICE_ERROR;
505 }
506 }
507
508 {
509 std::lock_guard<std::mutex> l(requestLock_);
510 requestMap_[captureId] = request;
511 }
512 return VDI::Camera::V1_0::NO_ERROR;
513 }
514
CancelCapture(int32_t captureId)515 int32_t StreamOperatorVdiImpl::CancelCapture(int32_t captureId)
516 {
517 CAMERA_LOGI("--- start CancelCapture captureId = [%{public}d] ---", captureId) ;
518 CHECK_IF_EQUAL_RETURN_VALUE(captureId < 0, true, INVALID_ARGUMENT);
519 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
520 HDF_CAMERA_TRACE;
521 DFX_LOCAL_HITRACE_BEGIN;
522
523 std::lock_guard<std::mutex> l(requestLock_);
524 auto itr = requestMap_.find(captureId);
525 if (itr == requestMap_.end()) {
526 CAMERA_LOGE("can't cancel capture [id = %{public}d], this capture doesn't exist", captureId);
527 return INVALID_ARGUMENT;
528 }
529
530 RetCode rc = itr->second->Cancel();
531 if (rc != RC_OK) {
532 return DEVICE_ERROR;
533 }
534 requestMap_.erase(itr);
535
536 DFX_LOCAL_HITRACE_END;
537 return VDI::Camera::V1_0::NO_ERROR;
538 }
539
ChangeToOfflineStream(const std::vector<int32_t> & streamIds,const sptr<IStreamOperatorVdiCallback> & callbackObj,sptr<IOfflineStreamOperatorVdi> & offlineOperator)540 int32_t StreamOperatorVdiImpl::ChangeToOfflineStream(const std::vector<int32_t> &streamIds,
541 const sptr<IStreamOperatorVdiCallback> &callbackObj, sptr<IOfflineStreamOperatorVdi> &offlineOperator)
542 {
543 PLACE_A_NOKILL_WATCHDOG(requestTimeoutCB_);
544 HDF_CAMERA_TRACE;
545 DFX_LOCAL_HITRACE_BEGIN;
546 CHECK_IF_PTR_NULL_RETURN_VALUE(callbackObj, INVALID_ARGUMENT);
547 // offlineOperator should not be null
548 CHECK_IF_NOT_EQUAL_RETURN_VALUE(offlineOperator, nullptr, INVALID_ARGUMENT);
549 CHECK_IF_EQUAL_RETURN_VALUE(streamIds.empty(), true, INVALID_ARGUMENT);
550
551 #ifdef CAMERA_BUILT_ON_OHOS_LITE
552 oflstor_ = std::make_shared<OfflineStreamOperatorVdiImpl>();
553 #else
554 oflstor_ = new (std::nothrow) OfflineStreamOperatorVdiImpl();
555 #endif
556 CHECK_IF_PTR_NULL_RETURN_VALUE(oflstor_, INSUFFICIENT_RESOURCES);
557
558 for (auto it : streamIds) {
559 CHECK_IF_EQUAL_RETURN_VALUE(it < 0, true, INVALID_ARGUMENT);
560 std::lock_guard<std::mutex> l(streamLock_);
561 auto streamIt = streamMap_.find(it);
562 if (streamIt == streamMap_.end()) {
563 CAMERA_LOGE("stream id %{public}d doesn't exist, change to offline mode failed.", it);
564 return INVALID_ARGUMENT;
565 }
566 // only still-capture stream can be changed to offline mode
567 if (streamMap_[it]->GetStreamAttribute().type != STILL_CAPTURE) {
568 return METHOD_NOT_SUPPORTED;
569 }
570
571 auto offlineStream = std::make_shared<OfflineStream>(it, callbackObj);
572 CHECK_IF_PTR_NULL_RETURN_VALUE(offlineStream, INSUFFICIENT_RESOURCES);
573
574 RetCode rc = streamMap_[it]->ChangeToOfflineStream(offlineStream);
575 if (rc != RC_OK) {
576 CAMERA_LOGE("stream id %{public}d change to offline mode failed.", it);
577 return DEVICE_ERROR;
578 }
579 rc = oflstor_->CommitOfflineStream(offlineStream);
580 if (rc != RC_OK) {
581 CAMERA_LOGE("stream id %{public}d, commit offline stream failed.", it);
582 return DEVICE_ERROR;
583 }
584 CAMERA_LOGI("stream %{public}d switch to offline success.", it);
585 }
586
587 offlineOperator = oflstor_;
588 DFX_LOCAL_HITRACE_END;
589 return VDI::Camera::V1_0::NO_ERROR;
590 }
591
CheckStreamInfo(const VdiStreamInfo streamInfo)592 bool StreamOperatorVdiImpl::CheckStreamInfo(const VdiStreamInfo streamInfo)
593 {
594 if (streamInfo.streamId_ < 0 || streamInfo.width_ < 0 || streamInfo.height_ < 0 || streamInfo.format_ < 0 ||
595 streamInfo.dataspace_ < 0 || streamInfo.intent_ > CUSTOM || streamInfo.intent_ < PREVIEW ||
596 streamInfo.minFrameDuration_ < 0) {
597 return false;
598 }
599 return true;
600 }
601
FillCaptureErrorInfo(std::vector<VdiCaptureErrorInfo> & info,MessageGroup message)602 void StreamOperatorVdiImpl::FillCaptureErrorInfo(std::vector<VdiCaptureErrorInfo> &info, MessageGroup message)
603 {
604 for (auto cm : message) {
605 auto m = std::static_pointer_cast<CaptureErrorMessage>(cm);
606 CHECK_IF_PTR_NULL_RETURN_VOID(m);
607 VdiCaptureErrorInfo edi = {};
608 edi.streamId_ = m->GetStreamId();
609 edi.error_ = m->GetStreamError();
610 info.push_back(edi);
611 }
612 }
613
FillCaptureEndedInfo(std::vector<VdiCaptureEndedInfo> & info,MessageGroup message)614 void StreamOperatorVdiImpl::FillCaptureEndedInfo(std::vector<VdiCaptureEndedInfo> &info, MessageGroup message)
615 {
616 for (auto cm : message) {
617 auto m = std::static_pointer_cast<CaptureEndedMessage>(cm);
618 CHECK_IF_PTR_NULL_RETURN_VOID(m);
619 VdiCaptureEndedInfo edi = {};
620 edi.streamId_ = m->GetStreamId();
621 edi.frameCount_ = m->GetFrameCount();
622 info.push_back(edi);
623 }
624 }
625
HandleCallbackMessage(MessageGroup & message)626 void StreamOperatorVdiImpl::HandleCallbackMessage(MessageGroup &message)
627 {
628 if (message.empty()) {
629 return;
630 }
631 CHECK_IF_PTR_NULL_RETURN_VOID(message[0]);
632 CaptureMessageType type = message[0]->GetMessageType();
633 switch (type) {
634 case CAPTURE_MESSAGE_TYPE_ON_STARTED: {
635 std::vector<int32_t> ids = {};
636 for (auto cm : message) {
637 auto m = std::static_pointer_cast<CaptureStartedMessage>(cm);
638 CHECK_IF_PTR_NULL_RETURN_VOID(m);
639 ids.push_back(m->GetStreamId());
640 }
641 OnCaptureStarted(message[0]->GetCaptureId(), ids);
642 break;
643 }
644 case CAPTURE_MESSAGE_TYPE_ON_ERROR: {
645 std::vector<VdiCaptureErrorInfo> info = {};
646 FillCaptureErrorInfo(info, message);
647 OnCaptureError(message[0]->GetCaptureId(), info);
648 break;
649 }
650 case CAPTURE_MESSAGE_TYPE_ON_ENDED: {
651 std::vector<VdiCaptureEndedInfo> info = {};
652 FillCaptureEndedInfo(info, message);
653 OnCaptureEnded(message[0]->GetCaptureId(), info);
654 break;
655 }
656 case CAPTURE_MESSAGE_TYPE_ON_SHUTTER: {
657 std::vector<int32_t> ids = {};
658 for (auto cm : message) {
659 auto m = std::static_pointer_cast<FrameShutterMessage>(cm);
660 CHECK_IF_PTR_NULL_RETURN_VOID(m);
661 ids.push_back(m->GetStreamId());
662 }
663 OnFrameShutter(message[0]->GetCaptureId(), ids, message[0]->GetTimestamp());
664 break;
665 }
666 default:
667 break;
668 }
669 return;
670 }
671
OnCaptureStarted(int32_t captureId,const std::vector<int32_t> & streamIds)672 void StreamOperatorVdiImpl::OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamIds)
673 {
674 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
675 callback_->OnCaptureStarted(captureId, streamIds);
676 }
677
OnCaptureEnded(int32_t captureId,const std::vector<VdiCaptureEndedInfo> & infos)678 void StreamOperatorVdiImpl::OnCaptureEnded(int32_t captureId, const std::vector<VdiCaptureEndedInfo> &infos)
679 {
680 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
681 int32_t ret = callback_->OnCaptureEnded(captureId, infos);
682 if (ret != 0) {
683 CAMERA_LOGE("OnCaptureEnded captureId: %{public}d failed, ret = %{public}d", captureId, ret);
684 return;
685 }
686
687 std::lock_guard<std::mutex> l(requestLock_);
688 auto itr = requestMap_.find(captureId);
689 if (itr == requestMap_.end()) {
690 CAMERA_LOGE("OnCaptureEnded captureId: %{public}d not found request", captureId);
691 return;
692 }
693 requestMap_.erase(itr);
694 }
695
OnCaptureError(int32_t captureId,const std::vector<VdiCaptureErrorInfo> & infos)696 void StreamOperatorVdiImpl::OnCaptureError(int32_t captureId, const std::vector<VdiCaptureErrorInfo> &infos)
697 {
698 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
699 callback_->OnCaptureError(captureId, infos);
700 }
701
OnFrameShutter(int32_t captureId,const std::vector<int32_t> & streamIds,uint64_t timestamp)702 void StreamOperatorVdiImpl::OnFrameShutter(int32_t captureId,
703 const std::vector<int32_t> &streamIds, uint64_t timestamp)
704 {
705 CHECK_IF_EQUAL_RETURN_VOID(callback_, nullptr);
706 callback_->OnFrameShutter(captureId, streamIds, timestamp);
707 }
708 } // end namespace OHOS::Camera
709