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 ReportUtil from '../utils/ReportUtil'; 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 ReportUtil.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 ReportUtil.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 ReportUtil.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({ 254 surfaceWidth: size.width, 255 surfaceHeight: size.height 256 }); 257 let previewProfiles = this.outputCapability.previewProfiles; 258 let previewProfile; 259 if (deviceInfo.deviceType == 'default') { 260 previewProfile = previewProfiles[0]; 261 } else { 262 Log.info(`${TAG} previewProfiles length.` + previewProfiles.length); 263 previewProfile = previewProfiles.find(item => item.size.width === size.width && 264 item.size.height === size.height && item.format === 1003); 265 } 266 await this.releasePreviewOutput(); 267 try { 268 this.mPreviewOutput = this.mCameraManager.createPreviewOutput(previewProfile, surfaceId); 269 } catch (error) { 270 Log.error(`${TAG} createPreviewOutput failed: ${JSON.stringify(error)}`); 271 ReportUtil.writeFaultLog(error); 272 } 273 Log.end(`${TAG} createPreviewOutput`); 274 } 275 276 public async releasePreviewOutput() { 277 Log.start(`${TAG} releasePreviewOutput`); 278 if (this.mPreviewOutput) { 279 try { 280 await this.mPreviewOutput.release(); 281 this.mPreviewOutput = null; 282 } catch (error) { 283 Log.error(`${TAG} releasePreviewOutput failed: ${JSON.stringify(error)}`); 284 ReportUtil.writeFaultLog(error); 285 } 286 } 287 Log.end(`${TAG} releasePreviewOutput`); 288 } 289 290 public async createPhotoOutput(functionCallback: FunctionCallBack) { 291 Log.start(`${TAG} createPhotoOutput`); 292 const size = SettingManager.getInstance().getImageSize(); 293 Log.info(`${TAG} createPhotoOutput size.width = ${size.width} size.height = ${size.height}`); 294 this.mImageReceiver = image.createImageReceiver(size.width, size.height, image.ImageFormat.JPEG, 8); 295 const surfaceId = await this.mImageReceiver.getReceivingSurfaceId(); 296 Log.info(`${TAG} createPhotoOutput surfaceId: ${surfaceId}.`); 297 let photoProfiles = this.outputCapability.photoProfiles; 298 let photoProfile; 299 if (deviceInfo.deviceType == 'default') { 300 photoProfile = photoProfiles[0]; 301 } else { 302 Log.info(`${TAG} videoProfiles length.` + photoProfiles.length); 303 photoProfile = photoProfiles.find(item => item.size.width === size.width && item.size.height === size.height); 304 } 305 try { 306 this.mPhotoOutPut = this.mCameraManager.createPhotoOutput(photoProfile, surfaceId); 307 } catch (error) { 308 Log.error(`${TAG} createPhotoOutput failed: ${JSON.stringify(error)}`); 309 ReportUtil.writeFaultLog(error); 310 } 311 Log.info(`${TAG} createPhotoOutput mPhotoOutPut: ${this.mPhotoOutPut}.`); 312 this.mSaveCameraAsset.saveImage(this.mImageReceiver, 40, 40, this.mThumbnailGetter, functionCallback); 313 Log.end(`${TAG} createPhotoOutput`); 314 } 315 316 public async releasePhotoOutput() { 317 Log.start(`${TAG} releasePhotoOutput`); 318 if (this.mPhotoOutPut) { 319 try { 320 await this.mPhotoOutPut.release(); 321 this.mPhotoOutPut = null; 322 } catch (error) { 323 Log.error(`${TAG} releasePhotoOutput failed: ${JSON.stringify(error)}`); 324 ReportUtil.writeFaultLog(error); 325 } 326 } 327 if (this.mImageReceiver) { 328 await this.mImageReceiver.release(); 329 this.mImageReceiver = null; 330 } 331 Log.end(`${TAG} releasePhotoOutput`); 332 } 333 334 public async createSession(surfaceId: string, isVideo: boolean) { 335 Log.start(`${TAG} createSession`); 336 GlobalContext.get().setObject('isSessionCreating', true) 337 this.mCaptureSession = this.mCameraManager.createCaptureSession(); 338 GlobalContext.get().setObject('isSessionCreating', false) 339 Log.info(`${TAG} createSession captureSession: ${this.mCaptureSession}, cameraInput: ${this.mCameraInput}, 340 videoOutPut: ${this.mVideoOutput}, photoOutPut: ${this.mPhotoOutPut}, mPreviewOutput: ${this.mPreviewOutput}`); 341 Log.info(`${TAG} createSession beginConfig.`); 342 Log.start(Log.STREAM_DISTRIBUTION); 343 try { 344 this.mCaptureSession?.beginConfig(); 345 await new Promise((resolve) => setTimeout(resolve, 1)); 346 Log.info(`${TAG} createSession addInput.`); 347 this.mCaptureSession?.addInput(this.mCameraInput); 348 if (!isVideo) { 349 Log.info(`${TAG} createSession photo addOutput.`); 350 this.mCaptureSession?.addOutput(this.mPhotoOutPut); 351 } 352 Log.info(`${TAG} createSession preview addOutput.`); 353 this.mCaptureSession?.addOutput(this.mPreviewOutput); 354 } catch (error) { 355 Log.error(`${TAG} createSession failed: ${JSON.stringify(error)}`); 356 if (error) { 357 ReportUtil.write(ReportUtil.CAMERA_ERROR); 358 } 359 } 360 Log.info(`${TAG} createSession commitConfig.`); 361 Log.start(Log.OPEN_CAMERA); 362 try { 363 await this.mCaptureSession?.commitConfig(); 364 Log.end(Log.OPEN_CAMERA); 365 Log.end(Log.STREAM_DISTRIBUTION); 366 await this.mCaptureSession?.start(); 367 } catch (err) { 368 if (err) { 369 ReportUtil.write(ReportUtil.OPEN_FAIL); 370 } 371 } 372 if (GlobalContext.get().getT<boolean>('cameraStartFlag') && (new Date().getTime() - GlobalContext.get().getT<number>('cameraStartTime')) > 2000) { 373 ReportUtil.write(ReportUtil.START_TIMEOUT); 374 } 375 GlobalContext.get().setObject('cameraStartFlag', false); 376 Log.end(`${TAG} createSession`); 377 } 378 379 public async releaseSession() { 380 Log.start(`${TAG} releaseSession`); 381 if (this.mCaptureSession) { 382 try { 383 await this.mCaptureSession.stop(); 384 await this.mCaptureSession.release(); 385 this.mCaptureSession = null; 386 } catch (error) { 387 Log.error(`${TAG} releaseSession failed: ${JSON.stringify(error)}`); 388 ReportUtil.writeFaultLog(error); 389 } 390 } 391 Log.end(`${TAG} releaseSession`); 392 } 393 394 public async startPreview() { 395 Log.start(`${TAG} startPreview`); 396 if (!this.mCaptureSession) { 397 return; 398 } 399 try { 400 await this.mCaptureSession.start(); 401 } catch (error) { 402 Log.error(`${TAG} startPreview failed: ${JSON.stringify(error)}`); 403 ReportUtil.writeFaultLog(error); 404 } 405 Log.end(`${TAG} startPreview`); 406 } 407 408 public async stopPreview() { 409 Log.start(`${TAG} stopPreview`); 410 if (!this.mCaptureSession) { 411 return; 412 } 413 try { 414 await this.mCaptureSession.stop(); 415 } catch (error) { 416 Log.error(`${TAG} stopPreview failed: ${JSON.stringify(error)}`); 417 ReportUtil.writeFaultLog(error); 418 } 419 Log.end(`${TAG} stopPreview`); 420 } 421 422 public async takePicture() { 423 Log.start(`${TAG} takePicture`); 424 ReportUtil.write(ReportUtil.CAPTURE); 425 if (!this.mCaptureSession) { 426 Log.info(`${TAG} takePicture session is release`); 427 return; 428 } 429 if (!this.mPhotoOutPut) { 430 Log.info(`${TAG} takePicture photoOutPut is release`); 431 return; 432 } 433 if (this.mCameraId === CameraId.FRONT) { 434 this.mCaptureSetting.mirror = SettingManager.getInstance().getSelfMirror(); 435 } 436 const locationData = SettingManager.getInstance().getCurGeoLocation(); 437 if (locationData) { 438 this.mCaptureSetting.location = { 439 latitude: locationData.latitude, 440 longitude: locationData.longitude, 441 altitude: locationData.altitude 442 } 443 } 444 Log.info(`${TAG} takePicture captureSetting ${JSON.stringify(this.mCaptureSetting)}`); 445 // todo modify the location and mirror config 446 try { 447 this.mPhotoOutPut.capture(this.mCaptureSetting); 448 } catch (err) { 449 if (err) { 450 ReportUtil.write(ReportUtil.CAPTURE_FAIL); 451 } 452 } 453 Log.end(`${TAG} takePicture`); 454 if ((new Date().getTime() - GlobalContext.get().getT<number>('startCaptureTime')) > 2000) { 455 ReportUtil.write(ReportUtil.CAPTURE_TIMEOUT); 456 } 457 } 458 459 public async createVideoOutput(functionCallBack: VideoCallBack) { 460 Log.start(`${TAG} createVideoOutput`); 461 this.mFileAssetId = await this.mSaveCameraAsset.createVideoFd(functionCallBack); 462 if (this.mFileAssetId === undefined) { 463 Log.error(`${TAG} createVideoOutput error: mFileAssetId undefined`); 464 functionCallBack.onRecodeError('createVideoOutput error: mFileAssetId undefined'); 465 } 466 this.mVideoConfig.url = `fd://${this.mFileAssetId.toString()}`; 467 await media.createAVRecorder().then((recorder) => { 468 Log.info(`${TAG} createVideoOutput createAVRecorder record: ${recorder}`); 469 this.mAVRecorder = recorder; 470 }); 471 const size = SettingManager.getInstance().getVideoSize(); 472 if (this.mAVRecorder != null) { 473 this.mAVRecorder.on('error', (error) => { 474 if (error) { 475 Log.error(`${TAG} createVideoOutput error: ${JSON.stringify(error)}`); 476 functionCallBack.onRecodeError(`createVideoOutput error: ${JSON.stringify(error)}`); 477 } 478 }); 479 Log.info(`${TAG} createVideoOutput size = ${JSON.stringify(size)}`); 480 this.mVideoConfig.profile.videoFrameWidth = size.width; 481 this.mVideoConfig.profile.videoFrameHeight = size.height; 482 const locationData = SettingManager.getInstance().getCurGeoLocation(); 483 if (locationData) { 484 this.mVideoConfig.location = { 485 latitude: locationData.latitude, 486 longitude: locationData.longitude 487 }; 488 } 489 490 if (deviceInfo.deviceType != 'tablet') { 491 if (this.curCameraName === 'BACK') { 492 this.mVideoConfig.rotation = 90; 493 } else { 494 this.mVideoConfig.rotation = 270; 495 } 496 } 497 Log.info(`${TAG} createVideoOutput mVideoConfig = ${JSON.stringify(this.mVideoConfig)}.`); 498 await this.mAVRecorder.prepare(this.mVideoConfig); 499 Log.info(`${TAG} createVideoOutput AVRecorder.prepare succeed.`); 500 } else { 501 Log.error(`${TAG} createVideoOutput createAVRecorder failed.`); 502 return; 503 } 504 505 let profileVideo; 506 if (deviceInfo.deviceType == 'default') { 507 profileVideo = this.outputCapability.videoProfiles[0]; 508 } else { 509 let videoProfiles = this.outputCapability.videoProfiles; 510 Log.info(`${TAG} videoProfiles length.` + videoProfiles.length); 511 profileVideo = videoProfiles.find(item => 512 item.size.width === size.width && item.size.height === size.height 513 && item.frameRateRange.min === DEFAULT_VIDEO_FRAME_RATE && item.frameRateRange.max === DEFAULT_VIDEO_FRAME_RATE 514 ); 515 } 516 517 const videoId = await this.mAVRecorder.getInputSurface(); 518 Log.info(`${TAG} createVideoOutput profileVideo = ${JSON.stringify(profileVideo)}.`); 519 try { 520 this.mVideoOutput = this.mCameraManager.createVideoOutput(profileVideo, videoId); 521 } catch (error) { 522 Log.error(`${TAG} createVideoOutput failed: ${JSON.stringify(error)}`); 523 ReportUtil.writeFaultLog(error); 524 } 525 Log.end(`${TAG} createVideoOutput`); 526 } 527 528 public async releaseVideoOutput() { 529 Log.start(`${TAG} releaseVideoOutput`); 530 if (this.mVideoOutput) { 531 Log.info(`${TAG} releaseVideoOutput start`); 532 try { 533 await this.mVideoOutput.release(); 534 } catch (error) { 535 Log.error(`${TAG} releaseVideoOutput failed: ${JSON.stringify(error)}`); 536 ReportUtil.writeFaultLog(error); 537 } 538 Log.info(`${TAG} releaseVideoOutput end`); 539 this.mVideoOutput = null; 540 } 541 Log.end(`${TAG} releaseVideoOutput`); 542 } 543 544 public async StartRecording(functionCallBack: VideoCallBack) { 545 let startRecordingTime = new Date().getTime(); 546 Log.start(`${TAG} StartRecording`); 547 Log.info(`${TAG} StartRecording codec ${this.mVideoConfig.profile.videoCodec}`); 548 ReportUtil.write(ReportUtil.VIDEO_RECORD); 549 try { 550 await this.mCaptureSession.stop(); 551 this.mCaptureSession.beginConfig(); 552 if (this.mVideoOutput) { 553 await this.mCaptureSession.removeOutput(this.mVideoOutput); 554 Log.info(`${TAG} old videoOutput has been removed.`); 555 } 556 await this.createVideoOutput(functionCallBack); 557 this.mCaptureSession.addOutput(this.mVideoOutput); 558 Log.info(`${TAG} StartRecording addOutput finished.`); 559 await this.mCaptureSession.commitConfig(); 560 Log.info(`${TAG} StartRecording commitConfig finished.`); 561 await this.mCaptureSession.start(); 562 Log.info(`${TAG} StartRecording Session.start finished.`); 563 } catch (err) { 564 GlobalContext.get().setObject('startRecordingFlag', false); 565 ReportUtil.writeFaultLog(error); 566 Log.error(`${TAG} remove videoOutput ${err}`); 567 } 568 await this.mVideoOutput.start().then(() => { 569 Log.info(`${TAG} videoOutput.start()`); 570 }); 571 await this.mAVRecorder.start().then(() => { 572 Log.info(`${TAG} AVRecorder.start()`); 573 }); 574 this.mIsStartRecording = true; 575 if (new Date().getTime() - startRecordingTime > 2000) { 576 ReportUtil.write(ReportUtil.START_RECORD_TIMEOUT); 577 } 578 Log.end(`${TAG} StartRecording`); 579 } 580 581 public async stopRecording(): Promise<PixelMap | undefined> { 582 Log.start(Log.STOP_RECORDING); 583 let stopRecordingTime = new Date().getTime(); 584 ReportUtil.write(ReportUtil.STOP_RECORD); 585 if (!this.mVideoOutput || !this.mAVRecorder) { 586 Log.error(`${TAG} stopRecording error videoOutPut: ${this.mVideoOutput}, 587 AVRecorder: ${this.mAVRecorder} .`); 588 return undefined; 589 } 590 this.mIsStartRecording = false; 591 try { 592 await this.mAVRecorder.stop(); 593 await this.mAVRecorder.release(); 594 } catch (err) { 595 Log.error(`${TAG} stop AVRecorder ${err}`); 596 } 597 598 try { 599 await this.mVideoOutput.stop(); 600 } catch (err) { 601 Log.error(`${TAG} stop videoOutput ${err}`); 602 } 603 604 if (this.mFileAssetId != undefined) { 605 await this.mSaveCameraAsset.videoPrepareFile.close(this.mFileAssetId); 606 this.mFileAssetId = undefined; 607 Log.info(`${TAG} fileAsset.close().`); 608 } 609 Log.start(Log.UPDATE_VIDEO_THUMBNAIL); 610 const thumbnailPixelMap: PixelMap | undefined = await this.mThumbnailGetter.getThumbnailInfo(40, 40); 611 Log.end(Log.UPDATE_VIDEO_THUMBNAIL); 612 if (new Date().getTime() - stopRecordingTime > 2000) { 613 ReportUtil.write(ReportUtil.FINISH_RECORD_TIMEOUT); 614 } 615 Log.end(Log.STOP_RECORDING); 616 return thumbnailPixelMap; 617 } 618 619 public async pauseRecording() { 620 Log.start(`${TAG} pauseRecording`); 621 if (!this.mVideoOutput || !this.mAVRecorder) { 622 Log.error(`${TAG} pauseRecording error videoOutPut: ${this.mVideoOutput}, 623 AVRecorder: ${this.mAVRecorder} .`); 624 return; 625 } 626 try { 627 await this.mAVRecorder.pause(); 628 await this.mVideoOutput.stop(); 629 } catch (error) { 630 Log.error(`${TAG} pauseRecording failed: ${JSON.stringify(error)}`); 631 } 632 Log.end(`${TAG} pauseRecording`); 633 } 634 635 public async resumeRecording() { 636 Log.start(`${TAG} resumeRecording`); 637 if (!this.mVideoOutput || !this.mAVRecorder) { 638 Log.error(`${TAG} resumeRecording error videoOutPut: ${this.mVideoOutput}, 639 AVRecorder: ${this.mAVRecorder} .`); 640 return; 641 } 642 await this.mVideoOutput.start().then(() => { 643 Log.info(`${TAG} videoOutput.start()`); 644 }).catch((error) => { 645 Log.error(`${TAG} resumeRecording mVideoOutput start failed: ${JSON.stringify(error)}`); 646 }); 647 await this.mAVRecorder.resume(); 648 Log.end(`${TAG} resumeRecording`); 649 } 650 651 public async releaseRecording() { 652 Log.start(`${TAG} releaseRecording`); 653 if (!this.mAVRecorder) { 654 Log.info(`${TAG} AVRecorder has not been created.`); 655 return; 656 } 657 if (this.mIsStartRecording) { 658 await this.stopRecording(); 659 } 660 await this.mAVRecorder.release().then(() => { 661 Log.info(`${TAG} AVRecorder.release() success.`); 662 this.mAVRecorder = undefined; 663 }); 664 Log.end(`${TAG} releaseRecording`); 665 } 666 667 public async releaseCamera() { 668 Log.start(`${TAG} releaseCamera`); 669 await this.releaseRecording(); 670 await this.releaseVideoOutput(); 671 await this.releasePhotoOutput(); 672 await this.releaseSession(); 673 Log.end(`${TAG} releaseCamera`); 674 } 675 676 public async setZoomRatio(zoomRatio: number) { 677 Log.info(`${TAG} setZoomRatio invoke E ${zoomRatio}`); 678 if (!this.mCaptureSession) { 679 Log.info(`${TAG} setZoomRatio mCaptureSession is release`); 680 return; 681 } 682 try { 683 this.mCaptureSession.setZoomRatio(zoomRatio); 684 } catch (error) { 685 Log.error(`${TAG} setZoomRatio failed: ${JSON.stringify(error)}`); 686 } 687 Log.info(`${TAG} setZoomRatio invoke X.`); 688 } 689 690 public async getZoomRatio(): Promise<number> { 691 Log.info(`${TAG} getZoomRatio invoke E.`); 692 if (!this.mCaptureSession) { 693 Log.info(`${TAG} getZoomRatio mCaptureSession is release`); 694 return 1; 695 } 696 Log.info(`${TAG} getZoomRatio invoke X.`); 697 return this.mCaptureSession.getZoomRatio(); 698 } 699 700 public async setVideoConfig(videoConfig: any) { 701 Log.info(`${TAG} setVideoConfig invoke E.`); 702 if (videoConfig) { 703 this.mVideoConfig = videoConfig; 704 } else { 705 Log.info(`${TAG} setVideoConfig videoConfig is null.`); 706 } 707 Log.info(`${TAG} setVideoConfig invoke X.`); 708 } 709 710 public async setCaptureSetting(captureSetting: any) { 711 Log.info(`${TAG} setCaptureSetting invoke E.`); 712 if (captureSetting) { 713 this.mCaptureSetting = captureSetting; 714 } else { 715 Log.info(`${TAG} setCaptureSetting captureSetting is null.`); 716 } 717 Log.info(`${TAG} setCaptureSetting invoke X.`); 718 } 719 720 public getThumbnail(functionCallBack: FunctionCallBack): image.PixelMap { 721 Log.start(`${TAG} getThumbnail`); 722 this.mThumbnailGetter.getThumbnailInfo(40, 40).then((thumbnail) => { 723 functionCallBack.thumbnail(thumbnail); 724 Log.end(`${TAG} getThumbnail`); 725 }); 726 return this.mThumbnail; 727 } 728 729 public getCameraName(): string { 730 return this.curCameraName; 731 } 732 733 public setCameraId(name: string): void { 734 this.curCameraName = name; 735 } 736 737 public getPhotoUri() { 738 return this.mSaveCameraAsset.getPhotoUri(); 739 } 740 741 public getRecentFileUri(): string { 742 return this.mThumbnailGetter.getRecentFileUri(); 743 } 744 745 private async getCameraLists() { 746 const cameras = this.mCameraManager.getSupportedCameras(); 747 this.camerasCache = cameras; 748 return cameras; 749 } 750}