1# Using AVScreenCapture to Capture Screens and Obtain Streams (C/C++)
2
3Screen capture is mainly used to record the main screen.
4
5You can call the C APIs of the [AVScreenCapture](media-kit-intro.md#avscreencapture) module to record the screen and collect audio and video source data output by the device and microphone. When developing a live streaming or an office application, you can call the APIs to obtain original audio and video streams and transfer the streams to other modules for processing. In this way, the home screen can be shared during live streaming.
6
7The AVScreenCapture, Window, and Graphics modules together implement the entire video capture process.
8
9By default, the main screen is captured, and the Graphics module generates the screen capture frame data based on the main screen and places the data to the display data buffer. The player framework obtains the data from the buffer for processing.
10
11The full screen capture process involves creating an AVScreenCapture instance, configuring audio and video capture parameters, starting and stopping screen capture, and releasing resources.
12
13If you are in a call when screen capture starts or a call is coming during screen capture, screen capture automatically stops, and the **OH_SCREEN_CAPTURE_STATE_STOPPED_BY_CALL** status is reported.
14
15Screen capture automatically stops upon system user switching, and **OH_SCREEN_CAPTURE_STATE_STOPPED_BY_USER_SWITCHES** is reported.
16
17This topic describes how to use the AVScreenCapture APIs to carry out one-time screen capture. For details about the API reference, see [AVScreenCapture](../../reference/apis-media-kit/_a_v_screen_capture.md).
18
19If microphone data collection is configured, configure the permission ohos.permission.MICROPHONE and request a continuous task. For details, see [Requesting User Authorization](../../security/AccessToken/request-user-authorization.md) and [Continuous Task](../../task-management/continuous-task.md).
20
21## How to Develop
22
23After an AVScreenCapture instance is created, different APIs can be called to switch the AVScreenCapture to different states and trigger the required behavior.
24
25If an API is called when the AVScreenCapture is not in the given state, the system may throw an exception or generate other undefined behavior. Therefore, you are advised to check the AVScreenCapture state before triggering state transition.
26
27**Linking the Dynamic Library in the CMake Script**
28
29```c++
30target_link_libraries(entry PUBLIC libnative_avscreen_capture.so libnative_buffer.so libnative_media_core.so)
31```
32
331. Add the header files.
34
35    ```c++
36    #include "napi/native_api.h"
37    #include <multimedia/player_framework/native_avscreen_capture.h>
38    #include <multimedia/player_framework/native_avscreen_capture_base.h>
39    #include <multimedia/player_framework/native_avscreen_capture_errors.h>
40    #include <native_buffer/native_buffer.h>
41    #include <fcntl.h>
42    #include "string"
43    #include "unistd.h"
44    ```
45
462. Check whether there is a running screen capture service instance. If yes, wait until the instance is stopped and the resources are released.
47
483. Create an AVScreenCapture instance, named **capture** in this example.
49
50    ```c++
51    OH_AVScreenCapture* capture = OH_AVScreenCapture_Create();
52    ```
53
544. Set screen capture parameters.
55
56    After the **capture** instance is created, you can set the parameters required for screen capture. For details about how to set the audio and video parameters, see [Detailed Description](#detailed-description).
57
58    ```c++
59    OH_AVScreenCaptureConfig config;
60
61    OH_AudioInfo audioinfo = {
62        .micCapInfo = miccapinfo,
63        .innerCapInfo = innerCapInfo,
64        .audioEncInfo = audioEncInfo
65    };
66
67    OH_VideoInfo videoinfo = {
68        .videoCapInfo = videocapinfo,
69        .videoEncInfo = videoEncInfo
70    };
71
72    OH_AVScreenCaptureConfig config = {
73        .captureMode = OH_CAPTURE_HOME_SCREEN,
74        .dataType = OH_ORIGINAL_STREAM,
75        .audioInfo = audioinfo,
76        .videoInfo = videoinfo
77    };
78
79    OH_AVScreenCapture_Init(capture, config);
80    ```
81
825. (Optional) Enable the microphone.
83
84    ```c++
85    bool isMic = true;
86    OH_AVScreenCapture_SetMicrophoneEnabled(capture, isMic);
87    ```
88
896. Set callback functions, which are used to listen for errors that may occur during screen capture and the generation of audio and video stream data. See [Detailed Description](#detailed-description) for more information.
90
91    ```c++
92    OH_AVScreenCapture_SetErrorCallback(capture, OnError, userData);
93    OH_AVScreenCapture_SetStateCallback(capture, OnStateChange, userData);
94    OH_AVScreenCapture_SetDataCallback(capture, OnBufferAvailable, userData);
95    ```
96
977. Call **StartScreenCapture()** to start screen capture.
98
99    ```c++
100    bool IsCaptureStreamRunning = true;
101    OH_AVScreenCapture_StartScreenCapture(capture);
102    ```
103
104    Alternatively, call **StartScreenCaptureWithSurface()** to start screen capture in surface mode.
105
106    ```c++
107    OH_AVScreenCapture_StartScreenCaptureWithSurface(capture, window);
108    ```
109
1108. Call **StopScreenCapture()** to stop screen capture. See [Detailed Description](#detailed-description) for more information.
111
112    ```c++
113    OH_AVScreenCapture_StopScreenCapture(capture);
114    ```
115
1169. Call **Release()** to release the instance.
117
118    ```c++
119    OH_AVScreenCapture_Release(capture);
120    ```
121
122## Specifications for Selecting the Window to Capture on 2-in-1 Devices
123For 2-in-1 devices, a selection page is offered to users for capturing a specific window. To maintain compatibility with the existing interface design, when third-party applications set the screen capture mode to **OH_CAPTURE_SPECIFIED_SCREEN** or **OH_CAPTURE_SPECIFIED_WINDOW**, a picker dialog appears with the designated window ID pre-selected. The content that gets captured ultimately depends on the user's choice within the picker.
124
125It is recommended that the selection page be used in **OH_CAPTURE_SPECIFIED_WINDOW** mode. You need to configure the screen capture height and width based on the 2-in-1 device's resolution and pass the display ID (and a window ID if you want to capture a specific window).
126
127```c++
128// Configure the screen capture width and height in config_ based on the 2-in-1 device's resolution.
129config_.videoInfo.videoCapInfo.videoFrameWidth = 2880;
130config_.videoInfo.videoCapInfo.videoFrameHeight = 1920;
131
132// Set the screen capture mode to OH_CAPTURE_SPECIFIED_WINDOW and pass a display ID.
133config_.captureMode = OH_CAPTURE_SPECIFIED_WINDOW;
134config_.videoInfo.videoCapInfo.displayId = 0;
135
136// (Optional) Pass a window ID if you want to capture a specific window.
137vector<int32_t> missionIds = {61}; // Window 61 is pre-selected in the picker.
138config_.videoInfo.videoCapInfo.missionIDs = &missionIds[0];
139config_.videoInfo.videoCapInfo.missionIDsLen = static_cast<int32_t>(missionIds.size());
140```
141
142The selection page is also compatible with the following screen capture modes:
143
1441. OH_CAPTURE_SPECIFIED_WINDOW mode, with multiple window IDs passed.
145
146    The 2-in-1 device does not display a picker dialog box. Instead, it displays a privacy dialog box to ask for user approval. Multiple windows can be captured at the same time.
147
148    ```c++
149    // Configure the screen capture width and height in config_ based on the 2-in-1 device's resolution.
150    config_.videoInfo.videoCapInfo.videoFrameWidth = 2880;
151    config_.videoInfo.videoCapInfo.videoFrameHeight = 1920;
152
153    // Set the screen capture mode to OH_CAPTURE_SPECIFIED_WINDOW and pass a display ID.
154    config_.captureMode = OH_CAPTURE_SPECIFIED_WINDOW;
155    config_.videoInfo.videoCapInfo.displayId = 0;
156
157    // Pass multiple window IDs.
158    vector<int32_t> missionIds = {60, 61}; // Windows 60 and 61 are to be captured at the same time.
159    config_.videoInfo.videoCapInfo.missionIDs = &missionIds[0];
160    config_.videoInfo.videoCapInfo.missionIDsLen = static_cast<int32_t>(missionIds.size());
161    ```
162
1632. OH_CAPTURE_SPECIFIED_SCREEN mode.
164
165    The 2-in-1 device displays a picker dialog box, with the display (specified by the passed display ID) pre-selected.
166
167    ```c++
168    // Configure the screen capture width and height in config_ based on the 2-in-1 device's resolution.
169    config_.videoInfo.videoCapInfo.videoFrameWidth = 2880;
170    config_.videoInfo.videoCapInfo.videoFrameHeight = 1920;
171
172    // Set the screen capture mode to OH_CAPTURE_SPECIFIED_SCREEN and pass a display ID.
173    config_.captureMode = OH_CAPTURE_SPECIFIED_SCREEN;
174    config_.videoInfo.videoCapInfo.displayId = 0;
175    ```
176
1773. OH_CAPTURE_HOME_SCREEN mode.
178
179    The 2-in-1 device does not display a picker dialog box. Instead, it displays a privacy dialog box to ask for user approval.
180
181    ```c++
182    // Configure the screen capture width and height in config_ based on the 2-in-1 device's resolution.
183    config_.videoInfo.videoCapInfo.videoFrameWidth = 2880;
184    config_.videoInfo.videoCapInfo.videoFrameHeight = 1920;
185
186    // Set the screen capture mode to OH_CAPTURE_HOME_SCREEN and pass a display ID.
187    config_.captureMode = OH_CAPTURE_HOME_SCREEN;
188    config_.videoInfo.videoCapInfo.displayId = 0;
189    ```
190
191## Detailed Description
192This section describes how to set screen capture parameters, set callback functions, and stop the screen capture service instance involved in [How to Develop](#how-to-develop).
193
1941. Set screen capture parameters.
195    ```c++
196    // Configure audio information in audioinfo.
197    OH_AudioCaptureInfo micCapinfo = {
198        .audioSampleRate = 48000,
199        .audioChannels = 2,
200        .audioSource = OH_SOURCE_DEFAULT
201    };
202    OH_AudioCaptureInfo innerCapInfo = {
203        .audioSampleRate = 48000,
204        .audioChannels = 2,
205        .audioSource = OH_ALL_PLAYBACK
206    };
207    OH_AudioEncInfo audioEncInfo = {
208        .audioSampleRate = 48000,
209        .audioCodecformat = OH_AudioCodecFormat::OH_AAC_LC
210    };
211
212    // Configure video information in videoinfo.
213    OH_VideoCaptureInfo videoCapInfo = {
214        .videoFrameWidth = 768,
215        .videoFrameHeight = 1280,
216        .videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA
217    };
218    OH_VideoEncInfo videoEncInfo = {
219        .videoCodec = OH_VideoCodecFormat::OH_H264,
220        .videoBitrate = 2000000,
221        .videoFrameRate = 30
222    };
223    ```
224
2252. Set callback functions.
226
227    Listeners are provided for error events, state changes, and data obtained involved in screen capture.
228
229    ```c++
230    // OnError(), a callback function invoked when an error occurs.
231    void OnError(OH_AVScreenCapture *capture, int32_t errorCode, void *userData) {
232        (void)capture;
233        (void)errorCode;
234        (void)userData;
235    }
236
237    // OnStageChange(), a callback function invoked when the state changes.
238    void OnStageChange(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureStateCode stateCode, void *userData) {
239        (void)capture;
240        if (stateCode == OH_SCREEN_CAPTURE_STATE_STARTED) {
241            // Process the screen capture start event.
242        }
243        if (stateCode == OH_SCREEN_CAPTURE_STATE_CANCELED) {
244            // Process the screen capture cancellation event.
245        }
246        if (stateCode == OH_SCREEN_CAPTURE_STATE_STOPPED_BY_CALL) {
247            // Process the event indicating that screen capture is interrupted by a call.
248        }
249        if (stateCode == OH_SCREEN_CAPTURE_STATE_MIC_UNAVAILABLE) {
250            // Process the event indicating that the microphone is unavailable during screen capture.
251        }
252        if (stateCode == OH_SCREEN_CAPTURE_STATE_INTERRUPTED_BY_OTHER) {
253            // Process the event indicating that screen capture is interrupted by others.
254        }
255        ...
256        if (stateCode == OH_SCREEN_CAPTURE_STATE_EXIT_PRIVATE_SCENE) {
257            // Process the event indicating that the application exits the privacy mode during screen capture.
258        }
259        (void)userData;
260    }
261
262    // Obtain and process the OnBufferAvailable() callback function of the original audio and video stream data.
263    void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVScreenCaptureBufferType bufferType, int64_t timestamp, void *userData) {
264        // Screen capture is in progress.
265        if (IsCaptureStreamRunning) {
266            if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO) {
267                // Video buffer.
268                OH_NativeBuffer *nativeBuffer = OH_AVBuffer_GetNativeBuffer(buffer);
269                if (nativeBuffer != nullptr && capture != nullptr) {
270                    // Obtain the buffer capacity.
271                    int bufferLen = OH_AVBuffer_GetCapacity(buffer);
272
273                    // Obtain the buffer attribute.
274                    OH_AVCodecBufferAttr info;
275                    OH_AVBuffer_GetBufferAttr(buffer, &info);
276
277                    // Obtain the native buffer configuration.
278                    OH_NativeBuffer_Config config;
279                    OH_NativeBuffer_GetConfig(nativeBuffer, &config);
280
281                    // Obtain the buffer address.
282                    uint8_t *buf = OH_AVBuffer_GetAddr(buffer);
283                    if (buf != nullptr) {
284                        return;
285                    }
286                    // Use the buffer data.
287
288                    // The reference count of the native buffer is decremented by 1. When the reference count reaches 0, the buffer is released.
289                    OH_NativeBuffer_Unreference(nativeBuffer);
290                }
291            } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER) {
292                // Buffer for internal recording.
293                // Obtain the buffer attribute.
294                OH_AVCodecBufferAttr info;
295                OH_AVBuffer_GetBufferAttr(buffer, &info);
296
297                // Obtain the buffer capacity.
298                int bufferLen = OH_AVBuffer_GetCapacity(buffer);
299
300                // Obtain the buffer address.
301                uint8_t *buf = OH_AVBuffer_GetAddr(buffer);
302                if (buf != nullptr) {
303                    return;
304                }
305                // Use the buffer data.
306            } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC) {
307                // Microphone buffer.
308                // Obtain the buffer capacity.
309                int bufferLen = OH_AVBuffer_GetCapacity(buffer);
310
311                // Obtain the buffer address.
312                uint8_t *buf = OH_AVBuffer_GetAddr(buffer);
313                if (buf != nullptr) {
314                    return;
315                }
316                // Use the buffer data.
317            }
318        }
319    }
320    ```
321
3223. Stops the screen capture service and releases resources.
323    ```c++
324    void StopScreenCapture() {
325        // Screen capture is in progress and a screen capture service instance exists.
326        if (IsCaptureStreamRunning && capture != nullptr) {
327            // Stop screen capture.
328            OH_AVScreenCapture_StopScreenCapture(capture);
329
330            // Release screen capture resources.
331            OH_AVScreenCapture_Release(capture);
332
333            // Clear other resources, such as closing the file.
334
335            // Set IsCaptureStreamRunning to false and the screen capture service instance to a null pointer.
336            IsCaptureStreamRunning = false;
337            capture = nullptr;
338        }
339    }
340    ```
341
342## Sample Code
343
344Refer to the sample code below to implement screen capture using AVScreenCapture.
345
346For details about how to create an OH_AVBuffer instance, see [Buffer Output](../avcodec/video-decoding.md#buffer-output).
347
348For details about screen capture in surface mode, see [Surface Input](../avcodec/video-encoding.md#surface-input).
349
350Currently, the buffer holds original streams, which can be encoded and saved in MP4 format for playback.
351
352> **NOTE**
353>
354> The encoding format is reserved and will be implemented in later versions.
355
356```c++
357
358#include "napi/native_api.h"
359#include <multimedia/player_framework/native_avscreen_capture.h>
360#include <multimedia/player_framework/native_avscreen_capture_base.h>
361#include <multimedia/player_framework/native_avscreen_capture_errors.h>
362#include <multimedia/player_framework/native_avbuffer.h>
363#include <native_buffer/native_buffer.h>
364#include <fcntl.h>
365#include "string"
366#include "unistd.h"
367
368struct OH_AVScreenCapture *capture;
369static napi_value Screencapture(napi_env env, napi_callback_info info) {
370    // Obtain the window ID number[] from the JS side.
371    std::vector<int> windowIdsExclude = {};
372    size_t argc = 1;
373    napi_value args[1] = {nullptr};
374    // Obtain parameters.
375    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
376    // Obtain the length of the array.
377    uint32_t array_length;
378    napi_get_array_length(env, args[0], &array_length);
379    // Read the initial window ID.
380    for (int32_t i = 0; i < array_length; i++) {
381        napi_value temp;
382        napi_get_element(env, args[0], i, &temp);
383        uint32_t tempValue;
384        napi_get_value_uint32(env, temp, &tempValue);
385        windowIdsExclude.push_back(tempValue);
386     }
387    // Instantiate AVScreenCapture.
388    capture = OH_AVScreenCapture_Create();
389
390    // Set the callbacks.
391    OH_AVScreenCapture_SetErrorCallback(capture, OnError, nullptr);
392    OH_AVScreenCapture_SetStateCallback(capture, OnStateChange, nullptr);
393    OH_AVScreenCapture_SetDataCallback(capture, OnBufferAvailable, nullptr);
394
395    // (Optional) Configure screen capture rotation. This API should be called when the device screen rotation is detected. If the device screen does not rotate, the API call is invalid.
396    OH_AVScreenCapture_SetCanvasRotation(capture, true);
397    // Optional. Filter audio.
398    OH_AVScreenCapture_ContentFilter *contentFilter= OH_AVScreenCapture_CreateContentFilter();
399    // Add a filter announcement.
400    OH_AVScreenCapture_ContentFilter_AddAudioContent(contentFilter, OH_SCREEN_CAPTURE_NOTIFICATION_AUDIO);
401    // Exclude the specified window ID.
402    OH_AVScreenCapture_ContentFilter_AddWindowContent(contentFilter, &windowIdsExclude[0],
403                                                      static_cast<int32_t>(windowIdsExclude.size()));
404
405    OH_AVScreenCapture_ExcludeContent(capture, contentFilter);
406
407    // Initialize the screen capture parameters and pass in an OH_AVScreenRecorderConfig struct.
408    OH_AudioCaptureInfo miccapinfo = {.audioSampleRate = 16000, .audioChannels = 2, .audioSource = OH_MIC};
409    OH_VideoCaptureInfo videocapinfo = {
410        .videoFrameWidth = 768, .videoFrameHeight = 1280, .videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA};
411    OH_AudioInfo audioinfo = {
412        .micCapInfo = miccapinfo,
413    };
414    OH_VideoInfo videoinfo = {.videoCapInfo = videocapinfo};
415    OH_AVScreenCaptureConfig config = {.captureMode = OH_CAPTURE_HOME_SCREEN,
416                                       .dataType = OH_ORIGINAL_STREAM,
417                                       .audioInfo = audioinfo,
418                                       .videoInfo = videoinfo};
419    OH_AVScreenCapture_Init(capture, config);
420
421    // Optional. Use the surface mode.
422    // To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
423    // OH_AVCodec *codec = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
424    // Obtain the input surface from a video encoder.
425    // OH_AVErrCode OH_VideoEncoder_GetSurface(codec, window);
426    // Start the encoder.
427    // int32_t retEnc = OH_VideoEncoder_Start(codec);
428    // Specify a surface to start screen capture.
429    // int32_t retStart = OH_AVScreenCapture_StartScreenCaptureWithSurface(capture, window);
430
431    // Start screen capture.
432    OH_AVScreenCapture_StartScreenCapture(capture);
433
434    // Enable the microphone.
435    OH_AVScreenCapture_SetMicrophoneEnabled(capture, true);
436
437    // (Optional) Transfer the IDs of the subwindows and main windows to skip from screen capture. Transfer an empty array to cancel the windows that has been configured for exemption.
438	// std::vector<int> windowIdsSkipPrivacy = {};
439    // OH_AVScreenCapture_SkipPrivacyMode(capture, &windowIdsSkipPrivacy[0],
440    //     static_cast<int32_t>(windowIdsSkipPrivacy.size()));
441
442    // (Optional) Adjust the screen capture resolution after the capture starts. For details about the resolution range, see the AVCodec encoding and decoding capabilities.
443    // OH_AVScreenCapture_ResizeCanvas(capture, 768, 1280);
444
445    // (Optional) Set the maximum frame rate for screen capture. Call the function after screen capture starts.
446    // OH_AVScreenCapture_SetMaxVideoFrameRate(capture, 20);
447
448    sleep(10); // Capture the screen for 10s.
449    // Stop screen capture.
450    OH_AVScreenCapture_StopScreenCapture(capture);
451    // Release the AVScreenCapture instance.
452    OH_AVScreenCapture_Release(capture);
453    // Return the call result. In the example, only a random number is returned.
454    napi_value sum;
455    napi_create_double(env, 5, &sum);
456
457    return sum;
458}
459```
460