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