• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Dual-Channel Preview (ArkTS)
2
3The camera application controls the camera hardware to implement basic operations such as image display (preview), photo saving (photographing), and video recording. The camera model is developed on the surface model. That is, an application transfers data through the surface. Specifically, it obtains the photo stream through the surface of an **ImageReceiver** object and the preview stream through the surface of an **\<XComponent>** object.
4
5To implement dual-channel preview (there are two preview streams instead of one preview stream plus one photo stream), you must create a **previewOutput** object through the surface of an **ImageReceiver** object. Other processes are the same as those of the photo stream and preview stream.
6
7Read [Camera](../reference/apis/js-apis-camera.md) for the API reference.
8
9## Constraints
10
11- Currently, streams cannot be dynamically added. In other words, you cannot call **addOutput** to add streams without calling **session.stop** first.
12- After an **ImageReceiver** object processes image data obtained, it must release the image buffer so that the buffer queue of the surface properly rotates.
13
14## API Calling Process
15
16The figure below shows the recommended API calling process of the dual-channel preview solution.
17
18![dual-preview-streams-instructions](figures/dual-preview-streams-instructions.png)
19
20## How to Develop
21
221. Import the image module.
23
24   Create a surface for the dual-channel preview stream. In addition to the surface of an **\<XComponent>** object, the surface ID generated by an **ImageReceiver** object is needed. The APIs provided by the image module are also needed.
25
26   ```ts
27   import image from '@ohos.multimedia.image';
28   ```
29
302. Create a surface of the **ImageReceiver** object.
31
32   ```ts
33   async function getImageReceiverSurfaceId(): Promise<string | undefined> {
34     let receiver: image.ImageReceiver = image.createImageReceiver(640, 480, 4, 8);
35     console.info('before ImageReceiver check');
36     let ImageReceiverSurfaceId: string | undefined = undefined;
37     if (receiver !== undefined) {
38       console.info('ImageReceiver is ok');
39       let ImageReceiverSurfaceId: string = await receiver.getReceivingSurfaceId();
40       console.info(`ImageReceived id: ${ImageReceiverSurfaceId}`);
41     } else {
42       console.error('ImageReceiver is not ok');
43     }
44     return ImageReceiverSurfaceId;
45   }
46   ```
47
483. Create a surface of an **\<XComponent>** object.
49
50   For details, see [Camera Preview](camera-preview.md).
51
52   ```ets
53   //xxx.ets
54   // Create an XComponentController object.
55   @Component
56   struct XComponentPage {
57     // Create an XComponentController object.
58     mXComponentController: XComponentController = new XComponentController;
59
60     build() {
61       Flex() {
62         // Create an XComponent object.
63         XComponent({
64           id: '',
65           type: 'surface',
66           libraryname: '',
67           controller: this.mXComponentController
68         })
69           .onLoad(() => {
70             // 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 from previewProfilesArray.
71             this.mXComponentController.setXComponentSurfaceSize({surfaceWidth:1920,surfaceHeight:1080});
72             // Obtain the surface ID.
73             let surfaceId: string = this.mXComponentController.getXComponentSurfaceId();
74           })
75           .width('1920px')
76           .height('1080px')
77       }
78     }
79   }
80   ```
81
824. Implement dual-channel preview.
83
84   Call **createPreviewOutput** to transfer the two surface IDs generated in steps 2 and 3 to the camera service to create two preview streams. Develop other processes based on the normal preview process.
85
86   ```ts
87   import camera from '@ohos.multimedia.camera';
88
89   async function createDualChannelPreview(cameraManager: camera.CameraManager, XComponentSurfaceId: string, receiver: image.ImageReceiver): Promise<void> {
90     let camerasDevices: Array<camera.CameraDevice> = cameraManager.getSupportedCameras(); // Obtain the supported camera devices.
91
92     // Obtain the profile object.
93     let profiles: camera.CameraOutputCapability = cameraManager.getSupportedOutputCapability(camerasDevices[0]); // Obtain the profiles of the camera.
94     let previewProfiles: Array<camera.Profile> = profiles.previewProfiles;
95
96     // Preview stream 1.
97     let previewProfilesObj: camera.Profile = previewProfiles[0];
98
99     // Preview stream 2.
100     let previewProfilesObj2: camera.Profile = previewProfiles[0];
101
102     // Create an output object for preview stream 1.
103     let previewOutput: camera.PreviewOutput = cameraManager.createPreviewOutput(previewProfilesObj, XComponentSurfaceId);
104
105     // Create an output object for preview stream 2.
106     let imageReceiverSurfaceId: string = await receiver.getReceivingSurfaceId();
107     let previewOutput2: camera.PreviewOutput = cameraManager.createPreviewOutput(previewProfilesObj2, imageReceiverSurfaceId);
108
109     // Create a CameraInput object.
110     let cameraInput: camera.CameraInput = cameraManager.createCameraInput(camerasDevices[0]);
111
112     // Open the camera.
113     await cameraInput.open();
114
115     // Create a session.
116     let captureSession: camera.CaptureSession = cameraManager.createCaptureSession();
117
118     // Start configuration for the session.
119     captureSession.beginConfig();
120
121     // Add the CameraInput object to the session.
122     captureSession.addInput(cameraInput);
123
124     // Add preview stream 1 to the session.
125     captureSession.addOutput(previewOutput);
126
127     // Add preview stream 2 to the session.
128     captureSession.addOutput(previewOutput2);
129
130     // Commit the configuration.
131     await captureSession.commitConfig();
132
133     // Start the session.
134     await captureSession.start();
135   }
136   ```
137
1385. Obtain preview images in real time through the **ImageReceiver** object.
139
140   Use the **imageArrival** event of the **ImageReceiver** object to listen for and obtain image data returned by the bottom layer. For details, see [Image](../reference/apis/js-apis-image.md).
141
142   ```ts
143   import { BusinessError } from '@ohos.base';
144
145   function onImageArrival(receiver: image.ImageReceiver): void {
146     receiver.on('imageArrival', () => {
147       receiver.readNextImage((err: BusinessError, nextImage: image.Image) => {
148         if (err || nextImage === undefined) {
149           return;
150         }
151         nextImage.getComponent(image.ComponentType.JPEG, (err: BusinessError, imgComponent: image.Component) => {
152           if (err || imgComponent === undefined) {
153             return;
154           }
155           if (imgComponent.byteBuffer as ArrayBuffer) {
156             // do something...
157           } else {
158             return;
159           }
160         })
161       })
162     })
163   }
164   ```
165