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