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