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