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 console.info('www data succeed' + 111) 102 if (this.cameraManager === undefined) { 103 return 104 } 105 //获取支持指定的相机设备对象 106 this.cameras = this.getSupportedCamerasFn(this.cameraManager) 107 if (this.cameras.length < 1 || this.cameras.length < cameraDeviceIndex + 1) { 108 return 109 } 110 console.info('www data 2') 111 this.curCameraDevice = this.cameras[cameraDeviceIndex] 112 let isSupported = this.isSupportedSceneMode(this.cameraManager, this.curCameraDevice) 113 if (!isSupported) { 114 return 115 } 116 console.info('www data 3') 117 let cameraOutputCapability=this.cameraManager.getSupportedOutputCapability(this.curCameraDevice,this.curSceneMode) 118 let previewProfile = this.getPreviewProfile(cameraOutputCapability) 119 if (previewProfile === undefined) { 120 return 121 } 122 console.info('www data 4') 123 this.previewProfileObj = previewProfile 124 let photoProfile = this.getPhotoProfile(cameraOutputCapability) 125 if (photoProfile === undefined) { 126 return 127 } 128 console.info('www data 5') 129 this.photoProfileObj = photoProfile 130 //创建previewOutput输出对象 131 this.previewOutput = this.createPreviewOutputFn(this.cameraManager, this.previewProfileObj, surfaceId) 132 if (this.previewOutput === undefined) { 133 return 134 } 135 console.info('www data 6') 136 //监听预览事件 137 this.previewOutputCallBack(this.previewOutput) 138 //创建photoOutPut输出对象 139 this.photoOutput = this.createPhotoOutputFn(this.cameraManager, this.photoProfileObj) 140 if (this.photoOutput === undefined) { 141 return 142 } 143 console.info('www data 7') 144 //创建cameraInput输出对象 145 this.cameraInput = this.createCameraInputFn(this.cameraManager, this.curCameraDevice) 146 if (this.cameraInput === undefined) { 147 return 148 } 149 console.info('www data 8') 150 //打开相机 151 let isOpenSuccess = await this.cameraInputOpenFn(this.cameraInput) 152 if (!isOpenSuccess) { 153 return 154 } 155 console.info('www data 9') 156 //镜头状态回调 157 this.onCameraStatusChange(this.cameraManager) 158 //监听CameraInput的错误事件 159 this.onCameraInputChange(this.cameraInput, this.curCameraDevice) 160 console.info('www data 9.5') 161 //会话流程 162 await this.sessionFlowFn(this.cameraManager, this.cameraInput, this.previewOutput, this.photoOutput) 163 console.info('www data 10') 164 } catch (error) { 165 console.info('www data3' + error) 166 console.info('www data3' + error.message) 167 let err = error as BusinessError 168 } 169 } 170 171 //变焦 172 setZoomRatioFn(zoomRatio: number): void { 173 //获取支持的变焦范围 174 try { 175 let zoomRationRange = this.session?.getZoomRatioRange() 176 } catch (error) { 177 let err = error as BusinessError 178 } 179 try { 180 this.session?.setZoomRatio(zoomRatio) 181 } catch (error) { 182 let err = error as BusinessError 183 } 184 try { 185 let nowZoomRatio = this.session?.getZoomRatio() 186 } catch (error) { 187 let err = error as BusinessError 188 } 189 } 190 191 //拍照 192 async takepicture(): Promise<void> { 193 let photoSettings: camera.PhotoCaptureSetting = { 194 quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, 195 mirror: false 196 } 197 await this.photoOutput?.capture(photoSettings) 198 } 199 200 //释放会话及相关参数 201 async releaseCamera(): Promise<void> { 202 if (this.previewOutput) { 203 try { 204 await this.previewOutput.release() 205 } catch (error) { 206 let err = error as BusinessError 207 } finally { 208 this.previewOutput = undefined 209 } 210 } 211 if(this.photoOutput){ 212 try { 213 214 } catch (error) { 215 let err = error as BusinessError; 216 } finally { 217 this.photoOutput = undefined; 218 } 219 } 220 if (this.session) { 221 try { 222 await this.session.release() 223 } catch (error) { 224 let err = error as BusinessError 225 } finally { 226 this.session = undefined 227 } 228 } 229 if (this.cameraInput) { 230 try { 231 await this.cameraInput.close() 232 } catch (error) { 233 let err = error as BusinessError 234 } finally { 235 this.cameraInput = undefined 236 } 237 } 238 this.offCameraStatusChange() 239 } 240 241 //获取相机管理器实例 242 getCameraManagerFn(): camera.CameraManager | undefined { 243 if (this.cameraManager) { 244 return this.cameraManager 245 } 246 let cameraManager: camera.CameraManager | undefined = undefined 247 try { 248 cameraManager = camera.getCameraManager(GlobalContext.get().getCameraSettingContext()) 249 } catch (error) { 250 let err = error as BusinessError 251 } 252 return cameraManager 253 } 254 255 //获取支持指定的相机设备对象 256 getSupportedCamerasFn(cameraManager: camera.CameraManager): Array<camera.CameraDevice> { 257 let supportedCameras: camera.CameraDevice[] = [] 258 try { 259 supportedCameras = cameraManager.getSupportedCameras() 260 } catch (error) { 261 let err = error as BusinessError 262 } 263 return supportedCameras 264 } 265 266 //创建previewOutput输出对象 267 createPreviewOutputFn(cameraManager: camera.CameraManager, previewProfileObj: camera.Profile, surfaceId: string): 268 camera.PreviewOutput | undefined { 269 let previewOutput: camera.PreviewOutput | undefined = undefined 270 try { 271 previewOutput = cameraManager.createPreviewOutput(previewProfileObj, surfaceId) 272 } catch (error) { 273 let err = error as BusinessError 274 } 275 return previewOutput 276 } 277 278 //创建photoOutput输出对象 279 createPhotoOutputFn(cameraManager: camera.CameraManager, photoProfileObj: camera.Profile): 280 camera.PhotoOutput | undefined { 281 let photoOutput: camera.PhotoOutput | undefined = undefined 282 try { 283 photoOutput = cameraManager.createPhotoOutput(photoProfileObj) 284 } catch (error) { 285 let err = error as BusinessError 286 } 287 return photoOutput 288 } 289 290 //创建cameraInput输出对象 291 createCameraInputFn(cameraManager: camera.CameraManager, cameraDevice: camera.CameraDevice): 292 camera.CameraInput | undefined { 293 let cameraInput: camera.CameraInput | undefined = undefined 294 try { 295 cameraInput = cameraManager.createCameraInput(cameraDevice) 296 } catch (error) { 297 let err = error as BusinessError 298 } 299 return cameraInput 300 } 301 302 //打开相机 303 async cameraInputOpenFn(cameraInput: camera.CameraInput): Promise<boolean> { 304 let isOpenSuccess = false 305 try { 306 await cameraInput.open() 307 isOpenSuccess = true 308 } catch (error) { 309 let err = error as BusinessError 310 } 311 return isOpenSuccess 312 } 313 314 /* 会话流程 */ 315 async sessionFlowFn(cameraManger: camera.CameraManager, cameraInput: camera.CameraInput, 316 previewOutput: camera.PreviewOutput, photoOutput: camera.PhotoOutput): Promise<void> { 317 try { 318 // 创建captureSession实例 319 this.session = cameraManger.createSession(this.curSceneMode) as camera.PhotoSession 320 if (this.session === undefined) { 321 return 322 } 323 // 监听拍照会话的错误事件 324 this.onCaptureSessionErrorChange(this.session) 325 // 开始配置会话 326 this.session.beginConfig() 327 // 把CameraInput加入会话 328 this.session.addInput(cameraInput) 329 // 把previewOutput加入会话 330 this.session.addOutput(previewOutput) 331 // 把photoOutput加入会话 332 this.session.addOutput(photoOutput) 333 // 拍照监听事件 334 this.photoOutputCallBack(photoOutput) 335 // 提交配置信息 336 await this.session.commitConfig() 337 // 开始会话工作 338 await this.session.start() 339 } catch (error) { 340 let err = error as BusinessError 341 } 342 } 343 344 // 监听拍照事件 345 photoOutputCallBack(photoOutput: camera.PhotoOutput): void { 346 try { 347 // 监听拍照开始 348 photoOutput.on('captureStartWithInfo', (err: BusinessError, captureStartInfo: camera.CaptureStartInfo): void => { 349 }) 350 // 监听拍照帧输出捕获 351 photoOutput.on('frameShutter', (err: BusinessError, frameShutterInfo: camera.FrameShutterInfo): void => { 352 }) 353 // 监听拍照结束 354 photoOutput.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo): void => { 355 }) 356 // 监听拍照异常 357 photoOutput.on('error', (data: BusinessError): void => { 358 }) 359 } catch (err) { 360 } 361 } 362 363 // 监听预览事件 364 previewOutputCallBack(previewOutput: camera.PreviewOutput): void { 365 try { 366 previewOutput.on('frameStart', (): void => { 367 }) 368 previewOutput.on('frameEnd', (): void => { 369 }) 370 previewOutput.on('error', (previewOutputError: BusinessError): void => { 371 }) 372 } catch (err) { 373 } 374 } 375 376 // 注册相机变化的回调函数 377 registerCameraStatusChange(err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo) { 378 } 379 380 // 监听相机状态变化 381 onCameraStatusChange(cameraManager: camera.CameraManager): void { 382 try { 383 cameraManager.on('cameraStatus', this.registerCameraStatusChange) 384 } catch (error) { 385 386 } 387 } 388 389 // 停止监听相机状态变化 390 offCameraStatusChange(): void { 391 this.cameraManager?.off('cameraStatus', this.registerCameraStatusChange) 392 } 393 394 // 监听相机输入变化 395 onCameraInputChange(cameraInput: camera.CameraInput, cameraDevice: camera.CameraDevice): void { 396 try { 397 cameraInput.on('error', cameraDevice, (cameraInputError: BusinessError): void => { 398 }) 399 } catch (error) { 400 } 401 } 402 403 // 监听捕获绘画错误变化 404 onCaptureSessionErrorChange(session: camera.PhotoSession): void { 405 try { 406 session.on('error', (captureSessionError: BusinessError): void => { 407 }) 408 } catch (error) { 409 } 410 } 411} 412 413export default new CameraService()