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