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