1/* 2 * Copyright (c) 2023-2024 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 { Action } from '../redux/actions/Action'; 17import { CameraId } from '../setting/settingitem/CameraId'; 18import { CameraPlatformCapability } from '../camera/CameraPlatformCapability'; 19import { Log } from '../utils/Log'; 20import { CameraStatus } from '../utils/Constants'; 21import { BaseFunction } from './BaseFunction'; 22import { FunctionCallBack } from '../camera/CameraService'; 23import ReportUtil from '../utils/ReportUtil'; 24import { GlobalContext } from '../utils/GlobalContext'; 25 26export class CameraBasicFunction extends BaseFunction { 27 public startIdentification: boolean = false 28 private TAG = '[CameraBasicFunction]:'; 29 private mCameraId: string = CameraId.BACK; 30 private mSurfaceId: string = ''; 31 private mCurrentMode: string = ''; 32 private mSessionList: string[] = []; 33 private isSessionReleasing: boolean = false 34 private initDataCache: any = null 35 36 static getInstance() { 37 if (!globalThis?.cameraBasicMethod) { 38 globalThis.cameraBasicMethod = new CameraBasicFunction() 39 } 40 return globalThis.cameraBasicMethod 41 } 42 43 public async initCamera(data, callType?: string) { 44 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_BEGIN_INIT); 45 Log.info(`${this.TAG} initCamera this.startIdentification:${JSON.stringify(this.startIdentification)} `); 46 if (this.startIdentification) { 47 const platformCapability = CameraPlatformCapability.getInstance(); 48 this.mWorkerManager.postMessage(Action.initCameraDone(platformCapability)); 49 return; 50 } 51 if (callType) { 52 this.startIdentification = true 53 } 54 Log.start(`${this.TAG} initCamera`) 55 this.mSessionList.push('CREATE') 56 let curStorageCameraId = AppStorage.Get<string>('storageCameraId') 57 if (curStorageCameraId) { 58 data.cameraId = curStorageCameraId 59 } 60 Log.info(`${this.TAG} initData:${JSON.stringify(data)} `) 61 this.initDataCache = data 62 if (GlobalContext.get().getT<boolean>('isSessionCreating') || this.isSessionReleasing) { 63 Log.info(`${this.TAG} initCamera isSessionCreating or isSessionReleasing return`) 64 return 65 } 66 this.mCameraId = data.cameraId 67 this.mCurrentMode = data.mode 68 let mCameraCount = await this.mCameraService.initCamera(this.mCameraId) 69 const platformCapability = CameraPlatformCapability.getInstance() 70 await platformCapability.init(mCameraCount) 71 this.mWorkerManager.postMessage(Action.initCameraDone(platformCapability)) 72 this.mCameraService.getThumbnail(this.functionBackImpl) 73 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_INIT_FINISHED); 74 this.mWorkerManager.postMessage(Action.updateCameraStatus()) 75 Log.end(`${this.TAG} initCamera`) 76 } 77 78 load(): void { 79 Log.info(`${this.TAG} load E`) 80 this.mEventBus.on(Action.ACTION_INIT, this.initCamera.bind(this)) 81 this.mEventBus.on(Action.ACTION_CHANGE_IMAGE_SIZE, this.imageSize.bind(this)) 82 this.mEventBus.on(Action.ACTION_CHANGE_VIDEO_SIZE, this.videoSize.bind(this)) 83 this.mEventBus.on(Action.ACTION_PREPARE_SURFACE, this.onSurfacePrepare.bind(this)) 84 this.mEventBus.on(Action.ACTION_START_PREVIEW, this.startPreview.bind(this)) 85 this.mEventBus.on(Action.ACTION_RESTART_PREVIEW, this.reStartPreview.bind(this)) 86 this.mEventBus.on(Action.ACTION_CHANGE_MODE, this.changeMode.bind(this)) 87 this.mEventBus.on(Action.ACTION_SWITCH_CAMERA, this.switchCamera.bind(this)) 88 this.mEventBus.on(Action.ACTION_CLOSE_CAMERA, this.close.bind(this)) 89 this.mEventBus.on(Action.ACTION_RELOAD_THUMBNAIL, this.reloadThumbnail.bind(this)) 90 Log.info(`${this.TAG} load X`) 91 } 92 93 unload(): void { 94 Log.info(`${this.TAG} unload E`) 95 this.mEventBus.off(Action.ACTION_INIT, this.initCamera.bind(this)) 96 this.mEventBus.off(Action.ACTION_CHANGE_IMAGE_SIZE, this.imageSize.bind(this)) 97 this.mEventBus.off(Action.ACTION_CHANGE_VIDEO_SIZE, this.videoSize.bind(this)) 98 this.mEventBus.off(Action.ACTION_PREPARE_SURFACE, this.onSurfacePrepare.bind(this)) 99 this.mEventBus.off(Action.ACTION_START_PREVIEW, this.startPreview.bind(this)) 100 this.mEventBus.off(Action.ACTION_RESTART_PREVIEW, this.reStartPreview.bind(this)) 101 this.mEventBus.off(Action.ACTION_CHANGE_MODE, this.changeMode.bind(this)) 102 this.mEventBus.off(Action.ACTION_SWITCH_CAMERA, this.switchCamera.bind(this)) 103 this.mEventBus.off(Action.ACTION_CLOSE_CAMERA, this.close.bind(this)) 104 this.mEventBus.off(Action.ACTION_RELOAD_THUMBNAIL, this.reloadThumbnail.bind(this)) 105 Log.info(`${this.TAG} unload X`) 106 } 107 108 private functionBackImpl: FunctionCallBack = { 109 onCapturePhotoOutput: (): void => { 110 Log.info(`${this.TAG} functionBackImpl onCapturePhotoOutput`) 111 this.mWorkerManager.postMessage(Action.capturePhotoOutput()) 112 }, 113 onCaptureSuccess: (thumbnail: any, resourceUri: any): void => { 114 Log.info(`${this.TAG} functionBackImpl onCaptureSuccess ${thumbnail}`) 115 this.mWorkerManager.postMessage(Action.updateThumbnail(thumbnail, resourceUri)) 116 }, 117 onCaptureFailure: (): void => { 118 Log.info(`${this.TAG} functionBackImpl onCaptureFailure`) 119 this.mWorkerManager.postMessage(Action.captureError()) 120 }, 121 onRecordSuccess: (thumbnail: any): void => { 122 Log.info(`${this.TAG} functionBackImpl onRecordSuccess ${thumbnail}`) 123 this.mWorkerManager.postMessage(Action.recordDone(thumbnail)) 124 }, 125 onRecordFailure: (): void => { 126 Log.info(`${this.TAG} functionBackImpl onRecordFailure`) 127 this.mWorkerManager.postMessage(Action.recordError()) 128 }, 129 thumbnail: (thumbnail: any): void => { 130 Log.info(`${this.TAG} functionBackImpl thumbnail ${thumbnail}`) 131 this.mWorkerManager.postMessage(Action.loadThumbnail(thumbnail)) 132 } 133 } 134 135 private async imageSize(data) { 136 Log.info(`${this.TAG} imageSize ${JSON.stringify(data)} E`) 137 this.mCameraService.mImageSize.imageWidth = data.imageSize.width 138 this.mCameraService.mImageSize.imageHeight = data.imageSize.height 139 Log.info(`${this.TAG} imageSize X`) 140 } 141 142 private async videoSize(data) { 143 Log.info(`${this.TAG} videoSize ${JSON.stringify(data)} E`) 144 this.mCameraService.mVideoFrameSize.frameWidth = data.videoSize.width 145 this.mCameraService.mVideoFrameSize.frameHeight = data.videoSize.height 146 Log.info(`${this.TAG} videoSize X`) 147 } 148 149 private async onSurfacePrepare(data) { 150 Log.info(`${this.TAG} onSurfacePrepare ${JSON.stringify(data)} E`) 151 this.mSurfaceId = data.surfaceId 152 Log.info(`${this.TAG} onSurfacePrepare X`) 153 } 154 155 private async startPreview(data?) { 156 Log.start(`${this.TAG} startPreview`) 157 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_BEGIN_PREVIEW); 158 if (!this.mSurfaceId) { 159 Log.info(`${this.TAG} startPreview error mSurfaceId is null`) 160 this.enableUi() 161 return 162 } 163 await this.mCameraService.createPreviewOutput(this.mSurfaceId, this.mCurrentMode) 164 if (await this.isVideoMode()) { 165 // await this.mCameraService.createVideoOutput(this.functionBackImpl) 166 } else { 167 await this.mCameraService.createPhotoOutput(this.functionBackImpl) 168 } 169 await this.mCameraService.createSession(this.mSurfaceId, await this.isVideoMode()) 170 if ([...this.mSessionList].pop() === 'RELEASE') { 171 await this.close() 172 } 173 if (data && data?.zoomRatio && data.zoomRatio !== 1) { 174 await this.mCameraService.setZoomRatio(data.zoomRatio) 175 } 176 this.mSessionList = [] 177 this.enableUi() 178 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_PREVIEW_FINISHED); 179 this.mWorkerManager.postMessage(Action.updateCameraStatus()) 180 Log.end(`${this.TAG} startPreview`) 181 } 182 183 private async reStartPreview(data) { 184 Log.start(`${this.TAG} reStartPreview`) 185 if (!this.mSurfaceId) { 186 Log.info(`${this.TAG} reStartPreview error mSurfaceId is null`) 187 this.enableUi() 188 return 189 } 190 this.mCameraService.setCameraId(this.mCameraId) 191 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_RELEASING); 192 await this.mCameraService.releaseCamera() 193 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_RELEASE_FINISHED); 194 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_BEGIN_PREVIEW); 195 await this.mCameraService.createCameraInput(this.mCameraId) 196 await this.mCameraService.createPreviewOutput(this.mSurfaceId, this.mCurrentMode) 197 if (await this.isVideoMode()) { 198 // await this.mCameraService.createVideoOutput(this.functionBackImpl) 199 } else { 200 await this.mCameraService.createPhotoOutput(this.functionBackImpl) 201 } 202 await this.mCameraService.createSession(this.mSurfaceId, await this.isVideoMode()) 203 if ([...this.mSessionList].pop() === 'RELEASE') { 204 await this.close() 205 } 206 if (data && data?.zoomRatio && data.zoomRatio !== 1) { 207 await this.mCameraService.setZoomRatio(data.zoomRatio) 208 } 209 this.mSessionList = [] 210 this.enableUi() 211 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_PREVIEW_FINISHED); 212 this.mWorkerManager.postMessage(Action.updateCameraStatus()) 213 Log.end(`${this.TAG} reStartPreview`) 214 } 215 216 private async changeMode(data) { 217 Log.start(`${this.TAG} changeMode`) 218 ReportUtil.write(ReportUtil.SWITCH_MODE) 219 this.mCurrentMode = data.mode 220 this.mCameraId = this.mCameraId.split('_').pop() as string; 221 Log.info(`${this.TAG} this.mCurrentMode = ${this.mCurrentMode}`) 222 await this.mCameraService.releaseCamera() 223 await this.mCameraService.createCameraInput(this.mCameraId, 'modeChange') 224 await this.mCameraService.createPreviewOutput(this.mSurfaceId, this.mCurrentMode) 225 if (await this.isVideoMode()) { 226 // await this.mCameraService.createVideoOutput(this.functionBackImpl) 227 } else { 228 await this.mCameraService.createPhotoOutput(this.functionBackImpl) 229 } 230 await this.mCameraService.createSession(this.mSurfaceId, await this.isVideoMode()) 231 this.mWorkerManager.postMessage(Action.onModeChanged(this.mCurrentMode)) 232 this.mWorkerManager.postMessage(Action.swipeModeChangeDone(false)) 233 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_PREVIEW_FINISHED); 234 this.mWorkerManager.postMessage(Action.updateCameraStatus()) 235 this.enableUi() 236 Log.end(`${this.TAG} changeMode`) 237 } 238 239 private async switchCamera(data) { 240 Log.start(`${this.TAG} switchCamera`) 241 ReportUtil.write(ReportUtil.SWITCH_CAMERA) 242 this.mCameraId = data.cameraId 243 this.mCameraService.setCameraId(this.mCameraId) 244 await this.mCameraService.releaseCamera() 245 await this.mCameraService.createCameraInput(this.mCameraId) 246 if (data?.curMode && data.curMode !== undefined && data.curMode !== this.mCurrentMode) { 247 this.mCurrentMode = data.curMode 248 } 249 await this.mCameraService.createPreviewOutput(this.mSurfaceId, this.mCurrentMode) 250 if (await this.isVideoMode()) { 251 // await this.mCameraService.createVideoOutput(this.functionBackImpl) 252 } else { 253 await this.mCameraService.createPhotoOutput(this.functionBackImpl) 254 } 255 await this.mCameraService.createSession(this.mSurfaceId, await this.isVideoMode()) 256 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_PREVIEW_FINISHED); 257 this.mWorkerManager.postMessage(Action.updateCameraStatus()) 258 if (new Date().getTime() - GlobalContext.get().getT<number>('switchCameraTime') > 2000) { 259 ReportUtil.write(ReportUtil.SWITCH_TIMEOUT) 260 } 261 this.enableUi() 262 Log.end(`${this.TAG} switchCamera`) 263 } 264 265 private async close() { 266 Log.start(`${this.TAG} close`) 267 this.mSessionList.push('RELEASE') 268 if (GlobalContext.get().getT<boolean>('isSessionCreating') || this.isSessionReleasing) { 269 Log.info(`${this.TAG} isSessionCreating or isSessionReleasing return`) 270 return 271 } 272 this.isSessionReleasing = true 273 await this.mCameraService.releaseCamera() 274 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_RELEASE_FINISHED); 275 this.mWorkerManager.postMessage(Action.updateCameraStatus()) 276 this.startIdentification = false 277 this.isSessionReleasing = false 278 if ([...this.mSessionList].pop() === 'CREATE') { 279 await this.initCamera(this.initDataCache) 280 GlobalContext.get().setObject('cameraStatus', CameraStatus.CAMERA_INIT_FINISHED); 281 this.mWorkerManager.postMessage(Action.updateCameraStatus()) 282 } 283 this.mSessionList = [] 284 Log.end(`${this.TAG} close`) 285 } 286 287 private async isVideoMode(): Promise<boolean> { 288 Log.info(`${this.TAG} isVideoMode ${this.mCurrentMode} ${this.mCurrentMode === 'VIDEO'}`) 289 return this.mCurrentMode === 'VIDEO' 290 } 291 292 private async reloadThumbnail(data) { 293 Log.info(`${this.TAG} loadThumbnail E`) 294 this.mCameraService.getThumbnail(this.functionBackImpl) 295 Log.info(`${this.TAG} loadThumbnail X`) 296 } 297}