• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Video Encoding
2
3You can call the native APIs provided by the **VideoEncoder** module to encode a video, that is, to compress audio and video data into an audio and video stream.
4
5Currently, the following encoding capabilities are supported:
6
7| Container Specification| Video Encoding Type       | Audio Encoding Type  |
8| -------- | --------------------- | ---------------- |
9| mp4      | HEVC (H.265), AVC (H.264)| AAC, MPEG (MP3)|
10| m4a      | HEVC (H.265), AVC (H.264)| AAC |
11
12## Surface Input and Buffer Input
13
14Surface input and buffer input differ in data sources.
15
16Surface input contains information such as pixel data and pixel format, for example, a recorded video stream directly transferred by the camera module. It is more applicable to scenarios such as real-time video capture.
17
18Buffer input refers to a memory space, which is generally a byte array or a pointer to the memory. It is more applicable to scenarios such as reading audio and video data from files or real-time streaming transmission.
19
20The two also differ slightly in the API calling modes:
21
22- In buffer input mode, an application calls **OH_VideoEncoder_PushInputData()** to input data. In surface input mode, an application, before the encoder starts, calls **OH_VideoEncoder_GetSurface()** to obtain the surface for video data transmission.
23
24- In buffer input mode, an application calls **OH_VideoEncoder_PushInputData()** to pass in the End of Stream (EOS) flag, and the encoder stops when it reads the last frame. In surface input mode, an application calls **OH_VideoEncoder_NotifyEndOfStream()** to notify the encoder of EOS.
25
26For details about the development procedure, see [Buffer Input](#buffer-input) and [Surface Input](#surface-input).
27
28## How to Develop
29
30Read [VideoEncoder](../reference/native-apis/_video_encoder.md) for the API reference.
31
32The figure below shows the call relationship of video encoding.
33
34![Call relationship of video encoding](figures/video-encode.png)
35
36### Buffer Input
37
38The following walks you through how to implement the entire video encoding process in buffer input mode. It uses the YUV file input and H.264 encoding format as an example.
39
40Currently, the **VideoEncoder** module supports only data transferring in asynchronous mode.
41
421. Create an encoder instance.
43
44   You can create an encoder by name or MIME type.
45
46    ``` c++
47    // To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
48    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(CodecMimeType::VIDEO_AVC.data());
49    ```
50
51    ```c++
52    // To create an encoder by name, call OH_AVCapability_GetName to obtain the codec names available and then call OH_VideoEncoder_CreateByName. If your application has special requirements, for example, expecting an encoder that supports a certain resolution, you can call OH_AVCodec_GetCapability to query the capability first.
53    OH_AVCapability *capability = OH_AVCodec_GetCapability(CodecMimeType::VIDEO_AVC.data(), true);
54    const char *codecName = OH_AVCapability_GetName(capability);
55    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
56    ```
57
582. Call **OH_VideoEncoder_SetCallback()** to set callback functions.
59
60   > **NOTE**
61   >
62   > In the callback functions, pay attention to the multi-thread conflict for operations on the data queue.
63
64   Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
65
66   - **OH_AVCodecOnError**, a callback used to report a codec operation error
67   - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
68   - **OH_AVCodecOnNeedInputData**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
69   - **OH_AVCodecOnNewOutputData**, a callback used to report output data generated, which means that encoding is complete
70
71   You need to process the callback functions to ensure that the encoder runs properly.
72
73    ``` c++
74    // Implement the OH_AVCodecOnError callback function.
75    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
76    {
77        (void)codec;
78        (void)errorCode;
79        (void)userData;
80    }
81
82    // Implement the OH_AVCodecOnStreamChanged callback function.
83    static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
84    {
85        (void)codec;
86        (void)format;
87        (void)userData;
88    }
89
90    // Implement the OH_AVCodecOnNeedInputData callback function.
91    static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem, void *userData)
92    {
93        (void)userData;
94        // The index of the input frame buffer is sent to InIndexQueue.
95        // The input frame data (specified by mem) is sent to InBufferQueue.
96        // Perform data processing. For details, see
97        // 7. Write the stream to encode.
98        // 8. Notify the encoder of EOS.
99    }
100
101    // Implement the OH_AVCodecOnNewOutputData callback function.
102    static void OnNeedOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem,
103                                 OH_AVCodecBufferAttr *attr, void *userData)
104    {
105        (void)userData;
106        // The index of the output frame buffer is sent to outIndexQueue.
107        // The encoded frame data (specified by mem) is sent to outBufferQueue.
108        // The data format of the encoded frame is sent to outAttrQueue.
109        // Perform data processing. For details, see
110        // 9. Output the encoded frames.
111    }
112
113    // Call OH_VideoEncoder_SetCallback to set the asynchronous callback functions.
114    OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputData, &OnNeedOutputData};
115    int32_t ret = OH_VideoEncoder_SetCallback(videoEnc, cb, userData);
116    if (ret != AV_ERR_OK) {
117        // Exception handling.
118    }
119    ```
120
1213. Call **OH_VideoEncoder_Configure()** to configure the encoder.
122
123   Currently, the following options must be configured for all supported formats: video frame width, video frame height, and video pixel format.
124
125   In the code snippet below, the following data is used:
126    - **DEFAULT_WIDTH**: 320 pixels
127    - **DEFAULT_HEIGHT**: 240 pixels
128    - **DEFAULT_PIXELFORMAT**: **VideoPixelFormat::YUV420P** (the pixel format of the YUV file is YUV420P)
129
130    ``` c++
131    // (Mandatory) Configure the video frame width.
132    constexpr uint32_t DEFAULT_WIDTH = 320;
133    // (Mandatory) Configure the video frame height.
134    constexpr uint32_t DEFAULT_HEIGHT = 240;
135    // (Mandatory) Configure the video pixel format.
136    constexpr VideoPixelFormat DEFAULT_PIXELFORMAT = VideoPixelFormat::YUV420P;
137    OH_AVFormat *format = OH_AVFormat_Create();
138    // Set the format.
139    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_WIDTH.data(), DEFAULT_WIDTH);
140    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_HEIGHT.data(), DEFAULT_HEIGHT);
141    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_PIXEL_FORMAT.data(), DEFAULT_PIXELFORMAT);
142    // Configure the encoder.
143    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
144    if (ret != AV_ERR_OK) {
145        // Exception handling.
146    }
147    ```
148
1494. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
150
151    ``` c++
152    ret = OH_VideoEncoder_Prepare(videoEnc);
153    if (ret != AV_ERR_OK) {
154        // Exception handling.
155    }
156    ```
157
1585. Call **OH_VideoEncoder_Start()** to start the encoder.
159
160   As soon as the encoder starts, the callback functions will be triggered to respond to events. Therefore, you must configure the input file and output file first.
161
162    ``` c++
163    // Configure the paths of the input and output files.
164    string_view inputFilePath = "/*yourpath*.yuv";
165    string_view outputFilePath = "/*yourpath*.h264";
166    std::unique_ptr<std::ifstream> inputFile = std::make_unique<std::ifstream>();
167    std::unique_ptr<std::ofstream> outputFile = std::make_unique<std::ofstream>();
168    inputFile->open(inputFilePath.data(), std::ios::in | std::ios::binary);
169    outputFile->open(outputFilePath.data(), std::ios::out | std::ios::binary | std::ios::ate);
170    // Start the encoder to start encoding.
171    int32_t ret = OH_VideoEncoder_Start(videoEnc);
172    if (ret != AV_ERR_OK) {
173        // Exception handling.
174    }
175    ```
176
1776. (Optional) Dynamically configure the encoder instance.
178
179    ``` c++
180    OH_AVFormat *format = OH_AVFormat_Create();
181    // Configure the video frame rate.
182    double frameRate = 30.0;
183    // Configure the video YUV range flag.
184    bool rangeFlag = false;
185    // Configure the video primary color.
186    int32_t primary = static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709);
187    // Configure the transfer features.
188    int32_t transfer = static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709);
189    // Configure the maximum matrix coefficient.
190    int32_t matrix = static_cast<int32_t>(OH_MaxtrixCoefficient::MATRIX_COFFICIENT_IDENTITY);
191    // Configure the encoding profile.
192    int32_t profile = static_cast<int32_t>(AVCProfile::AVC_PROFILE_BASELINE);
193    // Configure the encoding bit rate mode.
194    int32_t rateMode = static_cast<int32_t>(VideoEncodeBitrateMode::CBR);
195    // Configure the key frame interval, in milliseconds.
196    int32_t iFrameInterval = 23000;
197    // Configure the required encoding quality. Only an encoder in constant quality mode supports this configuration.
198    int32_t quality = 0;
199    // Configure the bit rate.
200    int64_t bitRate = 3000000;
201    // Set the format.
202    OH_AVFormat_SetDoubleValue(format, MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate);
203    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_RANGE_FLAG, rangeFlag);
204    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, primary);
205    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, transfer);
206    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, matrix);
207
208    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval);
209    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_PROFILE, profile);
210    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode);
211    OH_AVFormat_SetLongValue(format, MediaDescriptionKey::MD_KEY_BITRATE, bitRate);
212    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_QUALITY, quality);
213
214    int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
215    if (ret != AV_ERR_OK) {
216        // Exception handling.
217    }
218    ```
219
2207. Call **OH_VideoEncoder_PushInputData()** to push the stream to the input queue for encoding.
221
222    In the code snippet below, the following parameters are used:
223    - **GetOneFrameSize()**: function for calculating the frame length of the YUV file. For details about the calculation process, see related YUV documents.
224    - **mem**: parameter passed in by the callback function **OnNeedInputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
225    - **index**: index of the data queue, which is passed in by the callback function **OnNeedInputData**.
226
227    ``` c++
228    // Process the file stream and obtain the frame length, and then write the data to encode to the memory of the specified index.
229    int32_t frameSize = GetOneFrameSize();
230    inputFile->read(reinterpret_cast<char *>(OH_AVMemory_GetAddr(mem)), frameSize);
231    // Configure the buffer information.
232    OH_AVCodecBufferAttr info;
233    info.size = frameSize;
234    info.offset = 0;
235    info.pts = 0;
236    info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
237    // Send the data to the input queue for encoding. The index is the subscript of the input queue.
238    int32_t ret = OH_VideoEncoder_PushInputData(videoEnc, index, info);
239    if (ret != AV_ERR_OK) {
240        // Exception handling.
241    }
242    ```
243
2448. Notify the encoder of EOS.
245
246    In the code snippet below, the following parameter is used:
247
248    **index**: index of the data queue, which is passed in by the callback function **OnNeedInputData**.
249
250    The API **OH_VideoEncoder_PushInputData** is used to notify the encoder of EOS. This API is also used in step 7 to push the stream to the input queue for encoding. Therefore, in the current step, you must pass in the **AVCODEC_BUFFER_FLAGS_EOS** flag.
251
252    ``` c++
253    int32_t ret;
254    OH_AVCodecBufferAttr info;
255    info.size = 0;
256    info.offset = 0;
257    info.pts = 0;
258    info.flags = AVCODEC_BUFFER_FLAG_EOS;
259    ret = OH_VideoEncoder_PushInputData(videoEnc, index, info);
260    if (ret != AV_ERR_OK) {
261        // Exception handling.
262    }
263    ```
264
2659. Call **OH_VideoEncoder_FreeOutputData()** to output the encoded frames.
266
267    In the code snippet below, the following parameters are used:
268    - **index**: index of the data queue, which is passed in by the callback function **OnNeedOutputData**.
269    - **attr**: buffer storing the output data, which is passed in by the callback function **OnNeedOutputData**.
270    - **mem**: parameter passed in by the callback function **OnNeedOutputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
271
272    ``` c++
273    // Write the encoded frame data (specified by mem) to the output file.
274    outputFile->write(reinterpret_cast<char *>(OH_AVMemory_GetAddr(mem)), attr->size);
275    // Free the output buffer. The index is the subscript of the output queue.
276    int32_t ret = OH_VideoEncoder_FreeOutputData(videoEnc, index);
277    if (ret != AV_ERR_OK) {
278        // Exception handling.
279    }
280    ```
281
28210. (Optional) Call **OH_VideoEncoder_Flush()** to refresh the encoder.
283
284    After **OH_VideoEncoder_Flush()** is called, the encoder remains in the running state, but the current queue is cleared and the buffer storing the encoded data is freed.
285
286    To continue encoding, you must call **OH_VideoEncoder_Start()** again.
287
288    ``` c++
289    int32_t ret;
290    // Refresh the encoder.
291    ret = OH_VideoEncoder_Flush(videoEnc);
292    if (ret != AV_ERR_OK) {
293        // Exception handling.
294    }
295    // Start encoding again.
296    ret = OH_VideoEncoder_Start(videoEnc);
297    if (ret != AV_ERR_OK) {
298        // Exception handling.
299    }
300    ```
301
30211. (Optional) Call **OH_VideoEncoder_Reset()** to reset the encoder.
303
304    After **OH_VideoEncoder_Reset()** is called, the encoder returns to the initialized state. To continue encoding, you must call **OH_VideoEncoder_Configure()** and then **OH_VideoEncoder_Start()**.
305
306    ``` c++
307    int32_t ret;
308    // Reset the encoder.
309    ret = OH_VideoEncoder_Reset(videoEnc);
310    if (ret != AV_ERR_OK) {
311        // Exception handling.
312    }
313    // Reconfigure the encoder.
314    ret = OH_VideoEncoder_Configure(videoEnc, format);
315    if (ret != AV_ERR_OK) {
316        // Exception handling.
317    }
318    ```
319
32012. Call **OH_VideoEncoder_Stop()** to stop the encoder.
321
322    ``` c++
323    int32_t ret;
324    // Stop the encoder.
325    ret = OH_VideoEncoder_Stop(videoEnc);
326    if (ret != AV_ERR_OK) {
327        // Exception handling.
328    }
329    ```
330
33113. Call **OH_VideoEncoder_Destroy()** to destroy the encoder instance and release resources.
332
333    > **NOTE**
334    >
335    > After the call, you must set a null pointer to the encoder to prevent program errors caused by wild pointers.
336
337    ``` c++
338    int32_t ret;
339    // Call OH_VideoEncoder_Destroy to destroy the encoder.
340    ret = OH_VideoEncoder_Destroy(videoEnc);
341    videoEnc = nullptr;
342    if (ret != AV_ERR_OK) {
343        // Exception handling.
344    }
345    ```
346
347### Surface Input
348
349The following walks you through how to implement the entire video encoding process in surface input mode. It uses the video data input and H.264 encoding format as an example.
350Currently, the **VideoEncoder** module supports only data transferring in asynchronous mode.
351
3521. Create an encoder instance.
353
354   You can create an encoder by name or MIME type.
355
356    ``` c++
357    // To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
358    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(CodecMimeType::VIDEO_AVC.data());
359    ```
360
361    ```c++
362    // To create an encoder by name, call OH_AVCapability_GetName to obtain the codec names available and then call OH_VideoEncoder_CreateByName. If your application has special requirements, for example, expecting an encoder that supports a certain resolution, you can call OH_AVCodec_GetCapability to query the capability first.
363    OH_AVCapability *capability = OH_AVCodec_GetCapability(CodecMimeType::VIDEO_AVC.data(), true);
364    const char *codecName = OH_AVCapability_GetName(capability);
365    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
366    ```
367
3682. Call **OH_VideoEncoder_SetCallback()** to set callback functions.
369
370   > **NOTE**
371   >
372   > In the callback functions, pay attention to the multi-thread conflict for operations on the data queue.
373
374   Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
375
376   - **OnError**, a callback used to report a codec operation error
377   - **OnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
378   - **OnNeedInputData**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
379   - **onNeedOutputData**, a callback used to report output data generated, which means that encoding is complete
380
381    ``` c++
382    // Set the OnError callback function.
383    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
384    {
385        (void)codec;
386        (void)errorCode;
387        (void)userData;
388    }
389
390    // Set the OnStreamChanged callback function.
391    static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
392    {
393        (void)codec;
394        (void)format;
395        (void)userData;
396    }
397
398    // Set the OnNeedInputData callback function, which is used to send an input frame to the data queue.
399    static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem, void *userData)
400    {
401        (void)userData;
402        (void)index;
403        (void)mem;
404        // In surface mode, this callback function does not take effect. You can input data by using the surface.
405    }
406
407    // Set the OnNeedOutputData callback function, which is used to send an encoded frame to the output queue.
408    static void OnNeedOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem,
409                                 OH_AVCodecBufferAttr *attr, void *userData)
410    {
411        (void)userData;
412        // The index of the output frame buffer is sent to outIndexQueue.
413        // The encoded frame data (specified by mem) is sent to outBufferQueue.
414        // The data format of the encoded frame is sent to outAttrQueue.
415        // Perform data processing. For details, see
416        // 10. Output the encoded frames.
417    }
418
419    // Call OH_VideoEncoder_SetCallback to set the asynchronous callback functions.
420    OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputData, &OnNeedOutputData};
421    int32_t ret = OH_VideoEncoder_SetCallback(videoEnc, cb, userData);
422    if (ret != AV_ERR_OK) {
423        // Exception handling.
424    }
425    ```
426
4273. Call **OH_VideoEncoder_Configure()** to configure the encoder.
428
429   Currently, the following options must be configured for all supported formats: video frame width, video frame height, and video pixel format.
430
431   In the code snippet below, the following data is used:
432    - **DEFAULT_WIDTH**: 320 pixels
433    - **DEFAULT_HEIGHT**: 240 pixels
434    - **DEFAULT_PIXELFORMAT**: **VideoPixelFormat::YUV420P** (the pixel format of the YUV file is YUV420P)
435
436    ``` c++
437    // (Mandatory) Configure the video frame width.
438    constexpr uint32_t DEFAULT_WIDTH = 320;
439    // (Mandatory) Configure the video frame height.
440    constexpr uint32_t DEFAULT_HEIGHT = 240;
441    // (Mandatory) Configure the video pixel format.
442    constexpr VideoPixelFormat DEFAULT_PIXELFORMAT = VideoPixelFormat::YUV420P;
443    OH_AVFormat *format = OH_AVFormat_Create();
444    // Set the format.
445    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_WIDTH.data(), DEFAULT_WIDTH);
446    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_HEIGHT.data(), DEFAULT_HEIGHT);
447    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_PIXEL_FORMAT.data(), DEFAULT_PIXELFORMAT);
448    // Configure the encoder.
449    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
450    if (ret != AV_ERR_OK) {
451        // Exception handling.
452    }
453    ```
454
4554. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
456
457    ``` c++
458    ret = OH_VideoEncoder_Prepare(videoEnc);
459    if (ret != AV_ERR_OK) {
460        // Exception handling.
461    }
462    ```
463
4645. Obtain a surface.
465
466    Obtain the **OHNativeWindow** input in surface input mode. The surface must be obtained before the encoder starts.
467
468    ``` c++
469    int32_t ret;
470    // Obtain the surface used for data input.
471    OHNativeWindow *nativeWindow;
472    ret =  OH_VideoEncoder_GetSurface(videoEnc, &nativeWindow);
473    if (ret != AV_ERR_OK) {
474        // Exception handling.
475    }
476    // Configure the surface of the input data through the OHNativeWindow* variable type.
477    ```
478
479    For details about how to use the OHNativeWindow* variable type, see [NativeWindow](../reference/native-apis/_native_window.md).
480
4816. Call **OH_VideoEncoder_Start()** to start the encoder.
482
483    ``` c++
484    int32_t ret;
485    // Start the encoder to start encoding.
486    ret = OH_VideoEncoder_Start(videoEnc);
487    if (ret != AV_ERR_OK) {
488        // Exception handling.
489    }
490    ```
491
4927. (Optional) Dynamically configure the encoder instance.
493
494    ``` c++
495    OH_AVFormat *format = OH_AVFormat_Create();
496    // Configure the video frame rate.
497    double frameRate = 30.0;
498    // Configure the video YUV range flag.
499    bool rangeFlag = false;
500    // Configure the video primary color.
501    int32_t primary = static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709);
502    // Configure the transfer features.
503    int32_t transfer = static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709);
504    // Configure the maximum matrix coefficient.
505    int32_t matrix = static_cast<int32_t>(OH_MaxtrixCoefficient::MATRIX_COFFICIENT_IDENTITY);
506    // Configure the encoding profile.
507    int32_t profile = static_cast<int32_t>(AVCProfile::AVC_PROFILE_BASELINE);
508    // Configure the encoding bit rate mode.
509    int32_t rateMode = static_cast<int32_t>(VideoEncodeBitrateMode::CBR);
510    // Configure the key frame interval, in milliseconds.
511    int32_t iFrameInterval = 23000;
512    // Configure the required encoding quality. Only an encoder in constant quality mode supports this configuration.
513    int32_t quality = 0;
514    // Configure the bit rate.
515    int64_t bitRate = 3000000;
516    // Set the format.
517    OH_AVFormat_SetDoubleValue(format, MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate);
518    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_RANGE_FLAG, rangeFlag);
519    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, primary);
520    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, transfer);
521    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, matrix);
522
523    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, iFrameInterval);
524    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_PROFILE, profile);
525    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode);
526    OH_AVFormat_SetLongValue(format, MediaDescriptionKey::MD_KEY_BITRATE, bitRate);
527    OH_AVFormat_SetIntValue(format, MediaDescriptionKey::MD_KEY_QUALITY, quality);
528
529    int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
530    if (ret != AV_ERR_OK) {
531        // Exception handling.
532    }
533    ```
534
5358. Write the stream to encode.
536
537    In step 5, you have configured the **OHNativeWindow*** variable type returned by **OH_VideoEncoder_GetSurface**.
538
539    The data required for encoding is continuously input by the surface. Therefore, you do not need to process the **OnNeedInputData** callback function or use **OH_VideoEncoder_PushInputData** to input data.
540
5419. Call **OH_VideoEncoder_NotifyEndOfStream()** to notify the encoder of EOS.
542
543    ``` c++
544    int32_t ret;
545    // In surface input mode, you only need to call this API to notify the encoder of EOS.
546    // In buffer input mode, you need to set the AVCODEC_BUFFER_FLAGS_EOS flag and then call OH_VideoEncoder_PushInputData to notify the encoder of EOS.
547    ret = OH_VideoEncoder_NotifyEndOfStream(videoEnc);
548    if (ret != AV_ERR_OK) {
549        // Exception handling.
550    }
551    ```
552
55310. Call **OH_VideoEncoder_FreeOutputData()** to output the encoded frames.
554
555    In the code snippet below, the following parameters are used:
556    - **index**: index of the data queue, which is passed in by the callback function **OnNeedOutputData**.
557    - **attr**: buffer storing the output data, which is passed in by the callback function **OnNeedOutputData**.
558    - **mem**: parameter passed in by the callback function **OnNeedOutputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
559
560    ``` c++
561    // Write the encoded frame data (specified by mem) to the output file.
562    outputFile->write(reinterpret_cast<char *>(OH_AVMemory_GetAddr(mem)), attr->size);
563    // Free the output buffer. The index is the subscript of the output queue.
564    int32_t ret = OH_VideoEncoder_FreeOutputData(videoEnc, index);
565    if (ret != AV_ERR_OK) {
566        // Exception handling.
567    }
568    ```
569
570The subsequent processes (including refreshing, resetting, stopping, and destroying the encoder) are the same as those in buffer input mode. For details, see steps 9-12 in [Buffer Input](#buffer-input).
571