• 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.Camera> = 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 videoConfig: any = {
55    audioSourceType: 1,
56    videoSourceType: 0,
57    profile: {
58      audioBitrate: 48000,
59      audioChannels: 2,
60      audioCodec: 'audio/mp4v-es',
61      audioSampleRate: 48000,
62      durationTime: 1000,
63      fileFormat: 'mp4',
64      videoBitrate: 48000,
65      videoCodec: 'video/mp4v-es',
66      videoFrameWidth: 640,
67      videoFrameHeight: 480,
68      videoFrameRate: 30
69    },
70    url: '',
71    orientationHint: 0,
72    location: {
73      latitude: 30, longitude: 130
74    },
75    maxSize: 10000,
76    maxDuration: 10000
77  }
78
79  constructor(context: any) {
80    this.context = context
81    this.mediaUtil = MediaUtils.getInstance(context)
82    this.mReceiver = image.createImageReceiver(CameraSize.WIDTH, CameraSize.HEIGHT, 4, 8)
83    Logger.info(this.tag, 'createImageReceiver')
84    this.mReceiver.on('imageArrival', () => {
85      Logger.info(this.tag, 'imageArrival')
86      this.mReceiver.readNextImage((err, image) => {
87        Logger.info(this.tag, 'readNextImage')
88        if (err || image === undefined) {
89          Logger.error(this.tag, 'failed to get valid image')
90          return
91        }
92        image.getComponent(4, (errMsg, img) => {
93          Logger.info(this.tag, 'getComponent')
94          if (errMsg || img === undefined) {
95            Logger.info(this.tag, 'failed to get valid buffer')
96            return
97          }
98          let buffer = new ArrayBuffer(4096)
99          if (img.byteBuffer) {
100            buffer = img.byteBuffer
101          } else {
102            Logger.error(this.tag, 'img.byteBuffer is undefined')
103          }
104          this.savePicture(buffer, image)
105        })
106      })
107    })
108  }
109
110  async savePicture(buffer: ArrayBuffer, img: image.Image) {
111    Logger.info(this.tag, 'savePicture')
112    this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.IMAGE)
113    this.photoUri = this.fileAsset.uri
114    Logger.info(this.tag, `this.photoUri = ${this.photoUri}`)
115    this.fd = await this.mediaUtil.getFdPath(this.fileAsset)
116    Logger.info(this.tag, `this.fd = ${this.fd}`)
117    await fileio.write(this.fd, buffer)
118    await this.fileAsset.close(this.fd)
119    await img.release()
120    Logger.info(this.tag, 'save image done')
121    if (this.handleTakePicture) {
122      this.handleTakePicture(this.photoUri)
123    }
124  }
125
126  async initCamera(surfaceId: number) {
127    Logger.info(this.tag, 'initCamera')
128    if (this.curMode === CameraMode.MODE_VIDEO) {
129      await this.releaseCamera()
130    }
131    Logger.info(this.tag, `deviceInfo.deviceType = ${deviceInfo.deviceType}`)
132    if (deviceInfo.deviceType === 'default') {
133      this.videoConfig.videoSourceType = 1
134    } else {
135      this.videoConfig.videoSourceType = 0
136    }
137    this.cameraManager = await camera.getCameraManager(this.context)
138    Logger.info(this.tag, 'getCameraManager')
139    this.cameras = await this.cameraManager.getCameras()
140    Logger.info(this.tag, `get cameras ${this.cameras.length}`)
141    if (this.cameras.length === 0) {
142      Logger.info(this.tag, 'cannot get cameras')
143      return
144    }
145    this.cameraId = this.cameras[0].cameraId
146    this.cameraInput = await this.cameraManager.createCameraInput(this.cameraId)
147    Logger.info(this.tag, 'createCameraInput')
148    this.previewOutput = await camera.createPreviewOutput(surfaceId.toString())
149    Logger.info(this.tag, 'createPreviewOutput')
150    let mSurfaceId = await this.mReceiver.getReceivingSurfaceId()
151    this.photoOutPut = await camera.createPhotoOutput(mSurfaceId)
152    this.captureSession = await camera.createCaptureSession(this.context)
153    Logger.info(this.tag, 'createCaptureSession')
154    await this.captureSession.beginConfig()
155    Logger.info(this.tag, 'beginConfig')
156    await this.captureSession.addInput(this.cameraInput)
157    await this.captureSession.addOutput(this.previewOutput)
158    await this.captureSession.addOutput(this.photoOutPut)
159    await this.captureSession.commitConfig()
160    await this.captureSession.start()
161    Logger.info(this.tag, 'captureSession start')
162  }
163
164  setTakePictureCallback(callback) {
165    this.handleTakePicture = callback
166  }
167
168  async takePicture() {
169    Logger.info(this.tag, 'takePicture')
170    if (this.curMode === CameraMode.MODE_VIDEO) {
171      this.curMode = CameraMode.MODE_PHOTO
172    }
173    let photoSettings = {
174      rotation: camera.ImageRotation.ROTATION_0,
175      quality: camera.QualityLevel.QUALITY_LEVEL_MEDIUM,
176      location: { // 位置信息,经纬度
177        latitude: 12.9698,
178        longitude: 77.7500,
179        altitude: 1000
180      },
181      mirror: false
182    }
183    await this.photoOutPut.capture(photoSettings)
184    Logger.info(this.tag, 'takePicture done')
185  }
186
187  async startVideo() {
188    Logger.info(this.tag, 'startVideo begin')
189    await this.captureSession.stop()
190    await this.captureSession.beginConfig()
191    if (this.curMode === CameraMode.MODE_PHOTO) {
192      this.curMode = CameraMode.MODE_VIDEO
193      if (this.photoOutPut) {
194        await this.captureSession.removeOutput(this.photoOutPut)
195        this.photoOutPut.release()
196      }
197    } else {
198      if (this.videoOutput) {
199        await this.captureSession.removeOutput(this.videoOutput)
200      }
201    }
202    if (this.videoOutput) {
203      await this.captureSession.removeOutput(this.videoOutput)
204      await this.videoOutput.release()
205    }
206    this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.VIDEO)
207    this.fd = await this.mediaUtil.getFdPath(this.fileAsset)
208    this.videoRecorder = await media.createVideoRecorder()
209    this.videoConfig.url = `fd://${this.fd}`
210    await this.videoRecorder.prepare(this.videoConfig)
211    let videoId = await this.videoRecorder.getInputSurface()
212    this.videoOutput = await camera.createVideoOutput(videoId)
213    await this.captureSession.addOutput(this.videoOutput)
214    await this.captureSession.commitConfig()
215    await this.captureSession.start()
216    await this.videoOutput.start()
217    await this.videoRecorder.start()
218    Logger.info(this.tag, 'startVideo end')
219  }
220
221  async stopVideo() {
222    Logger.info(this.tag, 'stopVideo called')
223    await this.videoRecorder.stop()
224    await this.videoOutput.stop()
225    await this.videoRecorder.release()
226    await this.fileAsset.close(this.fd)
227  }
228
229  async releaseCamera() {
230    Logger.info(this.tag, 'releaseCamera')
231    if (this.cameraInput) {
232      await this.cameraInput.release()
233    }
234    if (this.previewOutput) {
235      await this.previewOutput.release()
236    }
237    if (this.photoOutPut) {
238      await this.photoOutPut.release()
239    }
240    if (this.videoOutput) {
241      await this.videoOutput.release()
242    }
243    if (this.captureSession) {
244      await this.captureSession.release()
245    }
246  }
247}