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