1 /*
2 * Copyright (c) 2025 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 "session/photo_session_for_sys.h"
17
18 #include <algorithm>
19 #include <cstdint>
20 #include <memory>
21
22 #include "camera_device.h"
23 #include "camera_error_code.h"
24 #include "camera_log.h"
25 #include "capture_scene_const.h"
26 #include "capture_session.h"
27 #include "input/camera_manager.h"
28 #include "output/camera_output_capability.h"
29
30 namespace OHOS {
31 namespace CameraStandard {
32 namespace {
GeneratePreconfigProfiles1_1(PreconfigType preconfigType)33 std::shared_ptr<PreconfigProfiles> GeneratePreconfigProfiles1_1(PreconfigType preconfigType)
34 {
35 std::shared_ptr<PreconfigProfiles> configs = std::make_shared<PreconfigProfiles>(ColorSpace::DISPLAY_P3);
36 switch (preconfigType) {
37 case PRECONFIG_720P:
38 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 720, .height = 720 } };
39 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
40
41 configs->photoProfile = configs->previewProfile;
42 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
43 break;
44 case PRECONFIG_1080P:
45 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1080, .height = 1080 } };
46 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
47
48 configs->photoProfile = configs->previewProfile;
49 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
50 break;
51 case PRECONFIG_4K:
52 // LCOV_EXCL_START
53 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1080, .height = 1080 } };
54 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
55
56 configs->photoProfile = configs->previewProfile;
57 configs->photoProfile.size_ = { .width = 2160, .height = 2160 };
58 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
59 break;
60 case PRECONFIG_HIGH_QUALITY:
61 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1440, .height = 1440 } };
62 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
63
64 configs->photoProfile = { CameraFormat::CAMERA_FORMAT_JPEG, { .width = 0, .height = 0 } };
65 configs->photoProfile.sizeRatio_ = RATIO_1_1;
66 configs->photoProfile.sizeFollowSensorMax_ = true;
67 break;
68 default:
69 MEDIA_ERR_LOG(
70 "PhotoSessionForSys::GeneratePreconfigProfiles1_1 not support this config:%{public}d", preconfigType);
71 return nullptr;
72 // LCOV_EXCL_STOP
73 }
74 return configs;
75 }
76
GeneratePreconfigProfiles4_3(PreconfigType preconfigType)77 std::shared_ptr<PreconfigProfiles> GeneratePreconfigProfiles4_3(PreconfigType preconfigType)
78 {
79 std::shared_ptr<PreconfigProfiles> configs = std::make_shared<PreconfigProfiles>(ColorSpace::DISPLAY_P3);
80 switch (preconfigType) {
81 case PRECONFIG_720P:
82 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 960, .height = 720 } };
83 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
84
85 configs->photoProfile = configs->previewProfile;
86 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
87 break;
88 case PRECONFIG_1080P:
89 // LCOV_EXCL_START
90 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1440, .height = 1080 } };
91 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
92
93 configs->photoProfile = configs->previewProfile;
94 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
95 break;
96 case PRECONFIG_4K:
97 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1440, .height = 1080 } };
98 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
99
100 configs->photoProfile = configs->previewProfile;
101 configs->photoProfile.size_ = { .width = 2880, .height = 2160 };
102 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
103 break;
104 case PRECONFIG_HIGH_QUALITY:
105 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1920, .height = 1440 } };
106 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
107
108 configs->photoProfile = { CameraFormat::CAMERA_FORMAT_JPEG, { .width = 0, .height = 0 } };
109 configs->photoProfile.sizeRatio_ = RATIO_4_3;
110 configs->photoProfile.sizeFollowSensorMax_ = true;
111 break;
112 default:
113 MEDIA_ERR_LOG(
114 "PhotoSessionForSys::GeneratePreconfigProfiles4_3 not support this config:%{public}d", preconfigType);
115 return nullptr;
116 // LCOV_EXCL_STOP
117 }
118 return configs;
119 }
120
GeneratePreconfigProfiles16_9(PreconfigType preconfigType)121 std::shared_ptr<PreconfigProfiles> GeneratePreconfigProfiles16_9(PreconfigType preconfigType)
122 {
123 // LCOV_EXCL_START
124 std::shared_ptr<PreconfigProfiles> configs = std::make_shared<PreconfigProfiles>(ColorSpace::DISPLAY_P3);
125 switch (preconfigType) {
126 case PRECONFIG_720P:
127 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1280, .height = 720 } };
128 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
129
130 configs->photoProfile = configs->previewProfile;
131 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
132 break;
133 case PRECONFIG_1080P:
134 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1920, .height = 1080 } };
135 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
136
137 configs->photoProfile = configs->previewProfile;
138 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
139 break;
140 case PRECONFIG_4K:
141 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 1920, .height = 1080 } };
142 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
143
144 configs->photoProfile = configs->previewProfile;
145 configs->photoProfile.size_ = { .width = 3840, .height = 2160 };
146 configs->photoProfile.format_ = CameraFormat::CAMERA_FORMAT_JPEG;
147 break;
148 case PRECONFIG_HIGH_QUALITY:
149 configs->previewProfile = { CameraFormat::CAMERA_FORMAT_YUV_420_SP, { .width = 2560, .height = 1440 } };
150 configs->previewProfile.fps_ = { .fixedFps = 30, .minFps = 12, .maxFps = 30 };
151
152 configs->photoProfile = { CameraFormat::CAMERA_FORMAT_JPEG, { .width = 0, .height = 0 } };
153 configs->photoProfile.sizeRatio_ = RATIO_16_9;
154 configs->photoProfile.sizeFollowSensorMax_ = true;
155 break;
156 default:
157 MEDIA_ERR_LOG(
158 "PhotoSessionForSys::GeneratePreconfigProfiles16_9 not support this config:%{public}d", preconfigType);
159 return nullptr;
160 }
161 return configs;
162 // LCOV_EXCL_STOP
163 }
164 } // namespace
165
CanAddOutput(sptr<CaptureOutput> & output)166 bool PhotoSessionForSys::CanAddOutput(sptr<CaptureOutput>& output)
167 {
168 // LCOV_EXCL_START
169 MEDIA_DEBUG_LOG("Enter Into PhotoSessionForSys::CanAddOutput");
170 CHECK_RETURN_RET(output == nullptr, false);
171 return output->GetOutputType() != CAPTURE_OUTPUT_TYPE_VIDEO && CaptureSession::CanAddOutput(output);
172 // LCOV_EXCL_STOP
173 }
174
GeneratePreconfigProfiles(PreconfigType preconfigType,ProfileSizeRatio preconfigRatio)175 std::shared_ptr<PreconfigProfiles> PhotoSessionForSys::GeneratePreconfigProfiles(
176 PreconfigType preconfigType, ProfileSizeRatio preconfigRatio)
177 {
178 // LCOV_EXCL_START
179 switch (preconfigRatio) {
180 case RATIO_1_1:
181 return GeneratePreconfigProfiles1_1(preconfigType);
182 case UNSPECIFIED:
183 // Fall through
184 case RATIO_4_3:
185 return GeneratePreconfigProfiles4_3(preconfigType);
186 case RATIO_16_9:
187 return GeneratePreconfigProfiles16_9(preconfigType);
188 default:
189 MEDIA_ERR_LOG("PhotoSessionForSys::GeneratePreconfigProfiles unknow profile size ratio.");
190 break;
191 }
192 return nullptr;
193 // LCOV_EXCL_STOP
194 }
195
IsPreconfigProfilesLegal(std::shared_ptr<PreconfigProfiles> configs)196 bool PhotoSessionForSys::IsPreconfigProfilesLegal(std::shared_ptr<PreconfigProfiles> configs)
197 {
198 auto cameraList = CameraManager::GetInstance()->GetSupportedCameras();
199 int32_t supportedCameraNum = 0;
200 for (auto& device : cameraList) {
201 MEDIA_INFO_LOG("PhotoSessionForSys::IsPreconfigProfilesLegal check camera:%{public}s type:%{public}d",
202 device->GetID().c_str(), device->GetCameraType());
203 if (device->GetCameraType() != CAMERA_TYPE_DEFAULT) {
204 continue;
205 }
206 // Check photo
207 bool isPhotoCanPreconfig = IsPhotoProfileLegal(device, configs->photoProfile);
208 CHECK_RETURN_RET_ELOG(!isPhotoCanPreconfig, false,
209 "PhotoSessionForSys::IsPreconfigProfilesLegal check photo profile fail, "
210 "no matched photo profiles:%{public}d %{public}dx%{public}d",
211 configs->photoProfile.format_, configs->photoProfile.size_.width, configs->photoProfile.size_.height);
212
213 // Check preview
214 bool isPreviewCanPreconfig = IsPreviewProfileLegal(device, configs->previewProfile);
215 CHECK_RETURN_RET_ELOG(!isPreviewCanPreconfig, false,
216 "PhotoSessionForSys::IsPreconfigProfilesLegal check preview profile fail, "
217 "no matched preview profiles:%{public}d %{public}dx%{public}d",
218 configs->previewProfile.format_, configs->previewProfile.size_.width, configs->previewProfile.size_.height);
219 supportedCameraNum++;
220 }
221 MEDIA_INFO_LOG(
222 "PhotoSessionForSys::IsPreconfigProfilesLegal check pass, supportedCameraNum is%{public}d", supportedCameraNum);
223 return supportedCameraNum > 0;
224 }
225
IsPhotoProfileLegal(sptr<CameraDevice> & device,Profile & photoProfile)226 bool PhotoSessionForSys::IsPhotoProfileLegal(sptr<CameraDevice>& device, Profile& photoProfile)
227 {
228 auto photoProfilesIt = device->modePhotoProfiles_.find(SceneMode::CAPTURE);
229 CHECK_RETURN_RET_ELOG(photoProfilesIt == device->modePhotoProfiles_.end(), false,
230 "PhotoSessionForSys::CanPreconfig check photo profile fail, empty photo profiles");
231 auto photoProfiles = photoProfilesIt->second;
232 return std::any_of(photoProfiles.begin(), photoProfiles.end(), [&photoProfile](auto& profile) {
233 CHECK_RETURN_RET(!photoProfile.sizeFollowSensorMax_, profile == photoProfile);
234 return IsProfileSameRatio(profile, photoProfile.sizeRatio_, RATIO_VALUE_4_3);
235 });
236 }
237
IsPreviewProfileLegal(sptr<CameraDevice> & device,Profile & previewProfile)238 bool PhotoSessionForSys::IsPreviewProfileLegal(sptr<CameraDevice>& device, Profile& previewProfile)
239 {
240 auto previewProfilesIt = device->modePreviewProfiles_.find(SceneMode::CAPTURE);
241 CHECK_RETURN_RET_ELOG(previewProfilesIt == device->modePreviewProfiles_.end(), false,
242 "PhotoSessionForSys::CanPreconfig check preview profile fail, empty preview profiles");
243 auto previewProfiles = previewProfilesIt->second;
244 return std::any_of(previewProfiles.begin(), previewProfiles.end(),
245 [&previewProfile](auto& profile) { return profile == previewProfile; });
246 }
247
CanPreconfig(PreconfigType preconfigType,ProfileSizeRatio preconfigRatio)248 bool PhotoSessionForSys::CanPreconfig(PreconfigType preconfigType, ProfileSizeRatio preconfigRatio)
249 {
250 MEDIA_INFO_LOG("PhotoSessionForSys::CanPreconfig check type:%{public}d, check ratio:%{public}d",
251 preconfigType, preconfigRatio);
252 std::shared_ptr<PreconfigProfiles> configs = GeneratePreconfigProfiles(preconfigType, preconfigRatio);
253 CHECK_RETURN_RET_ELOG(configs == nullptr, false, "PhotoSessionForSys::CanPreconfig get configs fail.");
254 return IsPreconfigProfilesLegal(configs);
255 }
256
Preconfig(PreconfigType preconfigType,ProfileSizeRatio preconfigRatio)257 int32_t PhotoSessionForSys::Preconfig(PreconfigType preconfigType, ProfileSizeRatio preconfigRatio)
258 {
259 MEDIA_INFO_LOG("PhotoSessionForSys::Preconfig type:%{public}d ratio:%{public}d", preconfigType, preconfigRatio);
260 std::shared_ptr<PreconfigProfiles> configs = GeneratePreconfigProfiles(preconfigType, preconfigRatio);
261 CHECK_RETURN_RET_ELOG(configs == nullptr, SERVICE_FATL_ERROR,
262 "PhotoSessionForSys::Preconfig not support this type:%{public}d ratio:%{public}d", preconfigType,
263 preconfigRatio);
264 CHECK_RETURN_RET_ELOG(!IsPreconfigProfilesLegal(configs), SERVICE_FATL_ERROR,
265 "PhotoSessionForSys::Preconfig preconfigProfile is illegal.");
266 SetPreconfigProfiles(configs);
267 MEDIA_INFO_LOG("PhotoSessionForSys::Preconfig %s", configs->ToString().c_str());
268 return SUCCESS;
269 }
270
CanSetFrameRateRange(int32_t minFps,int32_t maxFps,CaptureOutput * curOutput)271 bool PhotoSessionForSys::CanSetFrameRateRange(int32_t minFps, int32_t maxFps, CaptureOutput* curOutput)
272 {
273 return CanSetFrameRateRangeForOutput(minFps, maxFps, curOutput) ? true : false;
274 }
275 } // namespace CameraStandard
276 } // namespace OHOS