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}