1//@ts-nocheck 2/* 3 * Copyright (c) 2023 Huawei Device Co., Ltd. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17import camera from '@ohos.multimedia.camera'; 18import image from '@ohos.multimedia.image'; 19import media from '@ohos.multimedia.media'; 20import deviceInfo from '@ohos.deviceInfo'; 21 22import { CameraId } from '../setting/settingitem/CameraId'; 23import { Log } from '../utils/Log'; 24import ThumbnailGetter from './ThumbnailGetter'; 25import SaveCameraAsset from './SaveCameraAsset'; 26import { SettingManager } from '../setting/SettingManager'; 27import { CameraPlatformCapability } from './CameraPlatformCapability'; 28import EventLog from '../utils/EventLog'; 29import { GlobalContext } from '../utils/GlobalContext'; 30 31const TAG = '[CameraService]:'; 32 33const DEFAULT_VIDEO_FRAME_RATE = 30; 34const FRONT_CAMERA_POSITION = 2; 35const CAMERA_CONNECT_TYPE = 2; 36 37export interface FunctionCallBack { 38 onCapturePhotoOutput(): void 39 40 onCaptureSuccess(thumbnail: any, resourceUri: any): void 41 42 onCaptureFailure(): void 43 44 onRecordSuccess(thumbnail: any): void 45 46 onRecordFailure(): void 47 48 thumbnail(thumbnail: any): void 49} 50 51export interface VideoCallBack { 52 videoUri(videoUri: any): void 53 54 onRecodeError(errorMsg: any): void 55} 56 57type Callback = (args?: any) => void 58 59class CameraInformation { 60 deviceName: string; 61 cameraId: string; 62} 63 64export class CameraService { 65 public mImageSize = { 66 imageWidth: 1920, 67 imageHeight: 1080 68 } 69 public mVideoFrameSize = { 70 frameWidth: 1920, 71 frameHeight: 1080 72 } 73 private mCameraId: string = CameraId.BACK; 74 private mFileAssetId = 0; 75 private mCameraManager!: camera.CameraManager; 76 private mCameraIdMap: Map<string, string> = new Map(); 77 private mLocalCameraMap: Map<string, string> = new Map(); 78 private mCameraMap: Map<string, CameraInformation> = new Map(); 79 private curCameraName = ''; 80 private mCameraCount = 0; 81 private mCameraInput!: camera.CameraInput; 82 private mCaptureSession!: camera.CaptureSession; 83 private mPreviewOutput!: camera.PreviewOutput; 84 private mPhotoOutPut!: camera.PhotoOutput; 85 private mImageReceiver!: image.ImageReceiver; 86 private mVideoOutput!: camera.VideoOutput; 87 private mAVRecorder!: media.AVRecorder; 88 private mThumbnail!: image.PixelMap; 89 private mIsStartRecording = false; 90 private mSaveCameraAsset = new SaveCameraAsset(); 91 private mThumbnailGetter = new ThumbnailGetter(); 92 private camerasCache: any = null; 93 private outputCapability: camera.CameraOutputCapability = null; 94 private mVideoConfig: any = { 95 audioSourceType: 1, 96 videoSourceType: 1, 97 profile: { 98 audioBitrate: 48000, 99 audioChannels: 2, 100 audioCodec: 'audio/mp4a-latm', 101 audioSampleRate: 48000, 102 durationTime: 1000, 103 fileFormat: 'mp4', 104 videoBitrate: 5000000, 105 videoCodec: 'video/avc', 106 videoFrameWidth: 640, 107 videoFrameHeight: 480, 108 videoFrameRate: 30 109 }, 110 url: 'file:///data/media/01.mp4', 111 orientationHint: 0, 112 maxSize: 100, 113 maxDuration: 500, 114 rotation: 0 115 } 116 private mCaptureSetting: any = { 117 rotation: 0, 118 quality: 1, 119 mirror: false 120 } 121 122 private constructor() { 123 } 124 125 public static getInstance(): CameraService { 126 if (!globalThis?.sInstanceCameraService) { 127 globalThis.sInstanceCameraService = new CameraService(); 128 } 129 return globalThis.sInstanceCameraService; 130 } 131 132 public async initCamera(cameraId: string): Promise<number> { 133 Log.start(`${TAG} initCamera`); 134 if (!this.mCameraManager) { 135 try { 136 this.mCameraManager = camera.getCameraManager(GlobalContext.get().getCameraAbilityContext()); 137 const cameras = this.mCameraManager.getSupportedCameras(); 138 this.camerasCache = cameras; 139 this.mCameraCount = cameras.length; 140 if (cameras) { 141 Log.info(`${TAG} getCameras success.`); 142 for (let i = 0; i < cameras.length; i++) { 143 Log.info(`${TAG} camera_id: ${cameras[i].cameraId} cameraPosition: ${cameras[i].cameraPosition} 144 cameraType: ${cameras[i].cameraType} connectionType: ${cameras[i].connectionType}`); 145 if (cameras[i].cameraPosition === FRONT_CAMERA_POSITION && cameras[i].connectionType !== CAMERA_CONNECT_TYPE) { 146 this.mLocalCameraMap.set('front', 'true'); 147 } 148 if (cameras[i].cameraPosition !== FRONT_CAMERA_POSITION && cameras[i].connectionType !== CAMERA_CONNECT_TYPE) { 149 this.mLocalCameraMap.set('back', 'true'); 150 } 151 } 152 // TODO 根据底层信息匹配cameraId 目前默认第0个是back, 第1个是front 153 this.mCameraIdMap.set(CameraId.BACK, cameras[0].cameraId); 154 if (cameras.length > 1 && cameras[1].connectionType !== 2) { 155 this.mCameraIdMap.set(CameraId.FRONT, cameras[1].cameraId); 156 } else { 157 this.mCameraIdMap.set(CameraId.FRONT, cameras[0].cameraId); 158 } 159 } 160 } catch (error) { 161 Log.error(`${TAG} initCamera failed: ${JSON.stringify(error)}`); 162 EventLog.writeFaultLog(error); 163 } 164 } 165 this.curCameraName = cameraId; 166 await this.createCameraInput(cameraId, 'init'); 167 168 Log.info(`${TAG} deviceType = ${deviceInfo.deviceType}`); 169 if (deviceInfo.deviceType == 'default') { 170 this.mVideoConfig.videoSourceType = 1; 171 } else { 172 this.mVideoConfig.videoSourceType = 0; 173 } 174 Log.end(`${TAG} initCamera`); 175 return this.mCameraCount; 176 } 177 178 public getCameraManager(): camera.CameraManager { 179 return this.mCameraManager; 180 } 181 182 public getCameraIdMap(): Map<string, string> { 183 return this.mCameraIdMap; 184 } 185 186 public getLocalCameraMap(): Map<string, string> { 187 return this.mLocalCameraMap; 188 } 189 190 public getCameraMap(): Map<string, CameraInformation> { 191 return this.mCameraMap; 192 } 193 194 public getCameraCount(): number { 195 return this.mCameraCount; 196 } 197 198 public async createCameraInput(cameraName: string, callType?: string) { 199 Log.start(`${TAG} createCameraInput`); 200 this.mCameraId = cameraName; 201 this.curCameraName = cameraName; 202 if (callType === 'modeChange' || callType === 'init') { 203 let targetCamera = this.camerasCache.filter(item => item.connectionType !== 2); 204 if (targetCamera && targetCamera.length <= 1 && cameraName === 'BACK') { 205 this.curCameraName = 'FRONT'; 206 this.mCameraId = 'FRONT'; 207 } 208 } 209 if (this.mCameraInput) { 210 await this.mCameraInput.release(); 211 } 212 let id; 213 if (cameraName == CameraId.FRONT || cameraName == CameraId.BACK) { 214 id = this.mCameraIdMap.get(cameraName); 215 } else { 216 id = this.mCameraMap.get(cameraName).cameraId; 217 } 218 Log.info(`${TAG} createCameraInput id = ${id}`); 219 try { 220 let cameras = await this.getCameraLists(); 221 let targetCamera = cameras.find(item => item.cameraId === id); 222 this.outputCapability = this.mCameraManager.getSupportedOutputCapability(targetCamera); 223 this.mCameraInput = this.mCameraManager.createCameraInput(targetCamera); 224 await this.mCameraInput.open(); 225 const platformCapability = CameraPlatformCapability.getInstance(); 226 await platformCapability.calcSupportedSizes(this.mCameraInput, this.outputCapability); 227 SettingManager.getInstance().setCameraPlatformCapability(platformCapability); 228 } catch (error) { 229 Log.error(`${TAG} createCameraInput failed: ${JSON.stringify(error)}`); 230 EventLog.writeFaultLog(error); 231 } 232 Log.end(`${TAG} createCameraInput`); 233 } 234 235 public async releaseCameraInput() { 236 Log.start(`${TAG} releaseCameraInput`); 237 if (this.mCameraInput) { 238 try { 239 await this.mCameraInput.release(); 240 } catch (error) { 241 Log.error(`${TAG} releaseCameraInput failed: ${JSON.stringify(error)}`); 242 EventLog.writeFaultLog(error); 243 } 244 this.mCameraInput = null; 245 } 246 Log.end(`${TAG} releaseCameraInput`); 247 } 248 249 public async createPreviewOutput(surfaceId: string, mode: string) { 250 Log.start(`${TAG} createPreviewOutput`); 251 const size = SettingManager.getInstance().getPreviewSize(mode); 252 Log.info(`${TAG} createPreviewOutput size.width = ${size.width} size.height = ${size.height}`); 253 GlobalContext.get().getXComponentController().setXComponentSurfaceSize({ surfaceWidth: size.width, surfaceHeight: size.height }); 254 let previewProfiles = this.outputCapability.previewProfiles; 255 let previewProfile; 256 if (deviceInfo.deviceType == 'default') { 257 previewProfile = previewProfiles[0]; 258 } else { 259 Log.info(`${TAG} previewProfiles length.` + previewProfiles.length); 260 previewProfile = previewProfiles.find(item => item.size.width === size.width && 261 item.size.height === size.height && item.format === 1003); 262 } 263 await this.releasePreviewOutput(); 264 try { 265 this.mPreviewOutput = this.mCameraManager.createPreviewOutput(previewProfile, surfaceId); 266 } catch (error) { 267 Log.error(`${TAG} createPreviewOutput failed: ${JSON.stringify(error)}`); 268 EventLog.writeFaultLog(error); 269 } 270 Log.end(`${TAG} createPreviewOutput`); 271 } 272 273 public async releasePreviewOutput() { 274 Log.start(`${TAG} releasePreviewOutput`); 275 if (this.mPreviewOutput) { 276 try { 277 await this.mPreviewOutput.release(); 278 this.mPreviewOutput = null; 279 } catch (error) { 280 Log.error(`${TAG} releasePreviewOutput failed: ${JSON.stringify(error)}`); 281 EventLog.writeFaultLog(error); 282 } 283 } 284 Log.end(`${TAG} releasePreviewOutput`); 285 } 286 287 public async createPhotoOutput(functionCallback: FunctionCallBack) { 288 Log.start(`${TAG} createPhotoOutput`); 289 const size = SettingManager.getInstance().getImageSize(); 290 Log.info(`${TAG} createPhotoOutput size.width = ${size.width} size.height = ${size.height}`); 291 this.mImageReceiver = image.createImageReceiver(size.width, size.height, image.ImageFormat.JPEG, 8); 292 const surfaceId = await this.mImageReceiver.getReceivingSurfaceId(); 293 Log.info(`${TAG} createPhotoOutput surfaceId: ${surfaceId}.`); 294 let photoProfiles = this.outputCapability.photoProfiles; 295 let photoProfile; 296 if (deviceInfo.deviceType == 'default') { 297 photoProfile = photoProfiles[0]; 298 } else { 299 Log.info(`${TAG} videoProfiles length.` + photoProfiles.length); 300 photoProfile = photoProfiles.find(item => item.size.width === size.width && item.size.height === size.height); 301 } 302 try { 303 this.mPhotoOutPut = this.mCameraManager.createPhotoOutput(photoProfile, surfaceId); 304 } catch (error) { 305 Log.error(`${TAG} createPhotoOutput failed: ${JSON.stringify(error)}`); 306 EventLog.writeFaultLog(error); 307 } 308 Log.info(`${TAG} createPhotoOutput mPhotoOutPut: ${this.mPhotoOutPut}.`); 309 this.mSaveCameraAsset.saveImage(this.mImageReceiver, 40, 40, this.mThumbnailGetter, functionCallback); 310 Log.end(`${TAG} createPhotoOutput`); 311 } 312 313 public async releasePhotoOutput() { 314 Log.start(`${TAG} releasePhotoOutput`); 315 if (this.mPhotoOutPut) { 316 try { 317 await this.mPhotoOutPut.release(); 318 this.mPhotoOutPut = null; 319 } catch (error) { 320 Log.error(`${TAG} releasePhotoOutput failed: ${JSON.stringify(error)}`); 321 EventLog.writeFaultLog(error); 322 } 323 } 324 if (this.mImageReceiver) { 325 await this.mImageReceiver.release(); 326 this.mImageReceiver = null; 327 } 328 Log.end(`${TAG} releasePhotoOutput`); 329 } 330 331 public async createSession(surfaceId: string, isVideo: boolean) { 332 Log.start(`${TAG} createSession`); 333 GlobalContext.get().setObject('isSessionCreating', true) 334 this.mCaptureSession = this.mCameraManager.createCaptureSession(); 335 GlobalContext.get().setObject('isSessionCreating', false) 336 Log.info(`${TAG} createSession captureSession: ${this.mCaptureSession}, cameraInput: ${this.mCameraInput}, 337 videoOutPut: ${this.mVideoOutput}, photoOutPut: ${this.mPhotoOutPut}, mPreviewOutput: ${this.mPreviewOutput}`); 338 Log.info(`${TAG} createSession beginConfig.`); 339 Log.start(Log.STREAM_DISTRIBUTION); 340 try { 341 this.mCaptureSession?.beginConfig(); 342 await new Promise((resolve) => setTimeout(resolve, 1)); 343 Log.info(`${TAG} createSession addInput.`); 344 this.mCaptureSession?.addInput(this.mCameraInput); 345 if (!isVideo) { 346 Log.info(`${TAG} createSession photo addOutput.`); 347 this.mCaptureSession?.addOutput(this.mPhotoOutPut); 348 } 349 Log.info(`${TAG} createSession preview addOutput.`); 350 this.mCaptureSession?.addOutput(this.mPreviewOutput); 351 } catch (error) { 352 Log.error(`${TAG} createSession failed: ${JSON.stringify(error)}`); 353 if (error) { 354 EventLog.write(EventLog.CAMERA_ERROR); 355 } 356 } 357 Log.info(`${TAG} createSession commitConfig.`); 358 Log.start(Log.OPEN_CAMERA); 359 try { 360 await this.mCaptureSession?.commitConfig(); 361 Log.end(Log.OPEN_CAMERA); 362 Log.end(Log.STREAM_DISTRIBUTION); 363 await this.mCaptureSession?.start(); 364 } catch (err) { 365 if (err) { 366 EventLog.write(EventLog.OPEN_FAIL); 367 } 368 } 369 if (GlobalContext.get().getT<boolean>('cameraStartFlag') && (new Date().getTime() - GlobalContext.get().getT<number>('cameraStartTime')) > 2000) { 370 EventLog.write(EventLog.START_TIMEOUT); 371 } 372 GlobalContext.get().setObject('cameraStartFlag', false); 373 Log.end(`${TAG} createSession`); 374 } 375 376 public async releaseSession() { 377 Log.start(`${TAG} releaseSession`); 378 if (this.mCaptureSession) { 379 try { 380 await this.mCaptureSession.stop(); 381 await this.mCaptureSession.release(); 382 this.mCaptureSession = null; 383 } catch (error) { 384 Log.error(`${TAG} releaseSession failed: ${JSON.stringify(error)}`); 385 EventLog.writeFaultLog(error); 386 } 387 } 388 Log.end(`${TAG} releaseSession`); 389 } 390 391 public async startPreview() { 392 Log.start(`${TAG} startPreview`); 393 if (!this.mCaptureSession) { 394 return; 395 } 396 try { 397 await this.mCaptureSession.start(); 398 } catch (error) { 399 Log.error(`${TAG} startPreview failed: ${JSON.stringify(error)}`); 400 EventLog.writeFaultLog(error); 401 } 402 Log.end(`${TAG} startPreview`); 403 } 404 405 public async stopPreview() { 406 Log.start(`${TAG} stopPreview`); 407 if (!this.mCaptureSession) { 408 return; 409 } 410 try { 411 await this.mCaptureSession.stop(); 412 } catch (error) { 413 Log.error(`${TAG} stopPreview failed: ${JSON.stringify(error)}`); 414 EventLog.writeFaultLog(error); 415 } 416 Log.end(`${TAG} stopPreview`); 417 } 418 419 public async takePicture() { 420 Log.start(`${TAG} takePicture`); 421 EventLog.write(EventLog.CAPTURE); 422 if (!this.mCaptureSession) { 423 Log.info(`${TAG} takePicture session is release`); 424 return; 425 } 426 if (!this.mPhotoOutPut) { 427 Log.info(`${TAG} takePicture photoOutPut is release`); 428 return; 429 } 430 if (this.mCameraId === CameraId.FRONT) { 431 this.mCaptureSetting.mirror = SettingManager.getInstance().getSelfMirror(); 432 } 433 const locationData = SettingManager.getInstance().getCurGeoLocation(); 434 if (locationData) { 435 this.mCaptureSetting.location = { 436 latitude: locationData.latitude, 437 longitude: locationData.longitude, 438 altitude: locationData.altitude 439 } 440 } 441 Log.info(`${TAG} takePicture captureSetting ${JSON.stringify(this.mCaptureSetting)}`); 442 // todo modify the location and mirror config 443 try { 444 this.mPhotoOutPut.capture(this.mCaptureSetting); 445 } catch (err) { 446 if (err) { 447 EventLog.write(EventLog.CAPTURE_FAIL); 448 } 449 } 450 Log.end(`${TAG} takePicture`); 451 if ((new Date().getTime() - GlobalContext.get().getT<number>('startCaptureTime')) > 2000) { 452 EventLog.write(EventLog.CAPTURE_TIMEOUT); 453 } 454 } 455 456 public async createVideoOutput(functionCallBack: VideoCallBack) { 457 Log.start(`${TAG} createVideoOutput`); 458 this.mFileAssetId = await this.mSaveCameraAsset.createVideoFd(functionCallBack); 459 if (this.mFileAssetId === undefined) { 460 Log.error(`${TAG} createVideoOutput error: mFileAssetId undefined`); 461 functionCallBack.onRecodeError('createVideoOutput error: mFileAssetId undefined'); 462 } 463 this.mVideoConfig.url = `fd://${this.mFileAssetId.toString()}`; 464 await media.createAVRecorder().then((recorder) => { 465 Log.info(`${TAG} createVideoOutput createAVRecorder record: ${recorder}`); 466 this.mAVRecorder = recorder; 467 }); 468 const size = SettingManager.getInstance().getVideoSize(); 469 if (this.mAVRecorder != null) { 470 this.mAVRecorder.on('error', (error) => { 471 if (error) { 472 Log.error(`${TAG} createVideoOutput error: ${JSON.stringify(error)}`); 473 functionCallBack.onRecodeError(`createVideoOutput error: ${JSON.stringify(error)}`); 474 } 475 }); 476 Log.info(`${TAG} createVideoOutput size = ${JSON.stringify(size)}`); 477 this.mVideoConfig.profile.videoFrameWidth = size.width; 478 this.mVideoConfig.profile.videoFrameHeight = size.height; 479 const locationData = SettingManager.getInstance().getCurGeoLocation(); 480 if (locationData) { 481 this.mVideoConfig.location = { 482 latitude: locationData.latitude, 483 longitude: locationData.longitude 484 }; 485 } 486 487 if (deviceInfo.deviceType != 'tablet') { 488 if (this.curCameraName === 'BACK') { 489 this.mVideoConfig.rotation = 90; 490 } else { 491 this.mVideoConfig.rotation = 270; 492 } 493 } 494 Log.info(`${TAG} createVideoOutput mVideoConfig = ${JSON.stringify(this.mVideoConfig)}.`); 495 await this.mAVRecorder.prepare(this.mVideoConfig); 496 Log.info(`${TAG} createVideoOutput AVRecorder.prepare succeed.`); 497 } else { 498 Log.error(`${TAG} createVideoOutput createAVRecorder failed.`); 499 return; 500 } 501 502 let profileVideo; 503 if (deviceInfo.deviceType == 'default') { 504 profileVideo = this.outputCapability.videoProfiles[0]; 505 } else { 506 let videoProfiles = this.outputCapability.videoProfiles; 507 Log.info(`${TAG} videoProfiles length.` + videoProfiles.length); 508 profileVideo = videoProfiles.find(item => 509 item.size.width === size.width && item.size.height === size.height 510 && item.frameRateRange.min === DEFAULT_VIDEO_FRAME_RATE && item.frameRateRange.max === DEFAULT_VIDEO_FRAME_RATE 511 ); 512 } 513 514 const videoId = await this.mAVRecorder.getInputSurface(); 515 Log.info(`${TAG} createVideoOutput profileVideo = ${JSON.stringify(profileVideo)}.`); 516 try { 517 this.mVideoOutput = this.mCameraManager.createVideoOutput(profileVideo, videoId); 518 } catch (error) { 519 Log.error(`${TAG} createVideoOutput failed: ${JSON.stringify(error)}`); 520 EventLog.writeFaultLog(error); 521 } 522 Log.end(`${TAG} createVideoOutput`); 523 } 524 525 public async releaseVideoOutput() { 526 Log.start(`${TAG} releaseVideoOutput`); 527 if (this.mVideoOutput) { 528 Log.info(`${TAG} releaseVideoOutput start`); 529 try { 530 await this.mVideoOutput.release(); 531 } catch (error) { 532 Log.error(`${TAG} releaseVideoOutput failed: ${JSON.stringify(error)}`); 533 EventLog.writeFaultLog(error); 534 } 535 Log.info(`${TAG} releaseVideoOutput end`); 536 this.mVideoOutput = null; 537 } 538 Log.end(`${TAG} releaseVideoOutput`); 539 } 540 541 public async StartRecording(functionCallBack: VideoCallBack) { 542 let startRecordingTime = new Date().getTime(); 543 Log.start(`${TAG} StartRecording`); 544 Log.info(`${TAG} StartRecording codec ${this.mVideoConfig.profile.videoCodec}`); 545 EventLog.write(EventLog.VIDEO_RECORD); 546 try { 547 await this.mCaptureSession.stop(); 548 this.mCaptureSession.beginConfig(); 549 if (this.mVideoOutput) { 550 await this.mCaptureSession.removeOutput(this.mVideoOutput); 551 Log.info(`${TAG} old videoOutput has been removed.`); 552 } 553 await this.createVideoOutput(functionCallBack); 554 this.mCaptureSession.addOutput(this.mVideoOutput); 555 Log.info(`${TAG} StartRecording addOutput finished.`); 556 await this.mCaptureSession.commitConfig(); 557 Log.info(`${TAG} StartRecording commitConfig finished.`); 558 await this.mCaptureSession.start(); 559 Log.info(`${TAG} StartRecording Session.start finished.`); 560 } catch (err) { 561 GlobalContext.get().setObject('startRecordingFlag', false); 562 EventLog.writeFaultLog(error); 563 Log.error(`${TAG} remove videoOutput ${err}`); 564 } 565 await this.mVideoOutput.start().then(() => { 566 Log.info(`${TAG} videoOutput.start()`); 567 }); 568 await this.mAVRecorder.start().then(() => { 569 Log.info(`${TAG} AVRecorder.start()`); 570 }); 571 this.mIsStartRecording = true; 572 if (new Date().getTime() - startRecordingTime > 2000) { 573 EventLog.write(EventLog.START_RECORD_TIMEOUT); 574 } 575 Log.end(`${TAG} StartRecording`); 576 } 577 578 public async stopRecording(): Promise<PixelMap | undefined> { 579 Log.start(Log.STOP_RECORDING); 580 let stopRecordingTime = new Date().getTime(); 581 EventLog.write(EventLog.STOP_RECORD); 582 if (!this.mVideoOutput || !this.mAVRecorder) { 583 Log.error(`${TAG} stopRecording error videoOutPut: ${this.mVideoOutput}, 584 AVRecorder: ${this.mAVRecorder} .`); 585 return undefined; 586 } 587 this.mIsStartRecording = false; 588 try { 589 await this.mAVRecorder.stop(); 590 await this.mAVRecorder.release(); 591 } catch (err) { 592 Log.error(`${TAG} stop AVRecorder ${err}`); 593 } 594 595 try { 596 await this.mVideoOutput.stop(); 597 } catch (err) { 598 Log.error(`${TAG} stop videoOutput ${err}`); 599 } 600 601 if (this.mFileAssetId != undefined) { 602 await this.mSaveCameraAsset.videoPrepareFile.close(this.mFileAssetId); 603 this.mFileAssetId = undefined; 604 Log.info(`${TAG} fileAsset.close().`); 605 } 606 Log.start(Log.UPDATE_VIDEO_THUMBNAIL); 607 const thumbnailPixelMap: PixelMap | undefined = await this.mThumbnailGetter.getThumbnailInfo(40, 40); 608 Log.end(Log.UPDATE_VIDEO_THUMBNAIL); 609 if (new Date().getTime() - stopRecordingTime > 2000) { 610 EventLog.write(EventLog.FINISH_RECORD_TIMEOUT); 611 } 612 Log.end(Log.STOP_RECORDING); 613 return thumbnailPixelMap; 614 } 615 616 public async pauseRecording() { 617 Log.start(`${TAG} pauseRecording`); 618 if (!this.mVideoOutput || !this.mAVRecorder) { 619 Log.error(`${TAG} pauseRecording error videoOutPut: ${this.mVideoOutput}, 620 AVRecorder: ${this.mAVRecorder} .`); 621 return; 622 } 623 try { 624 await this.mAVRecorder.pause(); 625 await this.mVideoOutput.stop(); 626 } catch (error) { 627 Log.error(`${TAG} pauseRecording failed: ${JSON.stringify(error)}`); 628 } 629 Log.end(`${TAG} pauseRecording`); 630 } 631 632 public async resumeRecording() { 633 Log.start(`${TAG} resumeRecording`); 634 if (!this.mVideoOutput || !this.mAVRecorder) { 635 Log.error(`${TAG} resumeRecording error videoOutPut: ${this.mVideoOutput}, 636 AVRecorder: ${this.mAVRecorder} .`); 637 return; 638 } 639 await this.mVideoOutput.start().then(() => { 640 Log.info(`${TAG} videoOutput.start()`); 641 }).catch((error) => { 642 Log.error(`${TAG} resumeRecording mVideoOutput start failed: ${JSON.stringify(error)}`); 643 }); 644 await this.mAVRecorder.resume(); 645 Log.end(`${TAG} resumeRecording`); 646 } 647 648 public async releaseRecording() { 649 Log.start(`${TAG} releaseRecording`); 650 if (!this.mAVRecorder) { 651 Log.info(`${TAG} AVRecorder has not been created.`); 652 return; 653 } 654 if (this.mIsStartRecording) { 655 await this.stopRecording(); 656 } 657 await this.mAVRecorder.release().then(() => { 658 Log.info(`${TAG} AVRecorder.release() success.`); 659 this.mAVRecorder = undefined; 660 }); 661 Log.end(`${TAG} releaseRecording`); 662 } 663 664 public async releaseCamera() { 665 Log.start(`${TAG} releaseCamera`); 666 await this.releaseRecording(); 667 await this.releaseVideoOutput(); 668 await this.releasePhotoOutput(); 669 await this.releaseSession(); 670 Log.end(`${TAG} releaseCamera`); 671 } 672 673 public async setZoomRatio(zoomRatio: number) { 674 Log.info(`${TAG} setZoomRatio invoke E ${zoomRatio}`); 675 if (!this.mCaptureSession) { 676 Log.info(`${TAG} setZoomRatio mCaptureSession is release`); 677 return; 678 } 679 try { 680 this.mCaptureSession.setZoomRatio(zoomRatio); 681 } catch (error) { 682 Log.error(`${TAG} setZoomRatio failed: ${JSON.stringify(error)}`); 683 } 684 Log.info(`${TAG} setZoomRatio invoke X.`); 685 } 686 687 public async getZoomRatio(): Promise<number> { 688 Log.info(`${TAG} getZoomRatio invoke E.`); 689 if (!this.mCaptureSession) { 690 Log.info(`${TAG} getZoomRatio mCaptureSession is release`); 691 return 1; 692 } 693 Log.info(`${TAG} getZoomRatio invoke X.`); 694 return this.mCaptureSession.getZoomRatio(); 695 } 696 697 public async setVideoConfig(videoConfig: any) { 698 Log.info(`${TAG} setVideoConfig invoke E.`); 699 if (videoConfig) { 700 this.mVideoConfig = videoConfig; 701 } else { 702 Log.info(`${TAG} setVideoConfig videoConfig is null.`); 703 } 704 Log.info(`${TAG} setVideoConfig invoke X.`); 705 } 706 707 public async setCaptureSetting(captureSetting: any) { 708 Log.info(`${TAG} setCaptureSetting invoke E.`); 709 if (captureSetting) { 710 this.mCaptureSetting = captureSetting; 711 } else { 712 Log.info(`${TAG} setCaptureSetting captureSetting is null.`); 713 } 714 Log.debug(`${TAG} setCaptureSetting invoke X.`); 715 } 716 717 public getThumbnail(functionCallBack: FunctionCallBack): image.PixelMap { 718 Log.start(`${TAG} getThumbnail`); 719 this.mThumbnailGetter.getThumbnailInfo(40, 40).then((thumbnail) => { 720 functionCallBack.thumbnail(thumbnail); 721 Log.end(`${TAG} getThumbnail`); 722 }); 723 return this.mThumbnail; 724 } 725 726 public getCameraName(): string { 727 return this.curCameraName; 728 } 729 730 public setCameraId(name: string): void { 731 this.curCameraName = name; 732 } 733 734 public getPhotoUri() { 735 return this.mSaveCameraAsset.getPhotoUri(); 736 } 737 738 public getRecentFileUri(): string { 739 return this.mThumbnailGetter.getRecentFileUri(); 740 } 741 742 private async getCameraLists() { 743 const cameras = this.mCameraManager.getSupportedCameras(); 744 this.camerasCache = cameras; 745 return cameras; 746 } 747}