1 /*
2  * Copyright (c) 2021-2022 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 "output/preview_output.h"
17 
18 #include <cstdint>
19 #include <limits>
20 #include <memory>
21 #include <utility>
22 #include <variant>
23 
24 #include "camera_device_ability_items.h"
25 #include "camera_error_code.h"
26 #include "camera_log.h"
27 #include "camera_manager.h"
28 #include "camera_metadata_operator.h"
29 #include "camera_output_capability.h"
30 #include "camera_util.h"
31 #include "hstream_repeat_callback_stub.h"
32 #include "image_format.h"
33 #include "metadata_common_utils.h"
34 #include "pixel_map.h"
35 #include "session/capture_session.h"
36 #include "sketch_wrapper.h"
37 #include "parameters.h"
38 #include "bundle_mgr_interface.h"
39 #include "iservice_registry.h"
40 #include "system_ability_definition.h"
41 #include "camera_rotation_api_utils.h"
42 
43 namespace OHOS {
44 namespace CameraStandard {
45 namespace {
GetHdiFormatFromCameraFormat(CameraFormat cameraFormat)46 camera_format_t GetHdiFormatFromCameraFormat(CameraFormat cameraFormat)
47 {
48     switch (cameraFormat) {
49         case CAMERA_FORMAT_YCBCR_420_888:
50             return OHOS_CAMERA_FORMAT_YCBCR_420_888;
51         case CAMERA_FORMAT_YUV_420_SP: // nv21
52             return OHOS_CAMERA_FORMAT_YCRCB_420_SP;
53         case CAMERA_FORMAT_YCBCR_P010:
54             return OHOS_CAMERA_FORMAT_YCBCR_P010;
55         case CAMERA_FORMAT_YCRCB_P010:
56             return OHOS_CAMERA_FORMAT_YCRCB_P010;
57         case CAMERA_FORMAT_NV12: // nv12
58             return OHOS_CAMERA_FORMAT_YCBCR_420_SP;
59         case CAMERA_FORMAT_YUV_422_YUYV:
60             return OHOS_CAMERA_FORMAT_422_YUYV;
61         default:
62             return OHOS_CAMERA_FORMAT_IMPLEMENTATION_DEFINED;
63     }
64     return OHOS_CAMERA_FORMAT_IMPLEMENTATION_DEFINED;
65 }
66 } // namespace
67 
68 static constexpr int32_t SKETCH_MIN_WIDTH = 480;
PreviewOutput(sptr<IBufferProducer> bufferProducer)69 PreviewOutput::PreviewOutput(sptr<IBufferProducer> bufferProducer)
70     : CaptureOutput(CAPTURE_OUTPUT_TYPE_PREVIEW, StreamType::REPEAT, bufferProducer, nullptr)
71 {
72     PreviewFormat_ = 0;
73     PreviewSize_.height = 0;
74     PreviewSize_.width = 0;
75 }
76 
PreviewOutput()77 PreviewOutput::PreviewOutput() : PreviewOutput(nullptr)
78 {
79     PreviewFormat_ = 0;
80     PreviewSize_.height = 0;
81     PreviewSize_.width = 0;
82 }
83 
~PreviewOutput()84 PreviewOutput::~PreviewOutput()
85 {
86 }
87 
Release()88 int32_t PreviewOutput::Release()
89 {
90     {
91         std::lock_guard<std::mutex> lock(outputCallbackMutex_);
92         svcCallback_ = nullptr;
93         appCallback_ = nullptr;
94     }
95     std::lock_guard<std::mutex> lock(asyncOpMutex_);
96     MEDIA_DEBUG_LOG("Enter Into PreviewOutput::Release");
97     CHECK_ERROR_RETURN_RET_LOG(GetStream() == nullptr, CameraErrorCode::SERVICE_FATL_ERROR,
98         "PreviewOutput Failed to Release!, GetStream is nullptr");
99     auto itemStream = static_cast<IStreamRepeat*>(GetStream().GetRefPtr());
100     int32_t errCode = CAMERA_UNKNOWN_ERROR;
101     if (itemStream) {
102         errCode = itemStream->Release();
103         CHECK_ERROR_PRINT_LOG(errCode != CAMERA_OK, "Failed to release PreviewOutput!, errCode: %{public}d", errCode);
104     } else {
105         MEDIA_ERR_LOG("PreviewOutput::Release() itemStream is nullptr");
106     }
107     CaptureOutput::Release();
108     return ServiceToCameraError(errCode);
109 }
110 
OnFrameStarted()111 int32_t PreviewOutputCallbackImpl::OnFrameStarted()
112 {
113     CAMERA_SYNC_TRACE;
114     auto item = previewOutput_.promote();
115     if (item != nullptr) {
116         auto callback = item->GetApplicationCallback();
117         if (callback != nullptr) {
118             callback->OnFrameStarted();
119         } else {
120             MEDIA_INFO_LOG("Discarding PreviewOutputCallbackImpl::OnFrameStarted callback in preview");
121         }
122     } else {
123         MEDIA_INFO_LOG("PreviewOutputCallbackImpl::OnFrameStarted PreviewOutput is nullptr");
124     }
125     return CAMERA_OK;
126 }
127 
OnFrameEnded(int32_t frameCount)128 int32_t PreviewOutputCallbackImpl::OnFrameEnded(int32_t frameCount)
129 {
130     CAMERA_SYNC_TRACE;
131     auto item = previewOutput_.promote();
132     if (item != nullptr) {
133         auto callback = item->GetApplicationCallback();
134         if (callback != nullptr) {
135             callback->OnFrameEnded(frameCount);
136         } else {
137             MEDIA_INFO_LOG("Discarding PreviewOutputCallbackImpl::OnFrameEnded callback in preview");
138         }
139     } else {
140         MEDIA_INFO_LOG("PreviewOutputCallbackImpl::OnFrameEnded PreviewOutput is nullptr");
141     }
142     return CAMERA_OK;
143 }
144 
OnFrameError(int32_t errorCode)145 int32_t PreviewOutputCallbackImpl::OnFrameError(int32_t errorCode)
146 {
147     CAMERA_SYNC_TRACE;
148     auto item = previewOutput_.promote();
149     if (item != nullptr) {
150         auto callback = item->GetApplicationCallback();
151         if (callback != nullptr) {
152             callback->OnError(errorCode);
153         } else {
154             MEDIA_INFO_LOG("Discarding PreviewOutputCallbackImpl::OnFrameError callback in preview");
155         }
156     } else {
157         MEDIA_INFO_LOG("PreviewOutputCallbackImpl::OnFrameError PreviewOutput is nullptr");
158     }
159     return CAMERA_OK;
160 }
161 
OnSketchStatusChanged(SketchStatus status)162 int32_t PreviewOutputCallbackImpl::OnSketchStatusChanged(SketchStatus status)
163 {
164     auto previewOutput = previewOutput_.promote();
165     if (previewOutput != nullptr) {
166         previewOutput->OnSketchStatusChanged(status);
167     } else {
168         MEDIA_INFO_LOG("Discarding PreviewOutputCallbackImpl::OnFrameError callback in preview");
169     }
170     return CAMERA_OK;
171 }
172 
OnDeferredVideoEnhancementInfo(CaptureEndedInfoExt captureEndedInfo)173 int32_t PreviewOutputCallbackImpl::OnDeferredVideoEnhancementInfo(CaptureEndedInfoExt captureEndedInfo)
174 {
175     MEDIA_INFO_LOG("PreviewOutput::OnDeferredVideoEnhancementInfo called");
176     // empty impl
177     return CAMERA_OK;
178 }
179 
OnSketchStatusChanged(SketchStatus status)180 int32_t PreviewOutput::OnSketchStatusChanged(SketchStatus status)
181 {
182     CHECK_ERROR_RETURN_RET(sketchWrapper_ == nullptr, CAMERA_INVALID_STATE);
183     auto session = GetSession();
184     CHECK_ERROR_RETURN_RET(session == nullptr, CAMERA_INVALID_STATE);
185     SketchWrapper* wrapper = static_cast<SketchWrapper*>(sketchWrapper_.get());
186     wrapper->OnSketchStatusChanged(status, session->GetFeaturesMode());
187     return CAMERA_OK;
188 }
189 
AddDeferredSurface(sptr<Surface> surface)190 void PreviewOutput::AddDeferredSurface(sptr<Surface> surface)
191 {
192     MEDIA_INFO_LOG("PreviewOutput::AddDeferredSurface called");
193     CHECK_ERROR_RETURN_LOG(surface == nullptr, "PreviewOutput::AddDeferredSurface surface is null");
194     auto itemStream = static_cast<IStreamRepeat*>(GetStream().GetRefPtr());
195     CHECK_ERROR_RETURN_LOG(!itemStream, "PreviewOutput::AddDeferredSurface itemStream is null");
196     itemStream->AddDeferredSurface(surface->GetProducer());
197 }
198 
Start()199 int32_t PreviewOutput::Start()
200 {
201     std::lock_guard<std::mutex> lock(asyncOpMutex_);
202     MEDIA_DEBUG_LOG("Enter Into PreviewOutput::Start");
203     auto session = GetSession();
204     CHECK_ERROR_RETURN_RET_LOG(session == nullptr || !session->IsSessionCommited(),
205         CameraErrorCode::SESSION_NOT_CONFIG, "PreviewOutput Failed to Start, session not commited");
206     CHECK_ERROR_RETURN_RET_LOG(GetStream() == nullptr, CameraErrorCode::SERVICE_FATL_ERROR,
207         "PreviewOutput Failed to Start, GetStream is nullptr");
208     auto itemStream = static_cast<IStreamRepeat*>(GetStream().GetRefPtr());
209     int32_t errCode = CAMERA_UNKNOWN_ERROR;
210     if (itemStream) {
211         errCode = itemStream->Start();
212         CHECK_ERROR_PRINT_LOG(errCode != CAMERA_OK, "PreviewOutput Failed to Start!, errCode: %{public}d", errCode);
213     } else {
214         MEDIA_ERR_LOG("PreviewOutput::Start itemStream is nullptr");
215     }
216     return ServiceToCameraError(errCode);
217 }
218 
Stop()219 int32_t PreviewOutput::Stop()
220 {
221     std::lock_guard<std::mutex> lock(asyncOpMutex_);
222     MEDIA_DEBUG_LOG("Enter Into PreviewOutput::Stop");
223     CHECK_ERROR_RETURN_RET_LOG(GetStream() == nullptr, CameraErrorCode::SERVICE_FATL_ERROR,
224         "PreviewOutput Failed to Stop, GetStream is nullptr");
225     auto itemStream = static_cast<IStreamRepeat*>(GetStream().GetRefPtr());
226     int32_t errCode = CAMERA_UNKNOWN_ERROR;
227     if (itemStream) {
228         errCode = itemStream->Stop();
229         CHECK_ERROR_PRINT_LOG(errCode != CAMERA_OK, "PreviewOutput Failed to Stop!, errCode: %{public}d", errCode);
230     } else {
231         MEDIA_ERR_LOG("PreviewOutput::Stop itemStream is nullptr");
232     }
233     return ServiceToCameraError(errCode);
234 }
235 
IsSketchSupported()236 bool PreviewOutput::IsSketchSupported()
237 {
238     MEDIA_DEBUG_LOG("Enter Into PreviewOutput::IsSketchSupported");
239 
240     auto sketchSize = FindSketchSize();
241     CHECK_ERROR_RETURN_RET(sketchSize == nullptr, false);
242     MEDIA_INFO_LOG(
243         "IsSketchSupported FindSketchSize Size is %{public}dx%{public}d", sketchSize->width, sketchSize->height);
244     auto sketchRatio = GetSketchRatio();
245     if (sketchRatio > 0) {
246         return true;
247     }
248     MEDIA_DEBUG_LOG("IsSketchSupported GetSketchRatio failed, %{public}f ", sketchRatio);
249     auto session = GetSession();
250     CHECK_ERROR_RETURN_RET(session == nullptr, false);
251     SketchWrapper::UpdateSketchStaticInfo(GetDeviceMetadata());
252     auto subModeNames = session->GetSubFeatureMods();
253     for (auto subModeName : subModeNames) {
254         float ratio = SketchWrapper::GetSketchEnableRatio(subModeName);
255         if (ratio > 0) {
256             MEDIA_DEBUG_LOG("IsSketchSupported GetSketchEnableRatio success,subMode:%{public}s, ratio:%{public}f ",
257                 subModeName.Dump().c_str(), ratio);
258             return true;
259         }
260     }
261     return false;
262 }
263 
GetSketchRatio()264 float PreviewOutput::GetSketchRatio()
265 {
266     MEDIA_DEBUG_LOG("Enter Into PreviewOutput::GetSketchRatio");
267 
268     auto session = GetSession();
269     if (session == nullptr) {
270         MEDIA_WARNING_LOG("PreviewOutput::GetSketchRatio session is null");
271         return -1.0f;
272     }
273     auto currentMode = session->GetFeaturesMode();
274     SketchWrapper::UpdateSketchStaticInfo(GetDeviceMetadata());
275     float ratio = SketchWrapper::GetSketchEnableRatio(currentMode);
276     if (ratio <= 0) {
277         MEDIA_WARNING_LOG("PreviewOutput::GetSketchRatio mode:%{public}s", currentMode.Dump().c_str());
278     }
279     return ratio;
280 }
281 
CreateSketchWrapper(Size sketchSize)282 int32_t PreviewOutput::CreateSketchWrapper(Size sketchSize)
283 {
284     MEDIA_DEBUG_LOG("PreviewOutput::CreateSketchWrapper enter sketchSize is:%{public}d x %{public}d", sketchSize.width,
285         sketchSize.height);
286     auto session = GetSession();
287     CHECK_ERROR_RETURN_RET_LOG(session == nullptr, ServiceToCameraError(CAMERA_INVALID_STATE),
288         "EnableSketch session null");
289     auto wrapper = std::make_shared<SketchWrapper>(GetStream(), sketchSize);
290     sketchWrapper_ = wrapper;
291     auto metadata = GetDeviceMetadata();
292     int32_t retCode = wrapper->Init(metadata, session->GetFeaturesMode());
293     wrapper->SetPreviewStateCallback(appCallback_);
294     return ServiceToCameraError(retCode);
295 }
296 
EnableSketch(bool isEnable)297 int32_t PreviewOutput::EnableSketch(bool isEnable)
298 {
299     MEDIA_DEBUG_LOG("Enter Into PreviewOutput::EnableSketch %{public}d", isEnable);
300     CHECK_ERROR_RETURN_RET_LOG(!IsSketchSupported(), CameraErrorCode::OPERATION_NOT_ALLOWED,
301         "EnableSketch IsSketchSupported is false");
302     int32_t errCode = CAMERA_UNKNOWN_ERROR;
303     std::lock_guard<std::mutex> lock(asyncOpMutex_);
304 
305     auto session = GetSession();
306     CHECK_ERROR_RETURN_RET_LOG(session == nullptr || !session->IsSessionConfiged(),
307         CameraErrorCode::SESSION_NOT_CONFIG, "PreviewOutput Failed EnableSketch!, session not config");
308 
309     if (isEnable) {
310         CHECK_ERROR_RETURN_RET(sketchWrapper_ != nullptr, ServiceToCameraError(CAMERA_OPERATION_NOT_ALLOWED));
311         auto sketchSize = FindSketchSize();
312         CHECK_ERROR_RETURN_RET_LOG(sketchSize == nullptr, ServiceToCameraError(errCode),
313             "PreviewOutput EnableSketch FindSketchSize is null");
314         MEDIA_INFO_LOG("EnableSketch FindSketchSize Size is %{public}dx%{public}d",
315             sketchSize->width, sketchSize->height);
316         return CreateSketchWrapper(*sketchSize);
317     }
318 
319     // Disable sketch branch
320     CHECK_ERROR_RETURN_RET(sketchWrapper_ == nullptr, ServiceToCameraError(CAMERA_OPERATION_NOT_ALLOWED));
321     errCode = sketchWrapper_->Destroy();
322     sketchWrapper_ = nullptr;
323     return ServiceToCameraError(errCode);
324 }
325 
AttachSketchSurface(sptr<Surface> sketchSurface)326 int32_t PreviewOutput::AttachSketchSurface(sptr<Surface> sketchSurface)
327 {
328     auto session = GetSession();
329     CHECK_ERROR_RETURN_RET_LOG(session == nullptr || !session->IsSessionCommited(),
330         CameraErrorCode::SESSION_NOT_CONFIG, "PreviewOutput Failed to AttachSketchSurface, session not commited");
331     CHECK_ERROR_RETURN_RET(sketchWrapper_ == nullptr, CameraErrorCode::INVALID_ARGUMENT);
332     CHECK_ERROR_RETURN_RET(sketchSurface == nullptr, CameraErrorCode::INVALID_ARGUMENT);
333     int32_t errCode = sketchWrapper_->AttachSketchSurface(sketchSurface);
334     return ServiceToCameraError(errCode);
335 }
336 
CreateStream()337 int32_t PreviewOutput::CreateStream()
338 {
339     auto stream = GetStream();
340     CHECK_ERROR_RETURN_RET_LOG(stream != nullptr, CameraErrorCode::OPERATION_NOT_ALLOWED,
341         "PreviewOutput::CreateStream stream is not null");
342     auto producer = GetBufferProducer();
343     CHECK_ERROR_RETURN_RET_LOG(producer == nullptr, CameraErrorCode::OPERATION_NOT_ALLOWED,
344         "PreviewOutput::CreateStream producer is null");
345     sptr<IStreamRepeat> streamPtr = nullptr;
346     auto previewProfile = GetPreviewProfile();
347     CHECK_ERROR_RETURN_RET_LOG(previewProfile == nullptr, CameraErrorCode::SERVICE_FATL_ERROR,
348         "PreviewOutput::CreateStream previewProfile is null");
349     int32_t res =
350         CameraManager::GetInstance()->CreatePreviewOutputStream(streamPtr, *previewProfile, GetBufferProducer());
351     SetStream(streamPtr);
352     return res;
353 }
354 
GetFrameRateRange()355 const std::vector<int32_t>& PreviewOutput::GetFrameRateRange()
356 {
357     return previewFrameRateRange_;
358 }
359 
SetFrameRateRange(int32_t minFrameRate,int32_t maxFrameRate)360 void PreviewOutput::SetFrameRateRange(int32_t minFrameRate, int32_t maxFrameRate)
361 {
362     MEDIA_DEBUG_LOG("PreviewOutput::SetFrameRateRange min = %{public}d and max = %{public}d",
363                     minFrameRate, maxFrameRate);
364     previewFrameRateRange_ = { minFrameRate, maxFrameRate };
365 }
366 
SetOutputFormat(int32_t format)367 void PreviewOutput::SetOutputFormat(int32_t format)
368 {
369     MEDIA_DEBUG_LOG("PreviewOutput::SetOutputFormat set format %{public}d", format);
370     PreviewFormat_ = format;
371 }
372 
SetSize(Size size)373 void PreviewOutput::SetSize(Size size)
374 {
375     MEDIA_DEBUG_LOG("PreviewOutput::SetSize set size %{public}d, %{public}d", size.width, size.height);
376     PreviewSize_ = size;
377 }
378 
SetFrameRate(int32_t minFrameRate,int32_t maxFrameRate)379 int32_t PreviewOutput::SetFrameRate(int32_t minFrameRate, int32_t maxFrameRate)
380 {
381     int32_t result = canSetFrameRateRange(minFrameRate, maxFrameRate);
382     CHECK_ERROR_RETURN_RET(result != CameraErrorCode::SUCCESS, result);
383     CHECK_ERROR_RETURN_RET_LOG(minFrameRate == previewFrameRateRange_[0] && maxFrameRate == previewFrameRateRange_[1],
384         CameraErrorCode::INVALID_ARGUMENT, "PreviewOutput::SetFrameRate The frame rate does not need to be set.");
385     std::vector<int32_t> frameRateRange = {minFrameRate, maxFrameRate};
386     auto itemStream = static_cast<IStreamRepeat*>(GetStream().GetRefPtr());
387     if (itemStream) {
388         int32_t ret = itemStream->SetFrameRate(minFrameRate, maxFrameRate);
389         CHECK_ERROR_RETURN_RET_LOG(ret != CAMERA_OK, ServiceToCameraError(ret),
390             "PreviewOutput::setFrameRate failed to set stream frame rate");
391         SetFrameRateRange(minFrameRate, maxFrameRate);
392     }
393     auto session = GetSession();
394     wptr<PreviewOutput> weakThis(this);
395     CHECK_EXECUTE(session, session->AddFunctionToMap("preview" + std::to_string(OHOS_CONTROL_FPS_RANGES),
396         [weakThis, minFrameRate, maxFrameRate]() {
397             auto sharedThis = weakThis.promote();
398             if (!sharedThis) {
399                 MEDIA_ERR_LOG("SetFrameRate previewOutput is nullptr");
400                 return;
401             }
402             sharedThis->SetFrameRate(minFrameRate, maxFrameRate);
403         }));
404     return CameraErrorCode::SUCCESS;
405 }
406 
GetSupportedFrameRates()407 std::vector<std::vector<int32_t>> PreviewOutput::GetSupportedFrameRates()
408 {
409     MEDIA_DEBUG_LOG("PreviewOutput::GetSupportedFrameRates called.");
410     auto session = GetSession();
411     CHECK_ERROR_RETURN_RET(session == nullptr, {});
412     auto inputDevice = session->GetInputDevice();
413     CHECK_ERROR_RETURN_RET(inputDevice == nullptr, {});
414     sptr<CameraDevice> camera = inputDevice->GetCameraDeviceInfo();
415     SceneMode curMode = session->GetMode();
416 
417     sptr<CameraOutputCapability> cameraOutputCapability = CameraManager::GetInstance()->
418                                                           GetSupportedOutputCapability(camera, curMode);
419     CHECK_ERROR_RETURN_RET(cameraOutputCapability == nullptr, {});
420     std::vector<Profile> supportedProfiles = cameraOutputCapability->GetPreviewProfiles();
421     supportedProfiles.erase(std::remove_if(
422         supportedProfiles.begin(), supportedProfiles.end(),
423         [&](Profile& profile) {
424             return profile.format_ != PreviewFormat_ ||
425                    profile.GetSize().height != PreviewSize_.height ||
426                    profile.GetSize().width != PreviewSize_.width;
427         }), supportedProfiles.end());
428     std::vector<std::vector<int32_t>> supportedFrameRatesRange;
429     for (auto item : supportedProfiles) {
430         std::vector<int32_t> supportedFrameRatesItem = {item.fps_.minFps, item.fps_.maxFps};
431         supportedFrameRatesRange.emplace_back(supportedFrameRatesItem);
432     }
433     std::set<std::vector<int>> set(supportedFrameRatesRange.begin(), supportedFrameRatesRange.end());
434     supportedFrameRatesRange.assign(set.begin(), set.end());
435     MEDIA_DEBUG_LOG("PreviewOutput::GetSupportedFrameRates frameRateRange size:%{public}zu",
436                     supportedFrameRatesRange.size());
437     return supportedFrameRatesRange;
438 }
439 
StartSketch()440 int32_t PreviewOutput::StartSketch()
441 {
442     int32_t errCode = CAMERA_UNKNOWN_ERROR;
443 
444     auto session = GetSession();
445     CHECK_ERROR_RETURN_RET_LOG(session == nullptr || !session->IsSessionCommited(),
446         CameraErrorCode::SESSION_NOT_CONFIG,
447         "PreviewOutput Failed to StartSketch, session not commited");
448     if (sketchWrapper_ != nullptr) {
449         errCode = sketchWrapper_->StartSketchStream();
450     }
451     return ServiceToCameraError(errCode);
452 }
453 
StopSketch()454 int32_t PreviewOutput::StopSketch()
455 {
456     int32_t errCode = CAMERA_UNKNOWN_ERROR;
457 
458     auto session = GetSession();
459     CHECK_ERROR_RETURN_RET_LOG(session == nullptr || !session->IsSessionCommited(),
460         CameraErrorCode::SESSION_NOT_CONFIG,
461         "PreviewOutput Failed to StopSketch, session not commited");
462     if (sketchWrapper_ != nullptr) {
463         errCode = sketchWrapper_->StopSketchStream();
464     }
465     return ServiceToCameraError(errCode);
466 }
467 
GetDeviceMetadata()468 std::shared_ptr<Camera::CameraMetadata> PreviewOutput::GetDeviceMetadata()
469 {
470     auto session = GetSession();
471     CHECK_ERROR_RETURN_RET_LOG(session == nullptr, nullptr, "PreviewOutput::GetDeviceMetadata session is null");
472     auto inputDevice = session->GetInputDevice();
473     CHECK_ERROR_RETURN_RET_LOG(inputDevice == nullptr, nullptr, "PreviewOutput::GetDeviceMetadata input is null");
474     auto deviceInfo = inputDevice->GetCameraDeviceInfo();
475     CHECK_ERROR_RETURN_RET_LOG(deviceInfo == nullptr, nullptr, "PreviewOutput::GetDeviceMetadata info is null");
476     auto metaData = deviceInfo->GetMetadata();
477     CHECK_ERROR_RETURN_RET_LOG(metaData == nullptr, nullptr, "PreviewOutput::GetDeviceMetadata metaData is null");
478     return metaData;
479 }
480 
FindSketchSize()481 std::shared_ptr<Size> PreviewOutput::FindSketchSize()
482 {
483     auto session = GetSession();
484     auto metaData = GetDeviceMetadata();
485     CHECK_ERROR_RETURN_RET_LOG(session == nullptr || metaData == nullptr, nullptr,
486         "PreviewOutput::FindSketchSize GetDeviceMetadata failed");
487     auto profile = GetPreviewProfile();
488     CHECK_ERROR_RETURN_RET_LOG(profile == nullptr, nullptr, "PreviewOutput::FindSketchSize profile is nullptr");
489     camera_format_t hdi_format = GetHdiFormatFromCameraFormat(profile->GetCameraFormat());
490     CHECK_ERROR_RETURN_RET_LOG(hdi_format == OHOS_CAMERA_FORMAT_IMPLEMENTATION_DEFINED, nullptr,
491         "PreviewOutput::FindSketchSize preview format is illegal");
492     auto sizeList = MetadataCommonUtils::GetSupportedPreviewSizeRange(
493         session->GetFeaturesMode().GetSceneMode(), hdi_format, metaData);
494     CHECK_ERROR_RETURN_RET(sizeList == nullptr || sizeList->size() == 0, nullptr);
495     Size previewSize = profile->GetSize();
496     CHECK_ERROR_RETURN_RET(previewSize.width <= 0 || previewSize.height <= 0, nullptr);
497     float ratio = static_cast<float>(previewSize.width) / previewSize.height;
498     MEDIA_INFO_LOG("PreviewOutput::FindSketchSize preview size:%{public}dx%{public}d,ratio:%{public}f",
499         previewSize.width, previewSize.height, ratio);
500     std::shared_ptr<Size> outSize;
501     for (auto size : *sizeList.get()) {
502         if (size.width >= previewSize.width || size.width < SKETCH_MIN_WIDTH) {
503             continue;
504         }
505         float checkRatio = static_cast<float>(size.width) / size.height;
506         MEDIA_DEBUG_LOG("PreviewOutput::FindSketchSize List size:%{public}dx%{public}d,ratio:%{public}f", size.width,
507             size.height, checkRatio);
508         if (abs(checkRatio - ratio) / ratio <= 0.05f) { // 0.05f is 5% tolerance
509             if (outSize == nullptr) {
510                 outSize = std::make_shared<Size>(size);
511             } else if (size.width < outSize->width) {
512                 outSize = std::make_shared<Size>(size);
513             }
514         }
515     }
516     return outSize;
517 }
518 
SetCallback(std::shared_ptr<PreviewStateCallback> callback)519 void PreviewOutput::SetCallback(std::shared_ptr<PreviewStateCallback> callback)
520 {
521     std::lock_guard<std::mutex> lock(outputCallbackMutex_);
522     appCallback_ = callback;
523     if (appCallback_ != nullptr) {
524         if (svcCallback_ == nullptr) {
525             svcCallback_ = new (std::nothrow) PreviewOutputCallbackImpl(this);
526             if (svcCallback_ == nullptr) {
527                 MEDIA_ERR_LOG("new PreviewOutputCallbackImpl Failed to register callback");
528                 appCallback_ = nullptr;
529                 return;
530             }
531         }
532         CHECK_ERROR_RETURN_LOG(GetStream() == nullptr, "PreviewOutput Failed to SetCallback!, GetStream is nullptr");
533         auto itemStream = static_cast<IStreamRepeat*>(GetStream().GetRefPtr());
534         int32_t errorCode = CAMERA_OK;
535         if (itemStream) {
536             errorCode = itemStream->SetCallback(svcCallback_);
537         } else {
538             MEDIA_ERR_LOG("PreviewOutput::SetCallback itemStream is nullptr");
539         }
540         if (errorCode != CAMERA_OK) {
541             MEDIA_ERR_LOG("PreviewOutput::SetCallback: Failed to register callback, errorCode: %{public}d", errorCode);
542             svcCallback_ = nullptr;
543             appCallback_ = nullptr;
544         }
545     }
546     if (sketchWrapper_ != nullptr) {
547         SketchWrapper* wrapper = static_cast<SketchWrapper*>(sketchWrapper_.get());
548         wrapper->SetPreviewStateCallback(appCallback_);
549     }
550     return;
551 }
552 
GetObserverControlTags()553 const std::set<camera_device_metadata_tag_t>& PreviewOutput::GetObserverControlTags()
554 {
555     const static std::set<camera_device_metadata_tag_t> tags = { OHOS_CONTROL_ZOOM_RATIO, OHOS_CONTROL_CAMERA_MACRO,
556         OHOS_CONTROL_MOON_CAPTURE_BOOST, OHOS_CONTROL_SMOOTH_ZOOM_RATIOS };
557     return tags;
558 }
559 
OnControlMetadataChanged(const camera_device_metadata_tag_t tag,const camera_metadata_item_t & metadataItem)560 int32_t PreviewOutput::OnControlMetadataChanged(
561     const camera_device_metadata_tag_t tag, const camera_metadata_item_t& metadataItem)
562 {
563     // Don't trust outer public interface passthrough data. Check the legitimacy of the data.
564     CHECK_ERROR_RETURN_RET(metadataItem.count <= 0, CAM_META_INVALID_PARAM);
565     CHECK_ERROR_RETURN_RET(sketchWrapper_ == nullptr, CAM_META_FAILURE);
566     auto session = GetSession();
567     CHECK_ERROR_RETURN_RET(session == nullptr, CAM_META_FAILURE);
568     std::lock_guard<std::mutex> lock(asyncOpMutex_);
569     SketchWrapper* wrapper = reinterpret_cast<SketchWrapper*>(sketchWrapper_.get());
570     wrapper->OnMetadataDispatch(session->GetFeaturesMode(), tag, metadataItem);
571     return CAM_META_SUCCESS;
572 }
573 
OnResultMetadataChanged(const camera_device_metadata_tag_t tag,const camera_metadata_item_t & metadataItem)574 int32_t PreviewOutput::OnResultMetadataChanged(
575     const camera_device_metadata_tag_t tag, const camera_metadata_item_t& metadataItem)
576 {
577     // Don't trust outer public interface passthrough data. Check the legitimacy of the data.
578     CHECK_ERROR_RETURN_RET(metadataItem.count <= 0, CAM_META_INVALID_PARAM);
579     CHECK_ERROR_RETURN_RET(sketchWrapper_ == nullptr, CAM_META_FAILURE);
580     auto session = GetSession();
581     CHECK_ERROR_RETURN_RET(session == nullptr, CAM_META_FAILURE);
582     std::lock_guard<std::mutex> lock(asyncOpMutex_);
583     SketchWrapper* wrapper = reinterpret_cast<SketchWrapper*>(sketchWrapper_.get());
584     wrapper->OnMetadataDispatch(session->GetFeaturesMode(), tag, metadataItem);
585     return CAM_META_SUCCESS;
586 }
587 
GetApplicationCallback()588 std::shared_ptr<PreviewStateCallback> PreviewOutput::GetApplicationCallback()
589 {
590     std::lock_guard<std::mutex>lock(outputCallbackMutex_);
591     return appCallback_;
592 }
593 
OnNativeRegisterCallback(const std::string & eventString)594 void PreviewOutput::OnNativeRegisterCallback(const std::string& eventString)
595 {
596     if (eventString == CONST_SKETCH_STATUS_CHANGED) {
597         std::lock_guard<std::mutex> lock(asyncOpMutex_);
598         CHECK_ERROR_RETURN(sketchWrapper_ == nullptr);
599         auto session = GetSession();
600         CHECK_ERROR_RETURN(session == nullptr || !session->IsSessionCommited());
601         auto metadata = GetDeviceMetadata();
602         CHECK_ERROR_RETURN_LOG(metadata == nullptr, "metadata is nullptr");
603         camera_metadata_item_t item;
604         int ret = Camera::FindCameraMetadataItem(metadata->get(), OHOS_CONTROL_ZOOM_RATIO, &item);
605         CHECK_ERROR_RETURN(ret != CAM_META_SUCCESS || item.count <= 0);
606         float tagRatio = *item.data.f;
607         CHECK_ERROR_RETURN(tagRatio <= 0);
608         float sketchRatio = sketchWrapper_->GetSketchEnableRatio(session->GetFeaturesMode());
609         MEDIA_DEBUG_LOG("PreviewOutput::OnNativeRegisterCallback OHOS_CONTROL_ZOOM_RATIO >>> tagRatio:%{public}f -- "
610                         "sketchRatio:%{public}f",
611             tagRatio, sketchRatio);
612         sketchWrapper_->UpdateSketchRatio(sketchRatio);
613         sketchWrapper_->UpdateZoomRatio(tagRatio);
614     }
615 }
616 
OnNativeUnregisterCallback(const std::string & eventString)617 void PreviewOutput::OnNativeUnregisterCallback(const std::string& eventString)
618 {
619     if (eventString == CONST_SKETCH_STATUS_CHANGED) {
620         std::lock_guard<std::mutex> lock(asyncOpMutex_);
621         if (sketchWrapper_ == nullptr) {
622             return;
623         }
624         sketchWrapper_->StopSketchStream();
625     }
626 }
627 
CameraServerDied(pid_t pid)628 void PreviewOutput::CameraServerDied(pid_t pid)
629 {
630     MEDIA_ERR_LOG("camera server has died, pid:%{public}d!", pid);
631     std::lock_guard<std::mutex> lock(outputCallbackMutex_);
632     if (appCallback_ != nullptr) {
633         MEDIA_DEBUG_LOG("appCallback not nullptr");
634         int32_t serviceErrorType = ServiceToCameraError(CAMERA_INVALID_STATE);
635         appCallback_->OnError(serviceErrorType);
636     }
637 }
638 
canSetFrameRateRange(int32_t minFrameRate,int32_t maxFrameRate)639 int32_t PreviewOutput::canSetFrameRateRange(int32_t minFrameRate, int32_t maxFrameRate)
640 {
641     auto session = GetSession();
642     CHECK_ERROR_RETURN_RET_LOG(session == nullptr, CameraErrorCode::SESSION_NOT_CONFIG,
643         "PreviewOutput::canSetFrameRateRange Can not set frame rate range without commit session");
644     CHECK_ERROR_RETURN_RET_LOG(!session->CanSetFrameRateRange(minFrameRate, maxFrameRate, this),
645         CameraErrorCode::UNRESOLVED_CONFLICTS_BETWEEN_STREAMS,
646         "PreviewOutput::canSetFrameRateRange Can not set frame rate range with wrong state of output");
647     int32_t minIndex = 0;
648     int32_t maxIndex = 1;
649     std::vector<std::vector<int32_t>> supportedFrameRange = GetSupportedFrameRates();
650     for (auto item : supportedFrameRange) {
651         if (item[minIndex] <= minFrameRate && item[maxIndex] >= maxFrameRate) {
652             return CameraErrorCode::SUCCESS;
653         }
654     }
655     MEDIA_WARNING_LOG("Can not set frame rate range with invalid parameters");
656     return CameraErrorCode::INVALID_ARGUMENT;
657 }
GetPreviewRotation(int32_t imageRotation)658 int32_t PreviewOutput::GetPreviewRotation(int32_t imageRotation)
659 {
660     MEDIA_INFO_LOG("PreviewOutput GetPreviewRotation is called");
661     CHECK_ERROR_RETURN_RET_LOG(imageRotation % ROTATION_90_DEGREES != 0, INVALID_ARGUMENT,
662         "PreviewOutput GetPreviewRotation error!, invalid argument");
663     int32_t sensorOrientation = 0;
664     camera_metadata_item_t item;
665     ImageRotation result = ImageRotation::ROTATION_0;
666     sptr<CameraDevice> cameraObj;
667     auto session = GetSession();
668     CHECK_ERROR_RETURN_RET_LOG(session == nullptr, SERVICE_FATL_ERROR,
669         "PreviewOutput GetPreviewRotation error!, session is nullptr");
670     auto inputDevice = session->GetInputDevice();
671     CHECK_ERROR_RETURN_RET_LOG(inputDevice == nullptr, SERVICE_FATL_ERROR,
672         "PreviewOutput GetPreviewRotation error!, inputDevice is nullptr");
673     cameraObj = inputDevice->GetCameraDeviceInfo();
674     CHECK_ERROR_RETURN_RET_LOG(cameraObj == nullptr, SERVICE_FATL_ERROR,
675         "PreviewOutput GetPreviewRotation error!, cameraObj is nullptr");
676     std::shared_ptr<Camera::CameraMetadata> metadata = cameraObj->GetMetadata();
677     CHECK_ERROR_RETURN_RET(metadata == nullptr, SERVICE_FATL_ERROR);
678     int32_t ret = Camera::FindCameraMetadataItem(metadata->get(), OHOS_SENSOR_ORIENTATION, &item);
679     CHECK_ERROR_RETURN_RET_LOG(ret != CAM_META_SUCCESS, SERVICE_FATL_ERROR,
680         "PreviewOutput Can not find OHOS_SENSOR_ORIENTATION");
681     uint32_t apiCompatibleVersion = CameraApiVersion::GetApiVersion();
682     if (apiCompatibleVersion < CameraApiVersion::APIVersion::API_FOURTEEN) {
683         imageRotation = JudegRotationFunc(imageRotation);
684     }
685     sensorOrientation = item.data.i32[0];
686     result = (ImageRotation)((imageRotation + sensorOrientation) % CAPTURE_ROTATION_BASE);
687     MEDIA_INFO_LOG("PreviewOutput GetPreviewRotation :result %{public}d, sensorOrientation:%{public}d",
688         result, sensorOrientation);
689     return result;
690 }
691 
JudegRotationFunc(int32_t imageRotation)692 int32_t PreviewOutput::JudegRotationFunc(int32_t imageRotation)
693 {
694     std::string deviceType = OHOS::system::GetDeviceType();
695     if (imageRotation > CAPTURE_ROTATION_BASE) {
696         return INVALID_ARGUMENT;
697     }
698     bool isTableFlag = system::GetBoolParameter("const.multimedia.enable_camera_rotation_compensation", 0);
699     uint32_t apiCompatibleVersion = CameraApiVersion::GetApiVersion();
700     if (isTableFlag && apiCompatibleVersion < CameraApiVersion::APIVersion::API_FOURTEEN) {
701         imageRotation = ((imageRotation - ROTATION_90_DEGREES + CAPTURE_ROTATION_BASE) % CAPTURE_ROTATION_BASE);
702     }
703     return imageRotation;
704 }
705 
SetPreviewRotation(int32_t imageRotation,bool isDisplayLocked)706 int32_t PreviewOutput::SetPreviewRotation(int32_t imageRotation, bool isDisplayLocked)
707 {
708     MEDIA_INFO_LOG("PreviewOutput SetPreviewRotation is called");
709     CHECK_ERROR_RETURN_RET_LOG(imageRotation % ROTATION_90_DEGREES != 0, INVALID_ARGUMENT,
710         "PreviewOutput SetPreviewRotation error!, invalid argument");
711     int32_t sensorOrientation = 0;
712     camera_metadata_item_t item;
713     ImageRotation result = ROTATION_0;
714     sptr<CameraDevice> cameraObj;
715     auto session = GetSession();
716     CHECK_ERROR_RETURN_RET_LOG(session == nullptr, SERVICE_FATL_ERROR,
717         "PreviewOutput SetPreviewRotation error!, session is nullptr");
718     auto inputDevice = session->GetInputDevice();
719     CHECK_ERROR_RETURN_RET_LOG(inputDevice == nullptr, SERVICE_FATL_ERROR,
720         "PreviewOutput SetPreviewRotation error!, inputDevice is nullptr");
721     cameraObj = inputDevice->GetCameraDeviceInfo();
722     CHECK_ERROR_RETURN_RET_LOG(cameraObj == nullptr, SERVICE_FATL_ERROR,
723         "PreviewOutput SetPreviewRotation error!, cameraObj is nullptr");
724     std::shared_ptr<Camera::CameraMetadata> metadata = cameraObj->GetMetadata();
725     CHECK_ERROR_RETURN_RET(metadata == nullptr, SERVICE_FATL_ERROR);
726     int32_t ret = Camera::FindCameraMetadataItem(metadata->get(), OHOS_SENSOR_ORIENTATION, &item);
727     CHECK_ERROR_RETURN_RET_LOG(ret != CAM_META_SUCCESS, SERVICE_FATL_ERROR,
728         "PreviewOutput Can not find OHOS_SENSOR_ORIENTATION");
729     sensorOrientation = item.data.i32[0];
730     result = isDisplayLocked ? ImageRotation(sensorOrientation) : ImageRotation(imageRotation);
731     MEDIA_INFO_LOG("PreviewOutput SetPreviewRotation :result %{public}d, sensorOrientation:%{public}d",
732         result, sensorOrientation);
733     auto itemStream = static_cast<IStreamRepeat*>(GetStream().GetRefPtr());
734     int32_t errCode = CAMERA_UNKNOWN_ERROR;
735     if (itemStream) {
736         errCode = itemStream->SetCameraRotation(true, result);
737         CHECK_ERROR_RETURN_RET_LOG(errCode != CAMERA_OK, SERVICE_FATL_ERROR,
738             "Failed to SetCameraRotation! , errCode: %{public}d", errCode);
739     } else {
740         MEDIA_ERR_LOG("PreviewOutput::SetCameraRotation() itemStream is nullptr");
741         return CameraErrorCode::SERVICE_FATL_ERROR;
742     }
743     return CameraErrorCode::SUCCESS;
744 }
745 } // namespace CameraStandard
746 } // namespace OHOS
747