camera.md 16.2 KB
Newer Older
W
wusongqing 已提交
1 2 3 4
# Camera Development

## When to Use

5 6 7 8 9 10 11
With the APIs provided by the **Camera** module, you can access and operate camera devices and develop new functions. Common operations include preview, photographing, and video recording. You can also implement flash control, exposure time control, focus mode control, zooming control, and many others.

Before calling camera APIs, be familiar with the following concepts:

- **Static camera capabilities**: A series of parameters used to describe inherent capabilities of a camera, such as orientation and supported resolution.
- **Physical camera**: An independent camera device. The physical camera ID is a string that uniquely identifies a physical camera.
- **Asynchronous operation**: To prevent the UI thread from being blocked, most **Camera** calls are asynchronous. Each API provides the callback and promise functions.
W
wusongqing 已提交
12 13 14 15 16 17 18 19 20

## How to Develop

### Available APIs

For details about the APIs, see [Camera Management](../reference/apis/js-apis-camera.md).

### Full-Process Scenario

21 22 23 24 25 26 27 28 29 30 31 32 33
The full process includes applying for permissions, creating an instance, setting parameters, managing sessions, taking photos, recording videos, and releasing resources.

#### Applying for Permissions

You must apply for the permission for your application to access the camera device and other functions. The following table lists camera-related permissions.

| Permission| Attribute Value                    |
| -------- | ------------------------------ |
| Camera| ohos.permission.CAMERA         |
| Call recording| ohos.permission.MICROPHONE     |
| Storage| ohos.permission.WRITE_MEDIA    |
| Read| ohos.permission.READ_MEDIA     |
| Location| ohos.permission.MEDIA_LOCATION |
W
wusongqing 已提交
34

35
The code snippet is as follows:
W
wusongqing 已提交
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50
```typescript
const PERMISSIONS: Array<string> = [
    'ohos.permission.CAMERA',
    'ohos.permission.MICROPHONE',
    'ohos.permission.MEDIA_LOCATION',
    'ohos.permission.READ_MEDIA',
    'ohos.permission.WRITE_MEDIA'
]

function applyPermission() {
        console.info('[permission] get permission');
        globalThis.abilityContext.requestPermissionFromUser(PERMISSIONS)
    }
```
W
wusongqing 已提交
51 52 53

#### Creating an Instance

54 55 56
You must create an independent **CameraManager** instance before performing camera operations. If this operation fails, the camera may be occupied or unusable. If the camera is occupied, wait until it is released. You can call **getSupportedCameras()** to obtain the list of cameras supported by the current device. The list stores all camera IDs of the current device. If the list is not empty, each ID in the list can be used to create an independent camera instance. If the list is empty, no camera is available for the current device and subsequent operations cannot be performed. The camera has preview, shooting, video recording, and metadata streams. You can use **getSupportedOutputCapability()** to obtain the output stream capabilities of the camera and configure them in the **profile** field in **CameraOutputCapability**. The procedure for creating a **CameraManager** instance is as follows:

```typescript
W
wusongqing 已提交
57 58 59 60 61
import camera from '@ohos.multimedia.camera'
import image from '@ohos.multimedia.image'
import media from '@ohos.multimedia.media'

// Create a CameraManager object.
62 63 64 65 66
context: any = getContext(this)
let cameraManager = await camera.getCameraManager(this.context)
if (!cameraManager) {
    console.error('Failed to get the CameraManager instance');
}
W
wusongqing 已提交
67 68

// Obtain the camera list.
69 70 71 72
let cameraArray = await cameraManager.getSupportedCameras()
if (!cameraArray) {
    console.error('Failed to get the cameras');
}
W
wusongqing 已提交
73

74 75 76 77 78
for (let index = 0; index < cameraArray.length; index++) {
    console.log('cameraId : ' + cameraArray[index].cameraId)                          // Obtain the camera ID.
    console.log('cameraPosition : ' + cameraArray[index].cameraPosition)              // Obtain the camera position.
    console.log('cameraType : ' + cameraArray[index].cameraType)                      // Obtain the camera type.
    console.log('connectionType : ' + cameraArray[index].connectionType)              // Obtain the camera connection type.
W
wusongqing 已提交
79 80 81
}

// Create a camera input stream.
82 83
let cameraInput = await cameraManager.createCameraInput(cameraArray[0])

S
songchunpeng 已提交
84 85 86
// Open camera
await cameraInput.open();

87 88 89 90 91 92 93
// Obtain the output stream capabilities supported by the camera.
let cameraOutputCap = await cameraManager.getSupportedOutputCapability(cameraArray[0]);
if (!cameraOutputCap) {
    console.error("outputCapability outputCapability == null || undefined")
} else {
    console.info("outputCapability: " + JSON.stringify(cameraOutputCap));
}
W
wusongqing 已提交
94

95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
let previewProfilesArray = cameraOutputCap.GetPreviewProfiles();
if (!previewProfilesArray) {
    console.error("createOutput previewProfilesArray == null || undefined")
} 

let photoProfilesArray = cameraOutputCap.GetPhotoProfiles();
if (!photoProfilesArray) {
    console.error("createOutput photoProfilesArray == null || undefined")
} 

let videoProfilesArray = cameraOutputCap.GetVideoProfiles();
if (!videoProfilesArray) {
    console.error("createOutput videoProfilesArray == null || undefined")
} 

let metadataObjectTypesArray = cameraOutputCap.GetSupportedMetadataObjectType();
if (!metadataObjectTypesArray) {
    console.error("createOutput metadataObjectTypesArray == null || undefined")
}

// Create a preview stream. For details about the surfaceId parameter, see the XComponent section. The preview stream is the surface provided by the XComponent.
let previewOutput = await cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId)
if (!previewOutput) {
    console.error("Failed to create the PreviewOutput instance.")
}
W
wusongqing 已提交
120

121
// Create an ImageReceiver object and set photo parameters. The resolution is set based on the photographing resolutions supported by the current device, which are obtained by photoProfilesArray.
W
wusongqing 已提交
122 123 124 125
let imageReceiver = await image.createImageReceiver(1920, 1080, 4, 8)
// Obtain the surface ID for displaying the photos.
let photoSurfaceId = await imageReceiver.getReceivingSurfaceId()
// Create a photographing output stream.
126 127 128 129 130
let photoOutput = await cameraManager.createPhotoOutput(photoProfilesArray[0], photoSurfaceId)
if (!photoOutput) {
    console.error('Failed to create the PhotoOutput instance.');
    return;
}
W
wusongqing 已提交
131 132 133

// Define video recording parameters.
let videoConfig = {
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
    audioSourceType: 1,
    videoSourceType: 1,
    profile: {
        audioBitrate: 48000,
        audioChannels: 2,
        audioCodec: 'audio/mp4v-es',
        audioSampleRate: 48000,
        durationTime: 1000,
        fileFormat: 'mp4',
        videoBitrate: 48000,
        videoCodec: 'video/mp4v-es',
        videoFrameWidth: 640,
        videoFrameHeight: 480,
        videoFrameRate: 30
    },
    url: 'file:///data/media/01.mp4',
    orientationHint: 0,
    maxSize: 100,
    maxDuration: 500,
    rotation: 0
W
wusongqing 已提交
154 155 156 157
}

// Create a video recording output stream.
let videoRecorder
158
media.createVideoRecorder().then((recorder) => {
W
wusongqing 已提交
159 160 161 162
    console.log('createVideoRecorder called')
    videoRecorder = recorder
})
// Set video recording parameters.
163
videoRecorder.prepare(videoConfig)
W
wusongqing 已提交
164
// Obtain the surface ID for video recording.
165 166
let videoSurfaceId
videoRecorder.getInputSurface().then((id) => {
W
wusongqing 已提交
167 168 169
    console.log('getInputSurface called')
    videoSurfaceId = id
})
170

W
wusongqing 已提交
171
// Create a VideoOutput object.
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
let videoOutput = await cameraManager.createVideoOutput(videoProfilesArray[0], videoSurfaceId)
if (!videoOutput) {
    console.error('Failed to create the videoOutput instance.');
    return;
}
```
Surfaces must be created in advance for the preview, shooting, and video recording stream. The preview stream is the surface provided by the **XComponent**, the shooting stream is the surface provided by **ImageReceiver**, and the video recording stream is the surface provided by **VideoRecorder**.

**XComponent**

```typescript
mXComponentController: XComponentController = new XComponentController                   // Create an XComponentController.

build() {
    Flex() {
        XComponent({                                                                     // Create an XComponent.
            id: '',
            type: 'surface',
            libraryname: '',
            controller: this.mXComponentController
        })
        .onload(() => {                                                                  // Set the onload callback.
            // Set the surface width and height (1920 x 1080). For details about how to set the preview size, see the preview resolutions supported by the current device, which are obtained by previewProfilesArray.
            this.mXComponentController.setXComponentSurfaceSize({surfaceWidth:1920,surfaceHeight:1080})
            // Obtain the surface ID.
            globalThis.surfaceId = mXComponentController.getXComponentSurfaceId()
        })
        .width('1920px')                                                                 // Set the width of the XComponent.
        .height('1080px')                                                                // Set the height of the XComponent.
W
wusongqing 已提交
201
    }
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
}
```

**ImageReceiver**

```typescript
function getImageReceiverSurfaceId() {
    let receiver = image.createImageReceiver(640, 480, 4, 8)
    console.log(TAG + 'before ImageReceiver check')
    if (receiver !== undefined) {
      console.log('ImageReceiver is ok')
      surfaceId1 = receiver.getReceivingSurfaceId()
      console.log('ImageReceived id: ' + JSON.stringify(surfaceId1))
    } else {
      console.log('ImageReceiver is not ok')
    }
  }
```

**VideoRecorder**

```typescript
function getVideoRecorderSurface() {
        await getFd('CameraManager.mp4');
        mVideoConfig.url = mFdPath;
        media.createVideoRecorder((err, recorder) => {
            console.info('Entering create video receiver')
            mVideoRecorder = recorder
            console.info('videoRecorder is :' + JSON.stringify(mVideoRecorder))
            console.info('videoRecorder.prepare called.')
            mVideoRecorder.prepare(mVideoConfig, (err) => {
                console.info('videoRecorder.prepare success.')
                mVideoRecorder.getInputSurface((err, id) => {
                    console.info('getInputSurface called')
                    mVideoSurface = id
                    console.info('getInputSurface surfaceId: ' + JSON.stringify(mVideoSurface))
                })
            })
        })
    }
```

#### Managing Sessions

##### Creating a Session

```typescript
// Create a session.
let captureSession = await camera.createCaptureSession()
if (!captureSession) {
    console.error('Failed to create the CaptureSession instance.');
    return;
}
console.log('Callback returned with the CaptureSession instance.' + session);

// Start configuration for the session.
await captureSession.beginConfig()

// Add the camera input stream to the session.
await captureSession.addInput(cameraInput)

// Add the preview input stream to the session.
await captureSession.addOutput(previewOutput)

// Add the photographing output stream to the session.
await captureSession.addOutput(photoOutput)

// Commit the session configuration.
await captureSession.commitConfig()

// Start the session.
await captureSession.start().then(() => {
    console.log('Promise returned to indicate the session start success.');
})
```
W
wusongqing 已提交
277

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
##### Switching a Session

```typescript
// Stop the session.
await captureSession.stop()

// Start configuration for the session.
await captureSession.beginConfig()

// Remove the photographing output stream from the session.
await captureSession.removeOutput(photoOutput)

// Add a video recording output stream to the session.
await captureSession.addOutput(videoOutput)

// Commit the session configuration.
await captureSession.commitConfig()

// Start the session.
await captureSession.start().then(() => {
    console.log('Promise returned to indicate the session start success.');
})
W
wusongqing 已提交
300 301 302 303
```

#### Setting Parameters

304
```typescript
W
wusongqing 已提交
305
// Check whether the camera has flash.
306 307 308 309 310 311 312
let flashStatus = await captureSession.hasFlash()
if (!flashStatus) {
    console.error('Failed to check whether the device has the flash mode.');
}
console.log('Promise returned with the flash light support status:' + flashStatus);

if (flashStatus) {
W
wusongqing 已提交
313 314
    // Check whether the auto flash mode is supported.
    let flashModeStatus
315
    captureSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO, async (err, status) => {
W
wusongqing 已提交
316 317 318 319 320 321 322 323 324
        if (err) {
            console.error('Failed to check whether the flash mode is supported. ${err.message}');
            return;
        }
        console.log('Callback returned with the flash mode support status: ' + status);
        flashModeStatus = status
    })
    if(flashModeStatus) {
        // Set the flash mode to auto.
325
        captureSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO, async (err) => {
W
wusongqing 已提交
326 327 328 329 330 331 332 333 334 335 336
            if (err) {
                console.error('Failed to set the flash mode  ${err.message}');
                return;
            }
            console.log('Callback returned with the successful execution of setFlashMode.');
        })
    }
}

// Check whether the continuous auto focus is supported.
let focusModeStatus
337
captureSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO, async (err, status) => {
W
wusongqing 已提交
338 339 340 341 342 343 344
    if (err) {
        console.error('Failed to check whether the focus mode is supported. ${err.message}');
        return;
    }
    console.log('Callback returned with the focus mode support status: ' + status);
    focusModeStatus = status
})
345
if (focusModeStatus) {
W
wusongqing 已提交
346
    // Set the focus mode to continuous auto focus.
347
    captureSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO, async (err) => {
W
wusongqing 已提交
348 349 350 351 352 353 354 355 356
        if (err) {
            console.error('Failed to set the focus mode  ${err.message}');
            return;
        }
        console.log('Callback returned with the successful execution of setFocusMode.');
    })
}

// Obtain the zoom ratio range supported by the camera.
357 358 359 360 361
let zoomRatioRange = await captureSession.getZoomRatioRange()
if (!zoomRatioRange) {
    console.error('Failed to get the zoom ratio range.');
    return;
}
W
wusongqing 已提交
362 363

// Set a zoom ratio.
364
captureSession.setZoomRatio(zoomRatioRange[0], async (err) => {
W
wusongqing 已提交
365 366 367 368 369 370 371 372 373 374
    if (err) {
        console.error('Failed to set the zoom ratio value ${err.message}');
        return;
    }
    console.log('Callback returned with the successful execution of setZoomRatio.');
})
```

#### Taking Photos

375
```typescript
W
wusongqing 已提交
376
let settings = {
377 378
    quality: camera.QualityLevel.QUALITY_LEVEL_HIGH,                                     // Set the image quality to high.
    rotation: camera.ImageRotation.ROTATION_0                                            // Set the image rotation angle to 0.
W
wusongqing 已提交
379 380
}
// Use the current photographing settings to take photos.
381
photoOutput.capture(settings, async (err) => {
W
wusongqing 已提交
382 383 384 385 386 387 388 389 390 391
    if (err) {
        console.error('Failed to capture the photo ${err.message}');
        return;
    }
    console.log('Callback invoked to indicate the photo capture request success.');
});
```

#### Recording Videos

392
```typescript
W
wusongqing 已提交
393
// Start the video recording output stream.
394
videoOutput.start(async (err) => {
W
wusongqing 已提交
395 396 397 398 399 400 401 402
    if (err) {
        console.error('Failed to start the video output ${err.message}');
        return;
    }
    console.log('Callback invoked to indicate the video output start success.');
});

// Start video recording.
403
videoRecorder.start().then(() => {
W
wusongqing 已提交
404 405 406 407
    console.info('videoRecorder start success');
}

// Stop video recording.
408
videoRecorder.stop().then(() => {
W
wusongqing 已提交
409 410 411 412
    console.info('stop success');
}

// Stop the video recording output stream.
413
videoOutput.stop((err) => {
W
wusongqing 已提交
414 415 416 417 418 419 420 421
    if (err) {
        console.error('Failed to stop the video output ${err.message}');
        return;
    }
    console.log('Callback invoked to indicate the video output stop success.');
});
```

422 423
For details about the APIs used for saving photos, see [Image Processing](image.md#using-imagereceiver).

W
wusongqing 已提交
424 425
#### Releasing Resources

426
```typescript
427
// Stop the session.
428 429
captureSession.stop()

W
wusongqing 已提交
430
// Release the camera input stream.
431 432
cameraInput.release()

W
wusongqing 已提交
433
// Release the preview output stream.
434 435
previewOutput.release()

W
wusongqing 已提交
436
// Release the photographing output stream.
437 438
photoOutput.release()

W
wusongqing 已提交
439
// Release the video recording output stream.
440 441
videoOutput.release()

W
wusongqing 已提交
442
// Release the session.
443
captureSession.release()
W
wusongqing 已提交
444

445 446 447
// Set the session to null.
captureSession = null
```
W
wusongqing 已提交
448

449
## Process Flowchart
W
wusongqing 已提交
450

451 452
The following figure shows the process of using the camera.
![camera_framework process](figures/camera_framework_process.jpg)