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