• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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
16import camera from '@ohos.multimedia.camera'
17import deviceInfo from '@ohos.deviceInfo'
18import fileio from '@ohos.fileio'
19import image from '@ohos.multimedia.image'
20import media from '@ohos.multimedia.media'
21import mediaLibrary from '@ohos.multimedia.mediaLibrary'
22import Logger from '../model/Logger'
23import MediaUtils from '../model/MediaUtils'
24
25const CameraMode = {
26  MODE_PHOTO: 0, // 拍照模式
27  MODE_VIDEO: 1 // 录像模式
28}
29
30const CameraSize = {
31  WIDTH: 1920,
32  HEIGHT: 1080
33}
34
35export default class CameraService {
36  private tag: string = 'CameraService'
37  private context: any = undefined
38  private mediaUtil: MediaUtils = undefined
39  private cameraManager: camera.CameraManager = undefined
40  private cameras: Array<camera.CameraDevice> = undefined
41  private cameraId: string = ''
42  private cameraInput: camera.CameraInput = undefined
43  private previewOutput: camera.PreviewOutput = undefined
44  private photoOutPut: camera.PhotoOutput = undefined
45  private captureSession: camera.CaptureSession = undefined
46  private mReceiver: image.ImageReceiver = undefined
47  private photoUri: string = ''
48  private fileAsset: mediaLibrary.FileAsset = undefined
49  private fd: number = -1
50  private curMode = CameraMode.MODE_PHOTO
51  private videoRecorder: media.VideoRecorder = undefined
52  private videoOutput: camera.VideoOutput = undefined
53  private handleTakePicture: (photoUri: string) => void = undefined
54  private cameraOutputCapability: camera.CameraOutputCapability = undefined
55  private videoConfig: any = {
56    audioSourceType: 1,
57    videoSourceType: 0,
58    profile: {
59      audioBitrate: 48000,
60      audioChannels: 2,
61      audioCodec: 'audio/mp4v-es',
62      audioSampleRate: 48000,
63      durationTime: 1000,
64      fileFormat: 'mp4',
65      videoBitrate: 48000,
66      videoCodec: 'video/mp4v-es',
67      videoFrameWidth: 640,
68      videoFrameHeight: 480,
69      videoFrameRate: 30
70    },
71    url: '',
72    orientationHint: 0,
73    location: {
74      latitude: 30, longitude: 130
75    },
76    maxSize: 10000,
77    maxDuration: 10000
78  }
79
80  constructor(context: any) {
81    this.context = context
82    this.mediaUtil = MediaUtils.getInstance(context)
83    this.mReceiver = image.createImageReceiver(CameraSize.WIDTH, CameraSize.HEIGHT, 4, 8)
84    Logger.info(this.tag, 'createImageReceiver')
85    this.mReceiver.on('imageArrival', () => {
86      Logger.info(this.tag, 'imageArrival')
87      this.mReceiver.readNextImage((err, image) => {
88        Logger.info(this.tag, 'readNextImage')
89        if (err || image === undefined) {
90          Logger.error(this.tag, 'failed to get valid image')
91          return
92        }
93        image.getComponent(4, (errMsg, img) => {
94          Logger.info(this.tag, 'getComponent')
95          if (errMsg || img === undefined) {
96            Logger.info(this.tag, 'failed to get valid buffer')
97            return
98          }
99          let buffer = new ArrayBuffer(4096)
100          if (img.byteBuffer) {
101            buffer = img.byteBuffer
102          } else {
103            Logger.error(this.tag, 'img.byteBuffer is undefined')
104          }
105          this.savePicture(buffer, image)
106        })
107      })
108    })
109  }
110
111  async savePicture(buffer: ArrayBuffer, img: image.Image) {
112    Logger.info(this.tag, 'savePicture')
113    this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.IMAGE)
114    this.photoUri = this.fileAsset.uri
115    Logger.info(this.tag, `this.photoUri = ${this.photoUri}`)
116    this.fd = await this.mediaUtil.getFdPath(this.fileAsset)
117    Logger.info(this.tag, `this.fd = ${this.fd}`)
118    await fileio.write(this.fd, buffer)
119    await this.fileAsset.close(this.fd)
120    await img.release()
121    Logger.info(this.tag, 'save image done')
122    if (this.handleTakePicture) {
123      this.handleTakePicture(this.photoUri)
124    }
125  }
126
127  async initCamera(surfaceId: string) {
128    Logger.info(this.tag, 'initCamera')
129    await this.releaseCamera()
130    Logger.info(this.tag, `deviceInfo.deviceType = ${deviceInfo.deviceType}`)
131    if (deviceInfo.deviceType === 'default') {
132      this.videoConfig.videoSourceType = 1
133    } else {
134      this.videoConfig.videoSourceType = 0
135    }
136    this.cameraManager = await camera.getCameraManager(this.context)
137    Logger.info(this.tag, 'getCameraManager')
138    this.cameras = await this.cameraManager.getSupportedCameras()
139    Logger.info(this.tag, `get cameras ${this.cameras.length}`)
140    if (this.cameras.length === 0) {
141      Logger.info(this.tag, 'cannot get cameras')
142      return
143    }
144
145    let cameraDevice = this.cameras[0]
146    this.cameraInput = await this.cameraManager.createCameraInput(cameraDevice)
147    this.cameraInput.open()
148    Logger.info(this.tag, 'createCameraInput')
149    this.cameraOutputCapability = await this.cameraManager.getSupportedOutputCapability(cameraDevice)
150    let previewProfile = this.cameraOutputCapability.previewProfiles[0]
151    this.previewOutput = await this.cameraManager.createPreviewOutput(previewProfile, surfaceId)
152    Logger.info(this.tag, 'createPreviewOutput')
153    let mSurfaceId = await this.mReceiver.getReceivingSurfaceId()
154    let photoProfile = this.cameraOutputCapability.photoProfiles[0]
155    this.photoOutPut = await this.cameraManager.createPhotoOutput(photoProfile, mSurfaceId)
156    this.captureSession = await this.cameraManager.createCaptureSession()
157    Logger.info(this.tag, 'createCaptureSession')
158    await this.captureSession.beginConfig()
159    Logger.info(this.tag, 'beginConfig')
160    await this.captureSession.addInput(this.cameraInput)
161    await this.captureSession.addOutput(this.previewOutput)
162    await this.captureSession.addOutput(this.photoOutPut)
163    await this.captureSession.commitConfig()
164    await this.captureSession.start()
165    Logger.info(this.tag, 'captureSession start')
166  }
167
168  setTakePictureCallback(callback) {
169    this.handleTakePicture = callback
170  }
171
172  async takePicture() {
173    Logger.info(this.tag, 'takePicture')
174    if (this.curMode === CameraMode.MODE_VIDEO) {
175      this.curMode = CameraMode.MODE_PHOTO
176    }
177    let photoSettings = {
178      rotation: camera.ImageRotation.ROTATION_0,
179      quality: camera.QualityLevel.QUALITY_LEVEL_MEDIUM,
180      location: { // 位置信息,经纬度
181        latitude: 12.9698,
182        longitude: 77.7500,
183        altitude: 1000
184      },
185      mirror: false
186    }
187    await this.photoOutPut.capture(photoSettings)
188    Logger.info(this.tag, 'takePicture done')
189    AppStorage.Set('isRefresh', true)
190  }
191
192  async startVideo() {
193    Logger.info(this.tag, 'startVideo begin')
194    await this.captureSession.stop()
195    await this.captureSession.beginConfig()
196    if (this.curMode === CameraMode.MODE_PHOTO) {
197      this.curMode = CameraMode.MODE_VIDEO
198      if (this.photoOutPut) {
199        await this.captureSession.removeOutput(this.photoOutPut)
200        this.photoOutPut.release()
201      }
202    } else {
203      if (this.videoOutput) {
204        await this.captureSession.removeOutput(this.videoOutput)
205      }
206    }
207    if (this.videoOutput) {
208      await this.captureSession.removeOutput(this.videoOutput)
209      await this.videoOutput.release()
210    }
211    this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.VIDEO)
212    this.fd = await this.mediaUtil.getFdPath(this.fileAsset)
213    this.videoRecorder = await media.createVideoRecorder()
214    this.videoConfig.url = `fd://${this.fd}`
215    await this.videoRecorder.prepare(this.videoConfig)
216    let videoId = await this.videoRecorder.getInputSurface()
217    let videoProfile = this.cameraOutputCapability.videoProfiles[0];
218    this.videoOutput = await this.cameraManager.createVideoOutput(videoProfile, videoId)
219    await this.captureSession.addOutput(this.videoOutput)
220    await this.captureSession.commitConfig()
221    await this.captureSession.start()
222    await this.videoOutput.start()
223    await this.videoRecorder.start()
224    Logger.info(this.tag, 'startVideo end')
225  }
226
227  async stopVideo() {
228    Logger.info(this.tag, 'stopVideo called')
229    await this.videoRecorder.stop()
230    await this.videoOutput.stop()
231    await this.videoRecorder.release()
232    await this.fileAsset.close(this.fd)
233  }
234
235  async releaseCamera() {
236    Logger.info(this.tag, 'releaseCamera')
237    if (this.cameraInput) {
238      await this.cameraInput.close()
239    }
240    if (this.previewOutput) {
241      await this.previewOutput.release()
242    }
243    if (this.photoOutPut) {
244      await this.photoOutPut.release()
245    }
246    if (this.videoOutput) {
247      await this.videoOutput.release()
248    }
249    if (this.captureSession) {
250      await this.captureSession.release()
251    }
252  }
253}