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