1/* 2 * Copyright (c) 2021 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 16import photoAccessHelper from '@ohos.file.photoAccessHelper'; 17import { BusinessError } from '@ohos.base' 18import { GlobalContext } from '../comFile/utils/GlobalContext' 19import camera from '@ohos.multimedia.camera'; 20 21const TAG: string = 'CameraService' 22 23class CameraService { 24 private cameraManager: camera.CameraManager | undefined = undefined 25 private cameras: Array<camera.CameraDevice> | Array<camera.CameraDevice> = [] 26 private cameraInput: camera.CameraInput | undefined = undefined 27 private previewOutput: camera.PreviewOutput | undefined = undefined 28 private photoOutput: camera.PhotoOutput | undefined = undefined 29 private session: camera.PhotoSession | undefined = undefined 30 private handlePhotoAssetCb: (photoAsset: photoAccessHelper.PhotoAsset) => void = () => { 31 } 32 private curCameraDevice: camera.CameraDevice | undefined = undefined 33 // 推荐拍照分辨率之一 34 private photoProfileObj: camera.Profile = { 35 format: 2000, 36 size: { 37 width: 1920, 38 height: 1080 39 } 40 } 41 // 推荐预览分辨率之一 42 private previewProfileObj: camera.Profile = { 43 format: 1003, 44 size: { 45 width: 1920, 46 height: 1080 47 } 48 } 49 private curSceneMode: camera.SceneMode = camera.SceneMode.NORMAL_PHOTO 50 51 constructor() { 52 } 53 54 setSavePictureCallback(callback: (photoAsset: photoAccessHelper.PhotoAsset) => void): void { 55 this.handlePhotoAssetCb = callback 56 } 57 58 setSceneMode(sceneMode: camera.SceneMode): void { 59 this.curSceneMode = sceneMode 60 } 61 62 getSceneMode(): camera.SceneMode { 63 return this.curSceneMode 64 } 65 66 getPreviewProfile(cameraOutputCapability: camera.CameraOutputCapability): camera.Profile | undefined { 67 let previewProfiles = cameraOutputCapability.previewProfiles 68 if (previewProfiles.length < 1) { 69 return undefined 70 } 71 return previewProfiles[0] 72 } 73 74 getPhotoProfile(cameraOutputCapability: camera.CameraOutputCapability): camera.Profile | undefined { 75 let photoProfiles = cameraOutputCapability.photoProfiles 76 if (photoProfiles.length < 1) { 77 return undefined 78 } 79 return photoProfiles[0] 80 } 81 82 isSupportedSceneMode(cameraManager: camera.CameraManager, cameraDevice: camera.CameraDevice): boolean { 83 let sceneModes = cameraManager.getSupportedSceneModes(cameraDevice) 84 if (sceneModes === undefined) { 85 return false 86 } 87 let index = sceneModes.findIndex((sceneMode: camera.SceneMode) => { 88 return sceneMode === this.curSceneMode 89 }) 90 if (index === -1) { 91 return false 92 } 93 return true 94 } 95 96 //初始化相机功能 97 async initCamera(surfaceId: string, cameraDeviceIndex: number): Promise<void> { 98 try { 99 await this.releaseCamera() 100 this.cameraManager = this.getCameraManagerFn() 101 if (this.cameraManager === undefined) { 102 return 103 } 104 //获取支持指定的相机设备对象 105 this.cameras = this.getSupportedCamerasFn(this.cameraManager) 106 if (this.cameras.length < 1 || this.cameras.length < cameraDeviceIndex + 1) { 107 return 108 } 109 this.curCameraDevice = this.cameras[cameraDeviceIndex] 110 let isSupported = this.isSupportedSceneMode(this.cameraManager, this.curCameraDevice) 111 if (!isSupported) { 112 return 113 } 114 let cameraOutputCapability=this.cameraManager.getSupportedOutputCapability(this.curCameraDevice,this.curSceneMode) 115 let previewProfile = this.getPreviewProfile(cameraOutputCapability) 116 if (previewProfile === undefined) { 117 return 118 } 119 this.previewProfileObj = previewProfile 120 let photoProfile = this.getPhotoProfile(cameraOutputCapability) 121 if (photoProfile === undefined) { 122 return 123 } 124 this.photoProfileObj = photoProfile 125 //创建previewOutput输出对象 126 this.previewOutput = this.createPreviewOutputFn(this.cameraManager, this.previewProfileObj, surfaceId) 127 if (this.previewOutput === undefined) { 128 return 129 } 130 //监听预览事件 131 this.previewOutputCallBack(this.previewOutput) 132 //创建photoOutPut输出对象 133 this.photoOutput = this.createPhotoOutputFn(this.cameraManager, this.photoProfileObj) 134 if (this.photoOutput === undefined) { 135 return 136 } 137 //创建cameraInput输出对象 138 this.cameraInput = this.createCameraInputFn(this.cameraManager, this.curCameraDevice) 139 if (this.cameraInput === undefined) { 140 return 141 } 142 //打开相机 143 let isOpenSuccess = await this.cameraInputOpenFn(this.cameraInput) 144 if (!isOpenSuccess) { 145 return 146 } 147 //镜头状态回调 148 this.onCameraStatusChange(this.cameraManager) 149 //监听CameraInput的错误事件 150 this.onCameraInputChange(this.cameraInput, this.curCameraDevice) 151 //会话流程 152 await this.sessionFlowFn(this.cameraManager, this.cameraInput, this.previewOutput, this.photoOutput) 153 } catch (error) { 154 let err = error as BusinessError 155 } 156 } 157 158 //变焦 159 setZoomRatioFn(zoomRatio: number): void { 160 //获取支持的变焦范围 161 try { 162 let zoomRationRange = this.session?.getZoomRatioRange() 163 } catch (error) { 164 let err = error as BusinessError 165 } 166 try { 167 this.session?.setZoomRatio(zoomRatio) 168 } catch (error) { 169 let err = error as BusinessError 170 } 171 try { 172 let nowZoomRatio = this.session?.getZoomRatio() 173 } catch (error) { 174 let err = error as BusinessError 175 } 176 } 177 178 //拍照 179 async takepicture(): Promise<void> { 180 let photoSettings: camera.PhotoCaptureSetting = { 181 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, 182 mirror: false 183 } 184 await this.photoOutput?.capture(photoSettings) 185 } 186 187 //释放会话及相关参数 188 async releaseCamera(): Promise<void> { 189 if (this.previewOutput) { 190 try { 191 await this.previewOutput.release() 192 } catch (error) { 193 let err = error as BusinessError 194 } finally { 195 this.previewOutput = undefined 196 } 197 } 198 if(this.photoOutput){ 199 try { 200 201 } catch (error) { 202 let err = error as BusinessError; 203 } finally { 204 this.photoOutput = undefined; 205 } 206 } 207 if (this.session) { 208 try { 209 await this.session.release() 210 } catch (error) { 211 let err = error as BusinessError 212 } finally { 213 this.session = undefined 214 } 215 } 216 if (this.cameraInput) { 217 try { 218 await this.cameraInput.close() 219 } catch (error) { 220 let err = error as BusinessError 221 } finally { 222 this.cameraInput = undefined 223 } 224 } 225 this.offCameraStatusChange() 226 } 227 228 //获取相机管理器实例 229 getCameraManagerFn(): camera.CameraManager | undefined { 230 if (this.cameraManager) { 231 return this.cameraManager 232 } 233 let cameraManager: camera.CameraManager | undefined = undefined 234 try { 235 cameraManager = camera.getCameraManager(GlobalContext.get().getCameraSettingContext()) 236 } catch (error) { 237 let err = error as BusinessError 238 } 239 return cameraManager 240 } 241 242 //获取支持指定的相机设备对象 243 getSupportedCamerasFn(cameraManager: camera.CameraManager): Array<camera.CameraDevice> { 244 let supportedCameras: camera.CameraDevice[] = [] 245 try { 246 supportedCameras = cameraManager.getSupportedCameras() 247 } catch (error) { 248 let err = error as BusinessError 249 } 250 return supportedCameras 251 } 252 253 //创建previewOutput输出对象 254 createPreviewOutputFn(cameraManager: camera.CameraManager, previewProfileObj: camera.Profile, surfaceId: string): 255 camera.PreviewOutput | undefined { 256 let previewOutput: camera.PreviewOutput | undefined = undefined 257 try { 258 previewOutput = cameraManager.createPreviewOutput(previewProfileObj, surfaceId) 259 } catch (error) { 260 let err = error as BusinessError 261 } 262 return previewOutput 263 } 264 265 //创建photoOutput输出对象 266 createPhotoOutputFn(cameraManager: camera.CameraManager, photoProfileObj: camera.Profile): 267 camera.PhotoOutput | undefined { 268 let photoOutput: camera.PhotoOutput | undefined = undefined 269 try { 270 photoOutput = cameraManager.createPhotoOutput(photoProfileObj) 271 } catch (error) { 272 let err = error as BusinessError 273 } 274 return photoOutput 275 } 276 277 //创建cameraInput输出对象 278 createCameraInputFn(cameraManager: camera.CameraManager, cameraDevice: camera.CameraDevice): 279 camera.CameraInput | undefined { 280 let cameraInput: camera.CameraInput | undefined = undefined 281 try { 282 cameraInput = cameraManager.createCameraInput(cameraDevice) 283 } catch (error) { 284 let err = error as BusinessError 285 } 286 return cameraInput 287 } 288 289 //打开相机 290 async cameraInputOpenFn(cameraInput: camera.CameraInput): Promise<boolean> { 291 let isOpenSuccess = false 292 try { 293 await cameraInput.open() 294 isOpenSuccess = true 295 } catch (error) { 296 let err = error as BusinessError 297 } 298 return isOpenSuccess 299 } 300 301 /* 会话流程 */ 302 async sessionFlowFn(cameraManger: camera.CameraManager, cameraInput: camera.CameraInput, 303 previewOutput: camera.PreviewOutput, photoOutput: camera.PhotoOutput): Promise<void> { 304 try { 305 // 创建captureSession实例 306 this.session = cameraManger.createSession(this.curSceneMode) as camera.PhotoSession 307 if (this.session === undefined) { 308 return 309 } 310 // 监听拍照会话的错误事件 311 this.onCaptureSessionErrorChange(this.session) 312 // 开始配置会话 313 this.session.beginConfig() 314 // 把CameraInput加入会话 315 this.session.addInput(cameraInput) 316 // 把previewOutput加入会话 317 this.session.addOutput(previewOutput) 318 // 把photoOutput加入会话 319 this.session.addOutput(photoOutput) 320 // 拍照监听事件 321 this.photoOutputCallBack(photoOutput) 322 // 提交配置信息 323 await this.session.commitConfig() 324 // 开始会话工作 325 await this.session.start() 326 } catch (error) { 327 let err = error as BusinessError 328 } 329 } 330 331 // 监听拍照事件 332 photoOutputCallBack(photoOutput: camera.PhotoOutput): void { 333 try { 334 // 监听拍照开始 335 photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo): void => { 336 }) 337 // 监听拍照帧输出捕获 338 photoOutput.on('frameShutter', (err: BusinessError, frameShutterInfo: camera.FrameShutterInfo): void => { 339 }) 340 // 监听拍照结束 341 photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo): void => { 342 }) 343 // 监听拍照异常 344 photoOutput.on('error', (data: BusinessError): void => { 345 }) 346 } catch (err) { 347 } 348 } 349 350 // 监听预览事件 351 previewOutputCallBack(previewOutput: camera.PreviewOutput): void { 352 try { 353 previewOutput.on('frameStart', (): void => { 354 }) 355 previewOutput.on('frameEnd', (): void => { 356 }) 357 previewOutput.on('error', (previewOutputError: BusinessError): void => { 358 }) 359 } catch (err) { 360 } 361 } 362 363 // 注册相机变化的回调函数 364 registerCameraStatusChange(err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) { 365 } 366 367 // 监听相机状态变化 368 onCameraStatusChange(cameraManager: camera.CameraManager): void { 369 try { 370 cameraManager.on('cameraStatus', this.registerCameraStatusChange) 371 } catch (error) { 372 373 } 374 } 375 376 // 停止监听相机状态变化 377 offCameraStatusChange(): void { 378 this.cameraManager?.off('cameraStatus', this.registerCameraStatusChange) 379 } 380 381 // 监听相机输入变化 382 onCameraInputChange(cameraInput: camera.CameraInput, cameraDevice: camera.CameraDevice): void { 383 try { 384 cameraInput.on('error', cameraDevice, (cameraInputError: BusinessError): void => { 385 }) 386 } catch (error) { 387 } 388 } 389 390 // 监听捕获绘画错误变化 391 onCaptureSessionErrorChange(session: camera.PhotoSession): void { 392 try { 393 session.on('error', (captureSessionError: BusinessError): void => { 394 }) 395 } catch (error) { 396 } 397 } 398} 399 400export default new CameraService()