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