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