• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 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// @ts-nocheck
16import camera from '@ohos.multimedia.camera';
17import image from '@ohos.multimedia.image';
18import media from '@ohos.multimedia.media';
19import { BusinessError } from '@ohos.base';
20import Logger from '../model/Logger';
21import { Constants } from '../common/Constants';
22import photoAccessHelper from '@ohos.file.photoAccessHelper';
23import fs from '@ohos.file.fs';
24import { GlobalContext } from '../common/GlobalContext';
25import type { CameraConfig } from '../common/CameraConfig';
26import colorSpaceManager from '@ohos.graphics.colorSpaceManager';
27
28const cameraSize = {
29  width: 1280,
30  height: 720
31};
32
33enum PhotoOrientation {
34  ORIENTATION_0 = 0,
35  ORIENTATION_1,
36  ORIENTATION_2,
37  ORIENTATION_3
38}
39
40enum CaptureMode {
41  OLD_CAPTURE = 0,
42  NEW_CAPTURE,
43  NEW_DEFERRED_PHOTO
44}
45
46enum CameraMode {
47  NORMAL = 0,
48  VIDEO,
49  PORTRAIT,
50  SUPER_STAB,
51  NIGHT
52}
53
54function mockInterface(): void {
55  if (!camera.SceneFeatureType) {
56    camera.SceneFeatureType = { MOON_CAPTURE_BOOST: 0 };
57  }
58  if (!camera.SceneMode) {
59    camera.SceneMode = {
60      NORMAL_PHOTO: 1,
61      NORMAL_VIDEO: 2,
62      PORTRAIT_PHOTO: 3,
63      NIGHT_PHOTO: 4
64    };
65  }
66}
67
68const TAG: string = 'CameraService';
69
70class CameraService {
71  private captureMode: CaptureMode = CaptureMode.OLD_CAPTURE;
72  private cameraManager: camera.CameraManager | undefined = undefined;
73  private cameras: Array<camera.CameraDevice> | undefined = undefined;
74  private sceneModes: Array<camera.SceneMode> | undefined = undefined;
75  private cameraOutputCapability: camera.CameraOutputCapability | undefined = undefined;
76  private cameraInput: camera.CameraInput | undefined = undefined;
77  private previewOutput: camera.PreviewOutput | undefined = undefined;
78  private photoOutPut: camera.PhotoOutput | undefined = undefined;
79  private photoSession: camera.PhotoSession | undefined = undefined;
80  private videoSession: camera.VideoSession | undefined = undefined;
81  private portraitSession: camera.PortraitPhotoSession | undefined = undefined;
82  private nightSession: camera.NightPhotoSession | undefined = undefined;
83  private mReceiver: image.ImageReceiver | undefined = undefined;
84  private fileAsset: photoAccessHelper.PhotoAsset | undefined = undefined;
85  private fd: number = -1;
86  private videoRecorder: media.AVRecorder | undefined = undefined;
87  private videoOutput: camera.VideoOutput | undefined = undefined;
88  private handleTakePicture: (photoUri: string) => void | undefined = undefined;
89  private videoConfig: media.AVRecorderConfig = {
90    audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC,
91    videoSourceType: media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV,
92    profile: {
93      audioBitrate: 48000,
94      audioChannels: 2,
95      audioCodec: media.CodecMimeType.AUDIO_AAC,
96      audioSampleRate: 48000,
97      fileFormat: media.ContainerFormatType.CFT_MPEG_4,
98      videoBitrate: 512000,
99      videoCodec: media.CodecMimeType.VIDEO_AVC,
100      videoFrameWidth: 640,
101      videoFrameHeight: 480,
102      videoFrameRate: Constants.VIDEO_FRAME_30
103    },
104    url: '',
105    rotation: 270
106  };
107  private videoProfiles: Array<camera.VideoProfile>;
108  private videoProfileObj: camera.VideoProfile = {
109    format: 1003,
110    size: {
111      width: 1920,
112      height: 1080
113    },
114    frameRateRange: {
115      min: Constants.VIDEO_FRAME_30,
116      max: Constants.VIDEO_FRAME_30
117    }
118  };
119  private defaultProfile: camera.Profile = {
120    format: 1003,
121    size: {
122      width: 1920,
123      height: 1080
124    }
125  };
126  private photoProfileObj: camera.Profile = {
127    format: 1003,
128    size: {
129      width: 1920,
130      height: 1080
131    }
132  };
133  private previewProfileObj: camera.Profile = {
134    format: 1003,
135    size: {
136      width: 1920,
137      height: 1080
138    }
139  };
140  private photoRotationMap = {
141    rotation0: 0,
142    rotation90: 90,
143    rotation180: 180,
144    rotation270: 270,
145  };
146  private videoOutputStatus: boolean = false;
147  private colorEffect: camera.ColorEffectType | undefined = undefined;
148  private cameraMode: number = 0;
149  private accessHelper: photoAccessHelper.PhotoAccessHelper;
150  private globalContext: GlobalContext = GlobalContext.get();
151  private isFirstRecord = true;
152  private isMoonCaptureBoostSupported: Boolean = false;
153  private depthDataOutput: camera.DepthDataOutput | undefined = undefined;
154  private depthProfiles: Array<camera.DepthProfile>;
155  private depthProfileObj: camera.Profile;
156
157  constructor() {
158    mockInterface();
159    this.accessHelper = photoAccessHelper.getPhotoAccessHelper(this.globalContext.getCameraSettingContext());
160    // image capacity
161    let imageCapacity = 8;
162    try {
163      this.mReceiver = image.createImageReceiver(cameraSize.width, cameraSize.height, image.ImageFormat.JPEG, imageCapacity);
164      Logger.debug(TAG, `createImageReceiver value: ${this.mReceiver}`);
165      // debug版本可能监听进不来
166      this.mReceiver.on('imageArrival', (): void => {
167        Logger.debug(TAG, 'imageArrival start');
168        this.mReceiver.readNextImage((errCode: BusinessError, imageObj: image.Image): void => {
169          Logger.info(TAG, 'readNextImage start');
170          Logger.info(TAG, `err: ${JSON.stringify(errCode)}`);
171          if (errCode || imageObj === undefined) {
172            Logger.error(TAG, 'readNextImage failed');
173            return;
174          }
175          imageObj.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => {
176            Logger.debug(TAG, 'getComponent start');
177            Logger.info(TAG, `err: ${JSON.stringify(errCode)}`);
178            if (errCode || component === undefined) {
179              Logger.info(TAG, 'getComponent failed');
180              return;
181            }
182            let buffer: ArrayBuffer;
183            if (component.byteBuffer) {
184              buffer = component.byteBuffer;
185            } else {
186              Logger.error(TAG, 'component byteBuffer is undefined');
187            }
188            this.savePicture(buffer, imageObj);
189          });
190        });
191      });
192    } catch (error) {
193      let err = error as BusinessError;
194      Logger.error(TAG, `savePicture err: ${JSON.stringify(err)}`);
195    }
196  }
197
198  /**
199   * 读取图像
200   */
201  async savePicture(buffer: ArrayBuffer, img: image.Image): Promise<void> {
202    try {
203      Logger.info(TAG, 'savePicture start');
204      let fileName = `${Date.now()}.jpg`;
205      let fileAsset = await this.accessHelper.createAsset(fileName);
206      let imgPhotoUri: string = fileAsset.uri;
207      const fd = await fileAsset.open('rw');
208      await fs.write(fd, buffer);
209      await fileAsset.close(fd);
210      await img.release();
211      Logger.info(TAG, 'savePicture End');
212      if (this.handleTakePicture) {
213        this.handleTakePicture(imgPhotoUri);
214      }
215    } catch (error) {
216      let err = error as BusinessError;
217      Logger.error(TAG, `savePicture err: ${JSON.stringify(err)}`);
218    }
219  }
220
221  /**
222   * 判断两浮点数是否相等
223   */
224  withinErrorMargin(left: number, right: number): boolean {
225    // 底数
226    let baseNumber = 2;
227    // 指数
228    let indexNumber = 2;
229    return Math.abs(left - right) < Number.EPSILON * Math.pow(baseNumber, indexNumber);
230  }
231
232  switchProfiles(profiles: camera.CameraOutputCapability): void {
233    let previewProfiles: Array<camera.Profile> = profiles.previewProfiles;
234    let videoProfiles: Array<camera.Profile> = profiles.videoProfiles;
235    let photoProfiles: Array<camera.Profile> = profiles.photoProfiles;
236    let depthProfiles: Array<camera.Profile> = profiles.depthProfiles;
237    let isValidProfiles = true;
238    if (!previewProfiles || previewProfiles.length < 1) {
239      isValidProfiles = false;
240    }
241    if (isValidProfiles && (!photoProfiles || photoProfiles.length < 1)) {
242      isValidProfiles = false;
243    }
244    if (isValidProfiles && this.cameraMode !== CameraMode.PORTRAIT && (!videoProfiles || videoProfiles.length < 1)) {
245      isValidProfiles = false;
246    }
247    if (!isValidProfiles) {
248      Logger.error('Profile is invalid');
249      return;
250    }
251    let defaultAspectRatio: number = AppStorage.get<number>('defaultAspectRatio');
252    let previewProfileObj: camera.Profile;
253    let photoProfileObj: camera.Profile;
254    let depthProfileObj: camera.Profile;
255    if (!depthProfiles) {
256        depthProfileObj = depthProfiles[0];
257    }
258    const deviceType = AppStorage.get<string>('deviceType');
259    switch (this.cameraMode) {
260      case CameraMode.PORTRAIT:
261        previewProfileObj = previewProfiles.find((profile: camera.Profile) => {
262          return profile.size.height === this.defaultProfile.size.height &&
263            profile.size.width === this.defaultProfile.size.width;
264        });
265        Logger.info(`previewProfileObj: ${JSON.stringify(previewProfileObj)}`);
266        this.previewProfileObj = previewProfileObj;
267        photoProfileObj = photoProfiles.find((profile: camera.Profile) => {
268          return profile.size.height === this.defaultProfile.size.height &&
269            profile.size.width === this.defaultProfile.size.width;
270        });
271        Logger.info(`photoProfileObj: ${JSON.stringify(photoProfileObj)}`);
272        this.photoProfileObj = photoProfileObj;
273        break;
274      case CameraMode.SUPER_STAB:
275        previewProfileObj = previewProfiles.find((profile: camera.Profile) => {
276          return profile.size.height === this.defaultProfile.size.height &&
277            profile.size.width === this.defaultProfile.size.width;
278        });
279        Logger.info(`previewProfileObj: ${JSON.stringify(previewProfileObj)}`);
280        this.previewProfileObj = previewProfileObj;
281        photoProfileObj = photoProfiles.find((profile: camera.Profile) => {
282          return profile.size.height === this.defaultProfile.size.height &&
283            profile.size.width === this.defaultProfile.size.width;
284        });
285        Logger.info(`photoProfileObj: ${JSON.stringify(photoProfileObj)}`);
286        this.photoProfileObj = photoProfileObj;
287        this.videoProfileObj = {
288          format: 1003,
289          size: {
290            width: 1920,
291            height: 1080
292          },
293          frameRateRange: {
294            min: 60,
295            max: 60
296          }
297        };
298        let videoProfileObj = videoProfiles.find((profile: camera.VideoProfile) => {
299          return profile.size.height === this.videoProfileObj.size.height &&
300            profile.size.width === this.videoProfileObj.size.width &&
301            profile.frameRateRange.min === this.videoProfileObj.frameRateRange.min &&
302            profile.frameRateRange.max === this.videoProfileObj.frameRateRange.max;
303        });
304        Logger.info(`videoProfileObj: ${JSON.stringify(videoProfileObj)}`);
305        if (!videoProfileObj) {
306          Logger.error('videoProfileObj not supported');
307        }
308        break;
309      case CameraMode.NIGHT:
310        previewProfileObj = previewProfiles.find((profile: camera.Profile) => {
311          return profile.size.height === this.defaultProfile.size.height &&
312            profile.size.width === this.defaultProfile.size.width;
313        });
314        Logger.info(`previewProfileObj: ${JSON.stringify(previewProfileObj)}`);
315        this.previewProfileObj = previewProfileObj;
316        photoProfileObj = photoProfiles.find((profile: camera.Profile) => {
317          return profile.size.height === this.defaultProfile.size.height &&
318            profile.size.width === this.defaultProfile.size.width;
319        });
320        Logger.info(`photoProfileObj: ${JSON.stringify(photoProfileObj)}`);
321        this.photoProfileObj = photoProfileObj;
322        break;
323      case CameraMode.NORMAL:
324      case CameraMode.VIDEO:
325      default:
326        for (let index = profiles.previewProfiles.length - 1; index >= 0; index--) {
327          const previewProfile = profiles.previewProfiles[index];
328          if (this.withinErrorMargin(defaultAspectRatio, previewProfile.size.width / previewProfile.size.height)) {
329            if (previewProfile.size.width <= Constants.PHOTO_MAX_WIDTH &&
330              previewProfile.size.height <= Constants.PHOTO_MAX_WIDTH) {
331              let previewProfileTemp = {
332                format: deviceType === Constants.DEFAULT ? previewProfile.format : this.defaultProfile.format,
333                size: {
334                  width: previewProfile.size.width,
335                  height: previewProfile.size.height
336                }
337              };
338              this.previewProfileObj = previewProfileTemp;
339              Logger.debug(TAG, `previewProfileObj: ${JSON.stringify(this.previewProfileObj)}`);
340              break;
341            }
342          }
343        }
344        for (let index = profiles.videoProfiles.length - 1; index >= 0; index--){
345          let videoProfile = profiles.videoProfiles[index];
346          if (this.withinErrorMargin(defaultAspectRatio, videoProfile.size.width / videoProfile.size.height)) {
347            if (videoProfile.size.width <= Constants.PHOTO_MAX_WIDTH &&
348              videoProfile.size.height <= Constants.PHOTO_MAX_WIDTH) {
349              this.videoProfileObj = videoProfile;
350              Logger.debug(TAG, `videoProfileObj: ${JSON.stringify(this.videoProfileObj)}`);
351              break;
352            }
353          }
354        }
355        for (let index = profiles.photoProfiles.length - 1; index >= 0; index--) {
356          const photoProfile = profiles.photoProfiles[index];
357          if (this.withinErrorMargin(defaultAspectRatio, photoProfile.size.width / photoProfile.size.height)) {
358            if (photoProfile.size.width <= Constants.PHOTO_MAX_WIDTH &&
359              photoProfile.size.height <= Constants.PHOTO_MAX_WIDTH) {
360              let photoProfileTemp = {
361                format: photoProfile.format,
362                size: {
363                  width: photoProfile.size.width,
364                  height: photoProfile.size.height
365                }
366              };
367              this.photoProfileObj = photoProfileTemp;
368              Logger.debug(TAG, `photoProfileObj: ${JSON.stringify(this.photoProfileObj)}`);
369              break;
370            }
371          }
372        }
373    }
374    if (deviceType === Constants.DEFAULT) {
375      let cameraConfig = this.globalContext.getObject('cameraConfig') as CameraConfig;
376      for (let index = this.videoProfiles.length - 1; index >= 0; index--) {
377        const videoProfileObj = this.videoProfiles[index];
378        if (this.withinErrorMargin(defaultAspectRatio, videoProfileObj.size.width / videoProfileObj.size.height)) {
379          if (videoProfileObj.size.width <= Constants.VIDEO_MAX_WIDTH &&
380            videoProfileObj.size.height <= Constants.VIDEO_MAX_WIDTH) {
381            let videoProfileTemp = {
382              format: videoProfileObj.format,
383              size: {
384                width: videoProfileObj.size.width,
385                height: videoProfileObj.size.height
386              },
387              frameRateRange: {
388                min: Constants.VIDEO_FRAME_30,
389                max: Constants.VIDEO_FRAME_30
390              }
391            };
392            if ((cameraConfig.videoFrame === 0 ? Constants.VIDEO_FRAME_15 : Constants.VIDEO_FRAME_30) ===
393            videoProfileObj.frameRateRange.min) {
394              videoProfileTemp.frameRateRange.min = videoProfileObj.frameRateRange.min;
395              videoProfileTemp.frameRateRange.max = videoProfileObj.frameRateRange.max;
396              this.videoProfileObj = videoProfileTemp;
397              Logger.info(TAG, `videoProfileObj: ${JSON.stringify(this.videoProfileObj)}`);
398              break;
399            }
400            Logger.info(TAG, `videoProfileTemp: ${JSON.stringify(videoProfileTemp)}`);
401            this.videoProfileObj = videoProfileTemp;
402          }
403        }
404      }
405    }
406  }
407
408  setCameraMode(cameraMode: number): void {
409    this.cameraMode = cameraMode;
410  }
411
412  initProfile(cameraDeviceIndex: number): void {
413    let profiles;
414    if (this.cameraMode === CameraMode.PORTRAIT) {
415      profiles = this.cameraManager.getSupportedOutputCapability(this.cameras[cameraDeviceIndex], camera.SceneMode.PORTRAIT_PHOTO);
416    } else {
417      profiles = this.cameraManager.getSupportedOutputCapability(this.cameras[cameraDeviceIndex]);
418    }
419    this.videoProfiles = profiles.videoProfiles;
420    this.switchProfiles(profiles);
421  }
422
423  /**
424   * 初始化
425   */
426  async initCamera(surfaceId: string, cameraDeviceIndex: number): Promise<void> {
427    try {
428      this.isFirstRecord = true;
429      // 获取传入摄像头
430      Logger.debug(TAG, `initCamera cameraDeviceIndex: ${cameraDeviceIndex}`);
431      await this.releaseCamera();
432      // 获取相机管理器实例
433      this.getCameraManagerFn();
434      if (this.cameraMode === CameraMode.PORTRAIT || this.cameraMode === CameraMode.NIGHT) {
435        this.getModeManagerFn();
436      }
437      // 获取支持指定的相机设备对象
438      this.getSupportedCamerasFn();
439      if (this.cameraMode === CameraMode.PORTRAIT || this.cameraMode === CameraMode.NIGHT) {
440        this.getSupportedModeFn(cameraDeviceIndex);
441      }
442      this.initProfile(cameraDeviceIndex);
443      // 创建previewOutput输出对象
444      this.createPreviewOutputFn(this.previewProfileObj, surfaceId);
445      // 创建depthOutput输出对象
446      if (this.depthProfileObj) {
447        this.createDepthDataOutputFn(this.depthProfileObj);
448      }
449      // 监听预览事件
450      this.previewOutputCallBack();
451      if (this.cameraMode === CameraMode.SUPER_STAB || this.cameraMode === CameraMode.VIDEO) {
452        await this.createAVRecorder();
453        await this.createVideoOutput();
454        // 监听录像事件
455        this.onVideoOutputChange();
456      }
457      // 创建photoOutPut输出对象
458      let mSurfaceId = await this.mReceiver.getReceivingSurfaceId();
459      this.createPhotoOutputFn(this.photoProfileObj, mSurfaceId);
460      // 拍照监听事件
461      this.photoOutPutCallBack();
462      // 创建cameraInput输出对象
463      this.createCameraInputFn(this.cameras[cameraDeviceIndex]);
464      // 打开相机
465      await this.cameraInputOpenFn();
466      // 镜头状态回调
467      this.onCameraStatusChange();
468      // 监听CameraInput的错误事件
469      this.onCameraInputChange();
470      // 会话流程
471      if (this.cameraMode === CameraMode.PORTRAIT) {
472        await this.portraitSessionFlowFn();
473      } else if (this.cameraMode === CameraMode.NIGHT) {
474        await this.nightSessionFlowFn();
475      } else if (this.cameraMode === CameraMode.VIDEO) {
476        await this.videoSessionFlowFn();
477      } else {
478        await this.photoSessionFlowFn();
479      }
480    } catch (error) {
481      let err = error as BusinessError;
482      Logger.error(TAG, `initCamera fail: ${JSON.stringify(err)}`);
483    }
484  }
485
486  isVideoFrameSupportedFn(videoFrame: number): boolean {
487    let videoProfile: camera.VideoProfile | undefined = this.videoProfiles.find((videoProfile: camera.VideoProfile) => {
488      return videoProfile.size.height === this.videoProfileObj.size.height &&
489        videoProfile.size.width === this.videoProfileObj.size.width &&
490        videoProfile.format === this.videoProfileObj.format &&
491        videoProfile.frameRateRange.min === videoFrame &&
492        videoProfile.frameRateRange.max === videoFrame;
493    });
494    return videoProfile === undefined ? false : true;
495  }
496
497  /**
498   * 是否支持摄像头切换
499   */
500  isCameraSwitchSupportedFn(): boolean {
501    return this.cameraManager.getSupportedCameras().length > 1;
502  }
503
504  /**
505   * 曝光
506   */
507  isExposureModeSupportedFn(aeMode: camera.ExposureMode): boolean {
508    // 检测曝光模式是否支持
509    let isSupported: boolean = false;
510    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
511    if (!session) {
512      return isSupported;
513    }
514    isSupported = session.isExposureModeSupported(aeMode);
515    Logger.info(TAG, `isExposureModeSupported success, isSupported: ${isSupported}`);
516    return isSupported;
517  }
518
519  setExposureMode(aeMode: camera.ExposureMode): void {
520    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
521    if (!session) {
522      return;
523    }
524    session.setExposureMode(aeMode);
525    let exposureMode: camera.ExposureMode | undefined = undefined;
526    exposureMode = session.getExposureMode();
527    Logger.info(TAG, `getExposureMode success, exposureMode: ${exposureMode}`);
528  }
529
530  /**
531   * 曝光区域
532   */
533  isMeteringPoint(point: camera.Point): void {
534    // 获取当前曝光模式
535    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
536    if (!session) {
537      return;
538    }
539    let exposureMode: camera.ExposureMode | undefined = undefined;
540    exposureMode = session.getExposureMode();
541    Logger.info(TAG, `getExposureMode success, exposureMode: ${exposureMode}`);
542    session.setMeteringPoint(point);
543    let exposurePoint: camera.Point | undefined = undefined;
544    exposurePoint = session.getMeteringPoint();
545    Logger.info(TAG, `getMeteringPoint exposurePoint: ${JSON.stringify(exposurePoint)}`);
546  }
547
548  /**
549   * 曝光补偿
550   */
551  isExposureBiasRange(exposureBias: number): void {
552    Logger.debug(TAG, `setExposureBias value ${exposureBias}`);
553    // 查询曝光补偿范围
554    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
555    if (!session) {
556      return;
557    }
558    let biasRangeArray: Array<number> = [];
559    biasRangeArray = session.getExposureBiasRange();
560    Logger.debug(TAG, `getExposureBiasRange success, biasRangeArray: ${JSON.stringify(biasRangeArray)}`);
561    // 设置曝光补偿
562    session.setExposureBias(exposureBias);
563  }
564
565  /**
566   * 是否支持对应对焦模式
567   */
568  isFocusModeSupported(focusMode: camera.FocusMode): boolean {
569    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
570    if (!session) {
571      return false;
572    }
573    return session.isFocusModeSupported(focusMode);
574  }
575
576  /**
577   * 对焦模式
578   */
579  isFocusMode(focusMode: camera.FocusMode): void {
580    // 检测对焦模式是否支持
581    let isSupported = this.isFocusModeSupported(focusMode);
582    Logger.info(TAG, `isFocusModeSupported isSupported: ${JSON.stringify(isSupported)}`);
583    // 设置对焦模式
584    if (!isSupported) {
585      return;
586    }
587    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
588    if (!session) {
589      return;
590    }
591    session.setFocusMode(focusMode);
592  }
593
594  /**
595   * 焦点
596   */
597  isFocusPoint(point: camera.Point): void {
598    // 设置焦点
599    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
600    if (!session) {
601      return;
602    }
603    session.setFocusPoint(point);
604    Logger.info(TAG, 'setFocusPoint success');
605    // 获取当前的焦点
606    let nowPoint: camera.Point | undefined = undefined;
607    nowPoint = session.getFocusPoint();
608    Logger.info(TAG, `getFocusPoint success, nowPoint: ${JSON.stringify(nowPoint)}`);
609  }
610
611  /**
612   * 闪关灯
613   */
614  hasFlashFn(flashMode: camera.FlashMode): void {
615    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
616    if (!session) {
617      return;
618    }
619    // 检测是否有闪关灯
620    let hasFlash = session.hasFlash();
621    Logger.debug(TAG, `hasFlash success, hasFlash: ${hasFlash}`);
622    // 检测闪光灯模式是否支持
623    let isFlashModeSupported = session.isFlashModeSupported(flashMode);
624    Logger.debug(TAG, `isFlashModeSupported success, isFlashModeSupported: ${isFlashModeSupported}`);
625    // 设置闪光灯模式
626    session.setFlashMode(flashMode);
627    // 获取当前设备的闪光灯模式
628    let nowFlashMode = session.getFlashMode();
629    Logger.debug(TAG, `getFlashMode success, nowFlashMode: ${nowFlashMode}`);
630  }
631
632  getSession(): camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession | undefined {
633    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = undefined;
634    if (this.cameraMode === CameraMode.PORTRAIT) {
635      session = this.portraitSession;
636    } else if (this.cameraMode === CameraMode.NIGHT) {
637      session = this.nightSession;
638    } else if (this.cameraMode === CameraMode.VIDEO) {
639      session = this.videoSession;
640    } else {
641      session = this.photoSession;
642    }
643    return session;
644  }
645
646  isSupportZoom() {
647    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession  = this.getSession();
648    let zoomRatioRange = session.getZoomRatioRange();
649    return zoomRatioRange != undefined;
650  }
651
652  /**
653   * 变焦
654   */
655  setZoomRatioFn(zoomRatio: number): void {
656    Logger.info(TAG, `setZoomRatioFn value ${zoomRatio}`);
657    // 获取支持的变焦范围
658    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
659    if (!session) {
660      return;
661    }
662    try {
663      let zoomRatioRange = session.getZoomRatioRange();
664      Logger.info(TAG, `getZoomRatioRange success: ${JSON.stringify(zoomRatioRange)}`);
665    } catch (error) {
666      let err = error as BusinessError;
667      Logger.error(TAG, `getZoomRatioRange fail: ${JSON.stringify(err)}`);
668    }
669
670    try {
671      session.setZoomRatio(zoomRatio);
672      Logger.info(TAG, 'setZoomRatioFn success');
673    } catch (error) {
674      let err = error as BusinessError;
675      Logger.error(TAG, `setZoomRatioFn fail: ${JSON.stringify(err)}`);
676    }
677
678    try {
679      let nowZoomRatio = session.getZoomRatio();
680      Logger.info(TAG, `getZoomRatio nowZoomRatio: ${JSON.stringify(nowZoomRatio)}`);
681    } catch (error) {
682      let err = error as BusinessError;
683      Logger.error(TAG, `getZoomRatio fail: ${JSON.stringify(err)}`);
684    }
685  }
686
687  /**
688   * 防抖
689   */
690  isVideoStabilizationModeSupportedFn(videoStabilizationMode: camera.VideoStabilizationMode): boolean {
691    // 查询是否支持指定的视频防抖模式
692    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
693    let isVideoStabilizationModeSupported: boolean = session.isVideoStabilizationModeSupported(videoStabilizationMode);
694    Logger.info(TAG, `isVideoStabilizationModeSupported success: ${JSON.stringify(isVideoStabilizationModeSupported)}`);
695    return isVideoStabilizationModeSupported;
696  }
697
698  setVideoStabilizationMode(videoStabilizationMode: camera.VideoStabilizationMode): void {
699    // 设置视频防抖
700    Logger.info(TAG, `setVideoStabilizationMode: ${videoStabilizationMode}`);
701    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
702    session.setVideoStabilizationMode(videoStabilizationMode);
703    let nowVideoStabilizationMod: camera.VideoStabilizationMode = session.getActiveVideoStabilizationMode();
704    Logger.info(TAG, `getActiveVideoStabilizationMode nowVideoStabilizationMod: ${nowVideoStabilizationMod}`);
705  }
706
707  /**
708   * 是否支持夜景模式
709   */
710  isNightModeSupportedFn(): boolean {
711    let isSupportNightMode: boolean = this.sceneModes.indexOf(CameraMode.NIGHT) >= 0;
712    Logger.info(TAG, `isSupportNightMode success: ${JSON.stringify(isSupportNightMode)}`);
713    return isSupportNightMode;
714  }
715
716  /**
717   * 是否支持人像模式
718   */
719  isPortraitModeSupportedFn(): boolean {
720    let isSupportPortraitMode: boolean = this.sceneModes.indexOf(CameraMode.PORTRAIT) >= 0;
721    Logger.info(TAG, `isSupportPortraitMode success: ${JSON.stringify(isSupportPortraitMode)}`);
722    return isSupportPortraitMode;
723  }
724
725  /**
726   * 是否支持镜像
727   */
728  isMirrorSupportedFn(): void {
729    let isSupported = this.photoOutPut.isMirrorSupported();
730    Logger.info(TAG, `isMirrorSupported success Bol: ${JSON.stringify(isSupported)}`);
731  }
732
733  setTakePictureCallback(callback: (photoUri: string) => void): void {
734    this.handleTakePicture = callback;
735  }
736
737  /**
738   * 照片方向判断
739   */
740  onChangeRotation(): number {
741    let cameraConfig = (this.globalContext.getObject('cameraConfig') as CameraConfig);
742    switch (cameraConfig.photoOrientation) {
743      case PhotoOrientation.ORIENTATION_1:
744        return this.photoRotationMap.rotation90;
745      case PhotoOrientation.ORIENTATION_2:
746        return this.photoRotationMap.rotation180;
747      case PhotoOrientation.ORIENTATION_3:
748        return this.photoRotationMap.rotation270;
749      case PhotoOrientation.ORIENTATION_0:
750      default:
751        return this.photoRotationMap.rotation0;
752    }
753  }
754
755  /**
756   * 照片地理位置逻辑 ,后续需要靠定位实现 目前传入固定值
757   */
758  onChangeLocation(): {
759    latitude: number,
760    longitude: number,
761    altitude: number
762  } {
763    let cameraConfig = (this.globalContext.getObject('cameraConfig') as CameraConfig);
764    if (cameraConfig.locationBol) {
765      return {
766        // 位置信息,经纬度
767        latitude: 12.9698,
768        longitude: 77.7500,
769        altitude: 1000
770      };
771    }
772    return {
773      latitude: 0,
774      longitude: 0,
775      altitude: 0
776    };
777  }
778
779  /**
780   * 拍照
781   */
782  async takePicture(mirrorBol?: boolean): Promise<void> {
783    Logger.info(TAG, 'takePicture start');
784    mirrorBol = mirrorBol || false;
785    this.isMirrorSupportedFn();
786    let cameraConfig = (this.globalContext.getObject('cameraConfig') as CameraConfig);
787    let photoSettings = {
788      rotation: this.onChangeRotation(),
789      quality: cameraConfig.photoQuality,
790      location: this.onChangeLocation(),
791      mirror: cameraConfig.mirrorBol
792    };
793    Logger.debug(TAG, `takePicture photoSettings:${JSON.stringify(photoSettings)}`);
794    await this.photoOutPut.capture(photoSettings);
795    Logger.info(TAG, 'takePicture end');
796  }
797
798  /**
799   * 开启深度流
800   */
801  async startDepthDataOutput(depthDataOutput: camera.DepthDataOutput): Promise<void> {
802    Logger.info(TAG, 'startDepthDataOutput');
803    if (!depthDataOutput) {
804      Logger.error(TAG, 'depthDataOutput Undefined');
805      return;
806    }
807    try {
808      await depthDataOutput.start();
809    } catch (err) {
810      const error = err as BusinessError;
811      Logger.error(TAG, `depthDataOutputStart error:${error.code};${error.message}`);
812    }
813  }
814
815  /**
816   * 停止深度流
817   */
818  async stopDepthDataOutput(depthDataOutput: camera.DepthDataOutput): Promise<void> {
819    Logger.info(TAG, 'stopDepthDataOutput');
820    if (!depthDataOutput) {
821      Logger.error(TAG, 'depthDataOutput Undefined');
822      return;
823    }
824    try {
825      await depthDataOutput.stop();
826    } catch (err) {
827      const error = err as BusinessError;
828      Logger.error(TAG, `depthDataOutputStop error:${error.code};${error.message}`);
829    }
830  }
831
832  /**
833   * 接收深度数据
834   */
835  depthDataOutputOnDataAvailable(depthDataOutput: camera.DepthDataOutput,
836    callback?: (err: BusinessError, data: camera.DepthData) => void): void {
837    Logger.info(TAG, 'depthDataOutputOnDataAvailable');
838    if (!depthDataOutput) {
839      Logger.error(TAG, 'depthDataOutput Undefined');
840      return;
841    }
842    depthDataOutput.on('depthDataAvailable', (err: BusinessError, data: camera.DepthData) => {
843      callback?.(err, data);
844      // 获取到的深度图数据处理后,需要将对应的图像Buffer释放
845      this.releaseDepthData(data);
846    });
847  }
848
849  /**
850   * 释放深度图数据
851   */
852  releaseDepthData(depthData: camera.DepthData): void {
853    if (!depthData) {
854      Logger.error(TAG, 'depthData Undefined');
855      return;
856    }
857    try {
858      if (!depthData.depthMap) {
859        Logger.error(TAG, 'depthMap Undefined');
860      }
861      depthData.release();
862    } catch (err) {
863      const error = err as BusinessError;
864      Logger.error(TAG, `releaseDepthData error:${error.code};${error.message}`);
865    }
866  }
867
868  /**
869   * 监听深度输出流事件回调
870   */
871  depthDataOutputOnEvent(depthDataOutput: camera.DepthDataOutput,
872    errCallback?: (err: BusinessError) => void): void {
873    Logger.info(TAG, 'depthDataOutputOnEvent');
874    if (!depthDataOutput) {
875      Logger.error(TAG, 'depthDataOutput Undefined');
876      return;
877    }
878    depthDataOutput.on('error', (err: BusinessError) => {
879      Logger.error(TAG, 'depthDataOutput error');
880      errCallback?.(err);
881    });
882  }
883
884  /**
885   * 取消监听深度输出流事件回调
886   */
887  depthDataOutputOffEvent(depthDataOutput: camera.DepthDataOutput): void {
888    Logger.info(TAG, 'depthDataOutputOffEvent');
889    if (!depthDataOutput) {
890      Logger.error(TAG, 'depthDataOutput Undefined');
891      return;
892    }
893    depthDataOutput.off('depthDataAvailable');
894    depthDataOutput.off('error');
895  }
896
897  async prepareAVRecorder(): Promise<void> {
898    await this.initUrl();
899    let deviceType = AppStorage.get<string>('deviceType');
900    if (deviceType === Constants.DEFAULT) {
901      this.videoConfig.videoSourceType = media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_ES;
902    }
903    if (deviceType === Constants.PHONE) {
904      this.videoConfig.videoSourceType = media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV;
905      this.videoConfig.profile.videoCodec = media.CodecMimeType.VIDEO_AVC;
906      this.videoConfig.rotation = this.photoRotationMap.rotation90;
907    }
908    if (deviceType === Constants.TABLET) {
909      this.videoConfig.videoSourceType = media.VideoSourceType.VIDEO_SOURCE_TYPE_SURFACE_YUV;
910    }
911    this.videoConfig.profile.videoFrameWidth = this.videoProfileObj.size.width;
912    this.videoConfig.profile.videoFrameHeight = this.videoProfileObj.size.height;
913    this.videoConfig.profile.videoFrameRate = this.videoProfileObj.frameRateRange.max;
914    Logger.info(TAG, `prepareAVRecorder deviceType: ${deviceType}, videoSourceType: ${JSON.stringify(this.videoConfig)}`);
915    await this.videoRecorder.prepare(this.videoConfig).catch((err: { code?: number }): void => {
916      Logger.error(TAG, `prepareAVRecorder prepare err: ${JSON.stringify(err)}`);
917    });
918  }
919
920  async getAVRecorderSurfaceId(): Promise<string> {
921    return await this.videoRecorder.getInputSurface();
922  }
923
924  async createAVRecorder(): Promise<void> {
925    this.videoRecorder = await media.createAVRecorder();
926  }
927
928  /**
929   * 配置videoOutput流
930   */
931  async createVideoOutput(): Promise<void> {
932    Logger.info(TAG, 'createVideoOutput start');
933    await this.prepareAVRecorder();
934    let videoId = await this.getAVRecorderSurfaceId();
935    Logger.debug(TAG, `createVideoOutput videoProfileObj: ${JSON.stringify(this.videoProfileObj)}`);
936    this.videoOutput = this.cameraManager.createVideoOutput(this.videoProfileObj, videoId);
937    Logger.info(TAG, 'createVideoOutput end');
938  }
939
940  /**
941   * 暂停录制
942   */
943  async pauseVideo(): Promise<void> {
944    await this.videoRecorder.pause().then((): void => {
945      this.videoOutput.stop();
946      this.videoOutputStatus = false;
947      Logger.info(TAG, 'pauseVideo success');
948    }).catch((err: BusinessError): void => {
949      Logger.error(TAG, `pauseVideo failed: ${JSON.stringify(err)}`);
950    });
951  }
952
953  /**
954   * 恢复视频录制
955   */
956  async resumeVideo(): Promise<void> {
957    this.videoOutput.start().then((): void => {
958      this.videoOutputStatus = true;
959      Logger.info(TAG, 'resumeVideo start');
960      this.videoRecorder.resume().then((): void => {
961        Logger.info(TAG, 'resumeVideo success');
962      }).catch((err: { code?: number }): void => {
963        Logger.error(TAG, `resumeVideo failed: ${JSON.stringify(err)}`);
964      });
965    });
966  }
967
968  /**
969   * 初始化录制适配地址
970   */
971  async initUrl(): Promise<void> {
972    let fileName = `${Date.now()}.mp4`;
973    this.fileAsset = await this.accessHelper.createAsset(fileName);
974    this.fd = await this.fileAsset.open('rw');
975    this.videoConfig.url = `fd://${this.fd.toString()}`;
976  }
977
978  /**
979   * 开始录制
980   */
981  async startVideo(): Promise<void> {
982    try {
983      Logger.info(TAG, 'startVideo begin');
984      await this.videoOutput.start();
985      this.videoOutputStatus = true;
986      if (!this.isFirstRecord) {
987        await this.prepareAVRecorder();
988        await this.getAVRecorderSurfaceId();
989      }
990      await this.videoRecorder.start();
991      this.isFirstRecord = false;
992      AppStorage.setOrCreate<boolean>('isRecorder', true);
993      Logger.info(TAG, 'startVideo end');
994    } catch (error) {
995      let err = error as BusinessError;
996      Logger.error(TAG, `startVideo err: ${JSON.stringify(err)}`);
997    }
998  }
999
1000  async releaseVideoRecorder(): Promise<void> {
1001    if (this.videoRecorder) {
1002      try {
1003        await this.videoRecorder.release();
1004        this.videoOutputStatus = false;
1005        AppStorage.setOrCreate<boolean>('isRecorder', false);
1006      } catch (error) {
1007        let err = error as BusinessError;
1008        Logger.error(TAG, 'stopVideo err: ' + JSON.stringify(err));
1009      }
1010    }
1011  }
1012
1013  /**
1014   * 停止录制
1015   */
1016  async stopVideo(): Promise<photoAccessHelper.PhotoAsset> {
1017    let isRecorder: boolean = AppStorage.get<boolean>('isRecorder');
1018    if (!isRecorder) {
1019      Logger.info(TAG, 'not in recording');
1020      return undefined;
1021    }
1022    try {
1023      Logger.info(TAG, 'stopVideo start');
1024      AppStorage.setOrCreate<boolean>('isRecorder', false);
1025      if (this.videoRecorder) {
1026        await this.videoRecorder.stop();
1027      }
1028      if (this.videoOutputStatus) {
1029        await this.videoOutput.stop();
1030        this.videoOutputStatus = false;
1031      }
1032      if (this.fileAsset) {
1033        await this.fileAsset.close(this.fd);
1034        return this.fileAsset;
1035      }
1036      return undefined;
1037    } catch (error) {
1038      let err = error as BusinessError;
1039      Logger.error(TAG, 'stopVideo err: ' + JSON.stringify(err));
1040      return undefined;
1041    }
1042  }
1043
1044  /**
1045   * 释放会话及其相关参数
1046   */
1047  async releaseCamera(): Promise<void> {
1048    Logger.info(TAG, 'releaseCamera is called');
1049    await this.stopVideo();
1050    await this.releaseVideoRecorder();
1051    if (this.previewOutput) {
1052      try {
1053        await this.previewOutput.stop();
1054        await this.previewOutput.release();
1055      } catch (error) {
1056        let err = error as BusinessError;
1057        Logger.error(TAG, `previewOutput release fail: error: ${JSON.stringify(err)}`);
1058      } finally {
1059        this.previewOutput = null;
1060      }
1061
1062    }
1063    if (this.photoOutPut) {
1064      try {
1065        await this.photoOutPut.release();
1066      } catch (error) {
1067        let err = error as BusinessError;
1068        Logger.error(TAG, `photoOutPut release fail: error: ${JSON.stringify(err)}`);
1069      } finally {
1070        this.photoOutPut = null;
1071      }
1072    }
1073    if (this.videoOutput) {
1074      try {
1075        await this.videoOutput.release();
1076      } catch (error) {
1077        let err = error as BusinessError;
1078        Logger.error(TAG, `videoOutput release fail: error: ${JSON.stringify(err)}`);
1079      } finally {
1080        this.videoOutput = null;
1081      }
1082    }
1083    if (this.portraitSession) {
1084      try {
1085        await this.portraitSession.release();
1086      } catch (error) {
1087        let err = error as BusinessError;
1088        Logger.error(TAG, `portraitSession release fail: error: ${JSON.stringify(err)}`);
1089      } finally {
1090        this.portraitSession = null;
1091      }
1092    }
1093    if (this.nightSession) {
1094      try {
1095        await this.nightSession.release();
1096      } catch (error) {
1097        let err = error as BusinessError;
1098        Logger.error(TAG, `nightSession release fail: error: ${JSON.stringify(err)}`);
1099      } finally {
1100        this.nightSession = null;
1101      }
1102    }
1103    if (this.photoSession) {
1104      try {
1105        await this.photoSession.release();
1106      } catch (error) {
1107        let err = error as BusinessError;
1108        Logger.error(TAG, `photoSession release fail: error: ${JSON.stringify(err)}`);
1109      } finally {
1110        this.photoSession = null;
1111      }
1112    }
1113    if (this.videoSession) {
1114      try {
1115        await this.videoSession.release();
1116      } catch (error) {
1117        let err = error as BusinessError;
1118        Logger.error(TAG, `videoSession release fail: error: ${JSON.stringify(err)}`);
1119      } finally {
1120        this.videoSession = null;
1121      }
1122    }
1123    if (this.cameraInput) {
1124      try {
1125        await this.cameraInput.close();
1126      } catch (error) {
1127        let err = error as BusinessError;
1128        Logger.error(TAG, `cameraInput close fail: error: ${JSON.stringify(err)}`);
1129      } finally {
1130        this.cameraInput = null;
1131      }
1132    }
1133    Logger.info(TAG, 'releaseCamera success');
1134  }
1135
1136  /**
1137   * 获取相机管理器实例
1138   */
1139  getCameraManagerFn(): void {
1140    if (this.cameraManager) {
1141      return;
1142    }
1143    try {
1144      this.cameraManager = camera.getCameraManager(GlobalContext.get().getCameraSettingContext());
1145      Logger.info(TAG, `getCameraManager success: ${this.cameraManager}`);
1146    } catch (error) {
1147      let err = error as BusinessError;
1148      Logger.error(TAG, `getCameraManager failed: ${JSON.stringify(err)}`);
1149    }
1150  }
1151
1152  getModeManagerFn(): void {
1153    try {
1154      this.cameraManager = camera.getCameraManager(GlobalContext.get().getCameraSettingContext());
1155      Logger.info(TAG, `getModeManagerFn success: ${this.cameraManager}`);
1156    } catch (error) {
1157      let err = error as BusinessError;
1158      Logger.error(TAG, `getModeManagerFn failed: ${JSON.stringify(err)}`);
1159    }
1160  }
1161
1162  /**
1163   * 获取支持指定的相机设备对象
1164   */
1165  getSupportedCamerasFn(): void {
1166    try {
1167      this.cameras = this.cameraManager.getSupportedCameras();
1168      Logger.info(TAG, `getSupportedCameras success: ${this.cameras}, length: ${this.cameras.length}`);
1169    } catch (error) {
1170      let err = error as BusinessError;
1171      Logger.error(TAG, `getSupportedCameras failed: ${JSON.stringify(err)}`);
1172    }
1173  }
1174
1175  getSupportedModeFn(cameraIndex: number): void {
1176    try {
1177      this.sceneModes = this.cameraManager.getSupportedSceneModes(this.cameras[cameraIndex]);
1178      Logger.info(TAG, `getSupportedModeFn success: ${this.sceneModes}, length: ${this.sceneModes.length}`);
1179    } catch (error) {
1180      let err = error as BusinessError;
1181      Logger.error(TAG, `getSupportedModeFn failed: ${JSON.stringify(err)}`);
1182    }
1183  }
1184
1185  /**
1186   * 查询相机设备在模式下支持的输出能力
1187   */
1188  async getSupportedOutputCapabilityFn(cameraDeviceIndex: number): Promise<void> {
1189    this.cameraOutputCapability = this.cameraManager.getSupportedOutputCapability(this.cameras[cameraDeviceIndex]);
1190  }
1191
1192  /**
1193   * 创建previewOutput输出对象
1194   */
1195  createPreviewOutputFn(photoProfileObj: camera.Profile, surfaceId: string): void {
1196    try {
1197      this.previewOutput = this.cameraManager.createPreviewOutput(photoProfileObj, surfaceId);
1198      Logger.info(TAG, `createPreviewOutput success: ${this.previewOutput}`);
1199    } catch (error) {
1200      let err = error as BusinessError;
1201      Logger.error(TAG, `createPreviewOutput failed: ${JSON.stringify(err)}`);
1202    }
1203  }
1204
1205  /**
1206   * 创建photoOutPut输出对象
1207   */
1208  createPhotoOutputFn(photoProfileObj: camera.Profile, surfaceId: string): void {
1209    Logger.info(TAG, `createPhotoOutputFn photoProfiles: ${JSON.stringify(photoProfileObj)} ,captureMode: ${this.captureMode}, surfaceId: ${surfaceId}`);
1210    switch (this.captureMode) {
1211      case CaptureMode.OLD_CAPTURE:
1212        this.photoOutPut = this.cameraManager.createPhotoOutput(photoProfileObj, surfaceId);
1213        break;
1214      case CaptureMode.NEW_CAPTURE:
1215      case CaptureMode.NEW_DEFERRED_PHOTO:
1216        this.photoOutPut = this.cameraManager.createPhotoOutput(photoProfileObj);
1217        if (this.photoOutPut == null) {
1218          Logger.error(TAG, 'createPhotoOutputFn createPhotoOutput failed');
1219        }
1220        break;
1221    }
1222  }
1223
1224  /**
1225   * 创建depthDataOutput输出对象
1226   */
1227  createDepthDataOutputFn(depthProfileObj: camera.Profile): void {
1228    try {
1229      this.depthDataOutput = this.cameraManager.createDepthDataOutput(depthProfileObj);
1230      Logger.info(TAG, `createDepthDataOutput success: ${this.depthDataOutput}`);
1231    } catch (error) {
1232      let err = error as BusinessError;
1233      Logger.error(TAG, `createDepthDataOutput failed: ${JSON.stringify(err)}`);
1234    }
1235  }
1236
1237  /**
1238   * 创建cameraInput输出对象
1239   */
1240  createCameraInputFn(cameraDevice: camera.CameraDevice): void {
1241    Logger.info(TAG, 'createCameraInputFn is called.');
1242    try {
1243      this.cameraInput = this.cameraManager.createCameraInput(cameraDevice);
1244    } catch (err) {
1245
1246    }
1247  }
1248
1249  /**
1250   * 打开相机
1251   */
1252  async cameraInputOpenFn(): Promise<void> {
1253    try {
1254      await this.cameraInput.open();
1255      Logger.info(TAG, 'cameraInput open success');
1256    } catch (error) {
1257      let err = error as BusinessError;
1258      Logger.error(TAG, `createCameraInput failed : ${JSON.stringify(err)}`);
1259    }
1260  }
1261
1262  /**
1263   * 处理望月信息
1264   */
1265  configMoonCaptureBoost(): void {
1266    try {
1267      let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
1268      this.isMoonCaptureBoostSupported =
1269      session.isSceneFeatureSupported(camera.SceneFeatureType.MOON_CAPTURE_BOOST);
1270      if (this.isMoonCaptureBoostSupported) {
1271        session.on('featureDetectionStatus', camera.SceneFeatureType.MOON_CAPTURE_BOOST,
1272          (error, statusObject) => {
1273            Logger.info(TAG,
1274              `on featureDetectionStatus featureType:${statusObject.featureType} detected:${statusObject.detected}`);
1275            if (statusObject.featureType === camera.SceneFeatureType.MOON_CAPTURE_BOOST) {
1276              let status = statusObject.detected;
1277              Logger.info(TAG, `on moonCaptureBoostStatus change:${status}`);
1278              AppStorage.setOrCreate('moonCaptureComponentIsShow', status);
1279              if (!status) {
1280                this.setMoonCaptureBoostEnable(status);
1281              }
1282            }
1283          });
1284      }
1285    } catch (error) {
1286      let err = error as BusinessError;
1287      Logger.error(TAG, `isMoonCaptureBoostSupported fail: error code ${err.code}`);
1288    }
1289  }
1290
1291  /**
1292   * 拍照会话流程
1293   */
1294  async photoSessionFlowFn(): Promise<void> {
1295    try {
1296      Logger.info(TAG, "photoSessionFlowFn start");
1297      // 创建PhotoSession实例
1298      this.photoSession = this.cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO);
1299      // 监听焦距的状态变化
1300      this.onFocusStateChange();
1301      // 监听拍照会话的错误事件
1302      this.onCaptureSessionErrorChange();
1303      // 开始配置会话
1304      this.photoSession.beginConfig();
1305      // 把CameraInput加入到会话
1306      this.photoSession.addInput(this.cameraInput);
1307      // 把previewOutput加入到会话
1308      this.photoSession.addOutput(this.previewOutput);
1309      // 把photoOutPut加入到会话
1310      this.photoSession.addOutput(this.photoOutPut);
1311      // 把depthDataOutput加入到会话
1312      if (this.depthDataOutput) {
1313        this.photoSession.addOutput(this.depthDataOutput);
1314      }
1315      // hdr 拍照
1316      let hdrPhotoBol: boolean = (this.globalContext.getObject('cameraConfig') as CameraConfig).hdrPhotoBol;
1317      Logger.info(TAG, "hdrPhotoBol:" + hdrPhotoBol);
1318      if (hdrPhotoBol) {
1319        this.setColorSpace(this.photoSession, colorSpaceManager.ColorSpace.DISPLAY_P3);
1320      } else {
1321        this.setColorSpace(this.photoSession, colorSpaceManager.ColorSpace.SRGB);
1322      }
1323      // 提交配置信息
1324      await this.photoSession.commitConfig();
1325      // 开始会话工作
1326      await this.photoSession.start();
1327    } catch (error) {
1328      let err = error as BusinessError;
1329      Logger.error(TAG, `photoSessionFlowFn fail : ${JSON.stringify(err)}`);
1330    }
1331  }
1332
1333  /**
1334   * 录像会话流程
1335   */
1336  async videoSessionFlowFn(): Promise<void> {
1337    try {
1338      Logger.info(TAG, "videoSessionFlowFn start");
1339      // 创建VideoSession实例
1340      this.videoSession = this.cameraManager.createSession(camera.SceneMode.NORMAL_VIDEO);
1341      // 监听焦距的状态变化
1342      this.onFocusStateChange();
1343      // 监听拍照会话的错误事件
1344      this.onCaptureSessionErrorChange();
1345      // 开始配置会话
1346      this.videoSession.beginConfig();
1347      // 把CameraInput加入到会话
1348      this.videoSession.addInput(this.cameraInput);
1349      // 把previewOutput加入到会话
1350      this.videoSession.addOutput(this.previewOutput);
1351      // 把photoOutPut加入到会话
1352      this.videoSession.addOutput(this.videoOutput);
1353      // 提交配置信息
1354      await this.videoSession.commitConfig();
1355      // hdr 录像
1356      let hdrVideoBol: boolean = (this.globalContext.getObject('cameraConfig') as CameraConfig).hdrVideoBol;
1357      Logger.info(TAG, "hdrVideoBol:" + hdrVideoBol);
1358      if (hdrVideoBol) {
1359        this.setColorSpace(this.videoSession, colorSpaceManager.ColorSpace.BT2020_HLG);
1360      } else {
1361        this.setColorSpace(this.videoSession, colorSpaceManager.ColorSpace.BT709);
1362      }
1363      // 开始会话工作
1364      await this.videoSession.start();
1365    } catch (error) {
1366      let err = error as BusinessError;
1367      Logger.error(TAG, `videoSessionFlowFn fail : ${JSON.stringify(err)}`);
1368    }
1369  }
1370
1371  async portraitSessionFlowFn(sceneModeIndex?: number): Promise<void> {
1372    try {
1373      // 创建PortraitSession实例
1374      this.portraitSession = this.cameraManager.createSession(camera.SceneMode.PORTRAIT_PHOTO);
1375      // 监听焦距的状态变化
1376      this.onFocusStateChange();
1377      // 监听拍照会话的错误事件
1378      this.onCaptureSessionErrorChange();
1379      // 开始配置会话
1380      this.portraitSession.beginConfig();
1381      // 把CameraInput加入到会话
1382      this.portraitSession.addInput(this.cameraInput);
1383      // 把previewOutput加入到会话
1384      this.portraitSession.addOutput(this.previewOutput);
1385      // 把photoOutPut加入到会话
1386      this.portraitSession.addOutput(this.photoOutPut);
1387      if (this.captureMode === CaptureMode.NEW_DEFERRED_PHOTO) {
1388        if (this.isDeferredImageDeliverySupported(camera.DeferredDeliveryImageType.PHOTO)) {
1389          this.deferImageDeliveryFor(camera.DeferredDeliveryImageType.PHOTO);
1390          this.isDeferredImageDeliveryEnabled(camera.DeferredDeliveryImageType.PHOTO);
1391        }
1392      }
1393
1394      // 提交配置信息
1395      await this.portraitSession.commitConfig();
1396
1397      // 处理变焦条信息
1398      try {
1399        let range: Array<number> = this.portraitSession.getZoomRatioRange();
1400        Logger.info(TAG, `getZoomRatioRange:${range}`);
1401        if (range) {
1402          AppStorage.setOrCreate('zoomRatioMin', range[0]);
1403          AppStorage.setOrCreate('zoomRatioMax', range[1]);
1404        }
1405      } catch (error) {
1406        let err = error as BusinessError;
1407        Logger.error(TAG, `getZoomRatioRange fail: error code ${err.code}`);
1408      }
1409      // 开始会话工作
1410      await this.portraitSession.start();
1411      this.isFocusMode((this.globalContext.getObject('cameraConfig') as CameraConfig).focusMode);
1412      Logger.info(TAG, 'portraitSessionFlowFn success');
1413    } catch (error) {
1414      let err = error as BusinessError;
1415      Logger.error(TAG, `portraitSessionFlowFn fail : ${JSON.stringify(err)}`);
1416    }
1417  }
1418
1419  async nightSessionFlowFn(sceneModeIndex?: number): Promise<void> {
1420    try {
1421      // 创建PortraitSession实例
1422      this.nightSession = this.cameraManager.createSession(camera.SceneMode.NIGHT_PHOTO);
1423      // 监听焦距的状态变化
1424      this.onFocusStateChange();
1425      // 监听拍照会话的错误事件
1426      this.onCaptureSessionErrorChange();
1427      // 开始配置会话
1428      this.nightSession.beginConfig();
1429      // 把CameraInput加入到会话
1430      this.nightSession.addInput(this.cameraInput);
1431      // 把previewOutput加入到会话
1432      this.nightSession.addOutput(this.previewOutput);
1433      // 把photoOutPut加入到会话
1434      this.nightSession.addOutput(this.photoOutPut);
1435      if (this.captureMode === CaptureMode.NEW_DEFERRED_PHOTO) {
1436        if (this.isDeferredImageDeliverySupported(camera.DeferredDeliveryImageType.PHOTO)) {
1437          this.deferImageDeliveryFor(camera.DeferredDeliveryImageType.PHOTO);
1438          this.isDeferredImageDeliveryEnabled(camera.DeferredDeliveryImageType.PHOTO);
1439        }
1440      }
1441
1442      // 提交配置信息
1443      await this.nightSession.commitConfig();
1444
1445      // 处理变焦条信息
1446      try {
1447        let range: Array<number> = this.nightSession.getZoomRatioRange();
1448        Logger.info(TAG, `getZoomRatioRange:${range}`);
1449        if (range) {
1450          AppStorage.setOrCreate('zoomRatioMin', range[0]);
1451          AppStorage.setOrCreate('zoomRatioMax', range[1]);
1452        }
1453      } catch (error) {
1454        let err = error as BusinessError;
1455        Logger.error(TAG, `getZoomRatioRange fail: error code ${err.code}`);
1456      }
1457      // 开始会话工作
1458      await this.nightSession.start();
1459      this.isFocusMode((this.globalContext.getObject('cameraConfig') as CameraConfig).focusMode);
1460      Logger.info(TAG, 'nightSessionFlowFn success');
1461    } catch (error) {
1462      let err = error as BusinessError;
1463      Logger.error(TAG, `nightSessionFlowFn fail : ${JSON.stringify(err)}`);
1464    }
1465  }
1466
1467  setColorSpace(session: camera.PhotoSession | camera.VideoSession, colorSpace: colorSpaceManager.ColorSpace): void {
1468    try {
1469      Logger.info(TAG, `setColorSpace enter`);
1470      let colorSpaces: Array<colorSpaceManager.ColorSpace> = session.getSupportedColorSpaces();
1471      let isSupportedUseColorSpaces = colorSpaces.indexOf(colorSpace);
1472      if (isSupportedUseColorSpaces) {
1473        Logger.info(TAG, `setColorSpace ${colorSpace} start`);
1474        session.setColorSpace(colorSpace);
1475        Logger.info(TAG, `setColorSpace ${colorSpace} success`);
1476        return;
1477      }
1478    } catch (error) {
1479      let err = error as BusinessError;
1480      Logger.error(TAG, `setColorSpace fail : ${JSON.stringify(err)}`);
1481    }
1482  }
1483
1484  setPortraitEffect(): void {
1485    try {
1486      this.portraitSession.setPortraitEffect(camera.PortraitEffect.CIRCLES);
1487    } catch (error) {
1488      let err = error as BusinessError;
1489      Logger.error(TAG, `setPortraitEffect error code: ${err.code}`);
1490    }
1491    this.getPortraitEffect();
1492  }
1493
1494  getPortraitEffect(): void {
1495    try {
1496      let portraitEffect = this.portraitSession.getPortraitEffect();
1497      Logger.info(TAG, `getPortraitEffect portraitEffect: ${portraitEffect}`);
1498    } catch (error) {
1499      let err = error as BusinessError;
1500      Logger.error(TAG, `setPortraitEffect error code: ${err.code}`);
1501    }
1502  }
1503
1504  setMoonCaptureBoostEnable(moonCaptureBoostEnable: Boolean): boolean {
1505    Logger.info(TAG, 'moonCaptureBoostEnable is called.');
1506    let session: camera.CaptureSession = this.getSession();
1507    if (!session) {
1508      return false;
1509    }
1510    try {
1511      session.enableSceneFeature(camera.SceneFeatureType.MOON_CAPTURE_BOOST, moonCaptureBoostEnable);
1512      AppStorage.setOrCreate<boolean>('moonCaptureComponentEnable', moonCaptureBoostEnable);
1513    } catch (error) {
1514      let err = error as BusinessError;
1515      Logger.error(TAG, `setMoonCaptureBoostEnable fail: error code ${err.code}`);
1516      return false;
1517    }
1518    return true;
1519  }
1520
1521  setColorEffect(colorEffect: camera.ColorEffectType): void {
1522    Logger.info(TAG, 'setColorEffect is called.');
1523    if (this.photoSession || this.videoSession || this.portraitSession || this.nightSession) {
1524      let res: Array<camera.ColorEffectType> | undefined = [];
1525      res = this.getSupportedColorEffects();
1526      let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
1527      if (!session) {
1528        return;
1529      }
1530      for (let i = 0; i < res.length; i++) {
1531        if (res[i] === colorEffect) {
1532          Logger.info(TAG, 'setColorEffect success.');
1533          session.setColorEffect(colorEffect);
1534          this.colorEffect = colorEffect;
1535          return;
1536        }
1537      }
1538      Logger.error(TAG, `setColorEffect fail: The colorEffect ${colorEffect} was not found`);
1539    }
1540  }
1541
1542  getColorEffect(): camera.ColorEffectType | undefined {
1543    Logger.info(TAG, 'getColorEffect is called.');
1544    let colorEffect: camera.ColorEffectType | undefined = undefined;
1545    if (this.photoSession || this.videoSession || this.portraitSession || this.nightSession) {
1546      let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
1547      if (!session) {
1548        return colorEffect;
1549      }
1550      try {
1551        colorEffect = session.getColorEffect();
1552      } catch (error) {
1553        let err = error as BusinessError;
1554        Logger.error(TAG, `setColorEffect fail: error code ${err.code}`);
1555      }
1556    }
1557    return colorEffect;
1558  }
1559
1560  getSupportedColorEffects(): Array<camera.ColorEffectType> | undefined {
1561    Logger.info(TAG, 'getSupportedColorEffects is called.');
1562    let res: Array<camera.ColorEffectType> | undefined = [];
1563    if (this.photoSession || this.videoSession || this.portraitSession || this.nightSession) {
1564      let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
1565      if (!session) {
1566        return res;
1567      }
1568      res = session.getSupportedColorEffects();
1569      Logger.info(TAG, `getSupportedColorEffects length: ${res.length}`);
1570    }
1571    return res;
1572  }
1573
1574  /**
1575   * 监听拍照事件
1576   */
1577  photoOutPutCallBack(): void {
1578    // 监听拍照开始
1579    this.photoOutPut.on('captureStart', (err: BusinessError, captureId: number): void => {
1580      Logger.info(TAG, `photoOutPutCallBack captureStart captureId success: ${captureId}`);
1581    });
1582    // 监听拍照帧输出捕获
1583    // 获取时间戳转化异常
1584    this.photoOutPut.on('frameShutter', (err: BusinessError, frameShutterInfo: camera.FrameShutterInfo): void => {
1585      Logger.info(TAG, `photoOutPutCallBack frameShutter captureId: ${frameShutterInfo.captureId}, timestamp: ${frameShutterInfo.timestamp}`);
1586    });
1587    // 监听拍照结束
1588    this.photoOutPut.on('captureEnd', (err: BusinessError, captureEndInfo: camera.CaptureEndInfo): void => {
1589      Logger.info(TAG, `photoOutPutCallBack captureEnd captureId: ${captureEndInfo.captureId}, frameCount: ${captureEndInfo.frameCount}`);
1590    });
1591    this.photoOutPut.on('error', (data: BusinessError): void => {
1592      Logger.info(TAG, `photoOutPut data: ${JSON.stringify(data)}`);
1593    });
1594    this.photoOutPut.on('photoAvailable', (err: BusinessError, photo: camera.Photo): void => {
1595      Logger.info(TAG, 'photoOutPutCallBack photoAvailable 3');
1596      if (err) {
1597        Logger.info(TAG, `photoAvailable error: ${JSON.stringify(err)}.`);
1598        return;
1599      }
1600      let mainImage: image.Image = photo.main;
1601      AppStorage.setOrCreate('mainImage', mainImage);
1602      mainImage.getComponent(image.ComponentType.JPEG, (errCode: BusinessError, component: image.Component): void => {
1603        Logger.debug(TAG, 'getComponent start');
1604        Logger.info(TAG, `err: ${JSON.stringify(errCode)}`);
1605        if (errCode || component === undefined) {
1606          Logger.info(TAG, 'getComponent failed');
1607          return;
1608        }
1609        let buffer: ArrayBuffer;
1610        if (component.byteBuffer) {
1611          buffer = component.byteBuffer;
1612        } else {
1613          Logger.error(TAG, 'component byteBuffer is undefined');
1614        }
1615        this.savePicture(buffer, mainImage);
1616      });
1617      photo.release();
1618    });
1619    this.photoOutPut.on('deferredPhotoProxyAvailable', (err: BusinessError, proxyObj: camera.DeferredPhotoProxy): void => {
1620      if (err) {
1621        Logger.info(TAG, `deferredPhotoProxyAvailable error: ${JSON.stringify(err)}.`);
1622        return;
1623      }
1624      Logger.info(TAG, 'photoOutPutCallBack deferredPhotoProxyAvailable');
1625      proxyObj.getThumbnail().then((thumbnail: image.PixelMap) => {
1626        AppStorage.setOrCreate('proxyThumbnail', thumbnail);
1627      });
1628      this.saveDeferredPhoto(proxyObj);
1629    });
1630  }
1631
1632  /**
1633   * 调用媒体库方式落盘缩略图
1634   */
1635  async saveDeferredPhoto(proxyObj: camera.DeferredPhotoProxy): Promise<void> {
1636    try {
1637      // 创建 photoAsset
1638      let photoHelper = photoAccessHelper.getPhotoAccessHelper(this.globalContext.getCameraSettingContext());
1639      let fileName = Date.now() + '.jpg';
1640      let photoAsset = await photoHelper.createAsset(fileName);
1641      let imgPhotoUri: string = photoAsset.uri;
1642      // 将缩略图代理类传递给媒体库
1643      let mediaRequest: photoAccessHelper.MediaAssetChangeRequest = new photoAccessHelper.MediaAssetChangeRequest(photoAsset);
1644      mediaRequest.addResource(photoAccessHelper.ResourceType.PHOTO_PROXY, proxyObj);
1645      let res = await photoHelper.applyChanges(mediaRequest);
1646      this.handleTakePicture(imgPhotoUri);
1647      Logger.info(TAG, `saveDeferredPhoto res:${res}.`);
1648    } catch (err) {
1649      Logger.error(TAG, `Failed to saveDeferredPhoto. error: ${JSON.stringify(err)}`);
1650    }
1651  }
1652
1653  /**
1654   * 监听预览事件
1655   */
1656  previewOutputCallBack(): void {
1657    Logger.info(TAG, 'previewOutputCallBack is called');
1658    this.previewOutput.on('frameStart', (): void => {
1659      Logger.debug(TAG, 'Preview frame started');
1660    });
1661    this.previewOutput.on('frameEnd', (): void => {
1662      Logger.debug(TAG, 'Preview frame ended');
1663    });
1664    this.previewOutput.on('error', (previewOutputError: BusinessError): void => {
1665      Logger.info(TAG, `Preview output previewOutputError: ${JSON.stringify(previewOutputError)}`);
1666    });
1667  }
1668
1669  /**
1670   * 监听录像事件
1671   */
1672  onVideoOutputChange(): void {
1673    this.videoOutput.on('frameStart', (): void => {
1674      Logger.info(TAG, 'onVideoOutputChange frame started');
1675    });
1676    this.videoOutput.on('frameEnd', (): void => {
1677      Logger.info(TAG, 'onVideoOutputChange frame frameEnd');
1678    });
1679    this.videoOutput.on('error', (videoOutputError: BusinessError) => {
1680      Logger.error(TAG, `onVideoOutputChange fail: ${JSON.stringify(videoOutputError)}`);
1681    });
1682  }
1683
1684  /**
1685   * 镜头状态回调
1686   */
1687  onCameraStatusChange(): void {
1688    Logger.info(TAG, 'onCameraStatusChange is called');
1689    this.cameraManager.on('cameraStatus', async (err: BusinessError, cameraStatusInfo: camera.CameraStatusInfo): Promise<void> => {
1690      Logger.info(TAG, `onCameraStatusChange cameraStatus success, cameraId: ${cameraStatusInfo.camera.cameraId}, status: ${cameraStatusInfo.status}`);
1691    });
1692  }
1693
1694  /**
1695   * 监听CameraInput的错误事件
1696   */
1697  onCameraInputChange(): void {
1698    try {
1699      this.cameraInput.on('error', this.cameras[(this.globalContext.getObject('cameraDeviceIndex') as number)], (cameraInputError: BusinessError): void => {
1700        Logger.info(TAG, `onCameraInputChange cameraInput error code: ${cameraInputError.code}`);
1701      });
1702    } catch (error) {
1703      Logger.info(TAG, `onCameraInputChange cameraInput occur error: error`);
1704    }
1705  }
1706
1707  /**
1708   * 监听焦距的状态变化
1709   */
1710  onFocusStateChange(): void {
1711    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
1712    if (!session) {
1713      return;
1714    }
1715    session.on('focusStateChange', (err: BusinessError, focusState: camera.FocusState): void => {
1716      Logger.info(TAG, `onFocusStateChange captureSession focusStateChange success : ${focusState}`);
1717    });
1718  }
1719
1720  /**
1721   * 监听拍照会话的错误事件
1722   */
1723  onCaptureSessionErrorChange(): void {
1724    let session: camera.PortraitPhotoSession | camera.Session | camera.NightPhotoSession = this.getSession();
1725    if (!session) {
1726      return;
1727    }
1728    session.on('error', (captureSessionError: BusinessError): void => {
1729      Logger.info(TAG, 'onCaptureSessionErrorChange captureSession fail: ' + JSON.stringify(captureSessionError.code));
1730    });
1731
1732  }
1733
1734  setCaptureMode(mode: number): void {
1735    this.captureMode = mode;
1736  }
1737
1738  getCaptureMode(): number {
1739    return this.captureMode;
1740  }
1741
1742  /**
1743   * 查询是否支持二阶段
1744   */
1745  isDeferredImageDeliverySupported(deferredType: camera.DeferredDeliveryImageType): boolean {
1746    let res: boolean = this.photoOutPut.isDeferredImageDeliverySupported(deferredType);
1747    Logger.info(TAG, `isDeferredImageDeliverySupported deferredType:${deferredType} res: ${res}`);
1748    return res;
1749  }
1750
1751  /**
1752   * 查询是否已使能二阶段
1753   */
1754  isDeferredImageDeliveryEnabled(deferredType: camera.DeferredDeliveryImageType): boolean {
1755    let res: boolean = this.photoOutPut.isDeferredImageDeliveryEnabled(deferredType);
1756    Logger.info(TAG, `isDeferredImageDeliveryEnabled deferredType:${deferredType} res: ${res}`);
1757  }
1758
1759  /**
1760   * 使能二阶段
1761   */
1762  deferImageDeliveryFor(deferredType: camera.DeferredDeliveryImageType): void {
1763    Logger.info(TAG, `deferImageDeliveryFor type: ${deferredType}`);
1764    this.photoOutPut.deferImageDelivery(deferredType);
1765  }
1766
1767}
1768
1769export default new CameraService();