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