• 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- 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.
24
25For details about the development procedure, see [Buffer Input](#buffer-input) and [Surface Input](#surface-input).
26
27## How to Develop
28
29Read [VideoEncoder](../reference/native-apis/_video_encoder.md) for the API reference.
30
31The figure below shows the call relationship of video encoding.
32
33![Call relationship of video encoding](figures/video-encode.png)
34
35### Linking the Dynamic Library in the CMake Script
36
37```cmake
38target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
39target_link_libraries(sample PUBLIC libnative_media_core.so)
40target_link_libraries(sample PUBLIC libnative_media_venc.so)
41```
42
43### Buffer Input
44
45The 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.
46
47Currently, the **VideoEncoder** module supports only data transferring in asynchronous mode.
48
491. Add the header files.
50
51   ```cpp
52   #include <multimedia/player_framework/native_avcodec_videoencoder.h>
53   #include <multimedia/player_framework/native_avcapability.h>
54   #include <multimedia/player_framework/native_avcodec_base.h>
55   #include <multimedia/player_framework/native_avformat.h>
56   ```
57
582. Create an encoder instance.
59
60   You can create an encoder by name or MIME type. In the code snippet below, the following variables are used:
61
62   - videoEnc: pointer to the video encoder instance.
63   - capability: pointer to the codec capability instance.
64   - OH_AVCODEC_MIMETYPE_VIDEO_AVC: name of an AVC-format video stream.
65
66   ```c++
67   // To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
68   OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
69   ```
70
71   ```c++
72   // 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.
73   OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
74   const char *codecName = OH_AVCapability_GetName(capability);
75   OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
76   ```
77
783. Call **OH_VideoEncoder_SetCallback()** to set callback functions.
79
80   > **NOTE**
81   >
82   > In the callback functions, pay attention to the multi-thread conflict for operations on the data queue.
83
84   Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
85
86   - **OH_AVCodecOnError**, a callback used to report a codec operation error
87   - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
88   - **OH_AVCodecOnNeedInputData**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
89   - **OH_AVCodecOnNewOutputData**, a callback used to report output data generated, which means that encoding is complete
90
91   You need to process the callback functions to ensure that the encoder runs properly.
92
93   ```c++
94   // Implement the OH_AVCodecOnError callback function.
95   static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
96   {
97       (void)codec;
98       (void)errorCode;
99       (void)userData;
100   }
101
102   // Implement the OH_AVCodecOnStreamChanged callback function.
103   static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
104   {
105       (void)codec;
106       (void)format;
107       (void)userData;
108   }
109
110   // Implement the OH_AVCodecOnNeedInputData callback function.
111   static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem, void *userData)
112   {
113       (void)userData;
114       // The index of the input frame buffer is sent to InIndexQueue.
115       // The input frame data (specified by mem) is sent to InBufferQueue.
116       // Perform data processing. For details, see
117       // - Write the stream to encode.
118       // - Notify the encoder of EOS.
119   }
120
121   // Implement the OH_AVCodecOnNewOutputData callback function.
122   static void OnNeedOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem,
123                                OH_AVCodecBufferAttr *attr, void *userData)
124   {
125       (void)userData;
126       // The index of the output frame buffer is sent to outIndexQueue.
127       // The encoded frame data (specified by mem) is sent to outBufferQueue.
128       // The data format of the encoded frame is sent to outAttrQueue.
129       // Perform data processing. For details, see
130       // - Output the encoded frames.
131   }
132
133   // Call OH_VideoEncoder_SetCallback to set the callback functions.
134   OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputData, &OnNeedOutputData};
135   int32_t ret = OH_VideoEncoder_SetCallback(videoEnc, cb, NULL);
136   if (ret != AV_ERR_OK) {
137       // Exception handling.
138   }
139   ```
140
1414. Call **OH_VideoEncoder_Configure()** to configure the encoder.
142
143   Currently, the following options must be configured for all supported formats: video frame width, video frame height, and video pixel format. In the code snippet below, the following data is used:
144
145   - **DEFAULT_WIDTH**: 320 pixels
146   - **DEFAULT_HEIGHT**: 240 pixels
147   - **DEFAULT_PIXELFORMAT**: **AV_PIXEL_FORMAT_YUVI420** (the pixel format of the YUV file is YUV420P)
148
149   ```c++
150   // (Mandatory) Configure the video frame width.
151   constexpr uint32_t DEFAULT_WIDTH = 320;
152   // (Mandatory) Configure the video frame height.
153   constexpr uint32_t DEFAULT_HEIGHT = 240;
154   // (Mandatory) Configure the video pixel format.
155   constexpr OH_AVPixelFormat DEFAULT_PIXELFORMAT = AV_PIXEL_FORMAT_YUVI420;
156   OH_AVFormat *format = OH_AVFormat_Create();
157   // Set the format.
158   OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
159   OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
160   OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT);
161   // Configure the encoder.
162   int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
163   if (ret != AV_ERR_OK) {
164       // Exception handling.
165   }
166   ```
167
1685. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
169
170
171
172   ```c++
173   ret = OH_VideoEncoder_Prepare(videoEnc);
174   if (ret != AV_ERR_OK) {
175       // Exception handling.
176   }
177   ```
178
1796. Call **OH_VideoEncoder_Start()** to start the encoder.
180
181   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.
182
183   ```c++
184   // Configure the paths of the input and output files.
185   string_view inputFilePath = "/*yourpath*.yuv";
186   string_view outputFilePath = "/*yourpath*.h264";
187   std::unique_ptr<std::ifstream> inputFile = std::make_unique<std::ifstream>();
188   std::unique_ptr<std::ofstream> outputFile = std::make_unique<std::ofstream>();
189   inputFile->open(inputFilePath.data(), std::ios::in | std::ios::binary);
190   outputFile->open(outputFilePath.data(), std::ios::out | std::ios::binary | std::ios::ate);
191   // Start the encoder to start encoding.
192   int32_t ret = OH_VideoEncoder_Start(videoEnc);
193   if (ret != AV_ERR_OK) {
194       // Exception handling.
195   }
196   ```
197
1987. (Optional) Dynamically configure the encoder instance.
199
200   ```c++
201   OH_AVFormat *format = OH_AVFormat_Create();
202   // Configure the video frame rate.
203   double frameRate = 30.0;
204   // Configure the video YUV range flag.
205   bool rangeFlag = false;
206   // Configure the video primary color.
207   int32_t primary = static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709);
208   // Configure the transfer features.
209   int32_t transfer = static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709);
210   // Configure the maximum matrix coefficient.
211   int32_t matrix = static_cast<int32_t>(OH_MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY);
212   // Configure the encoding profile.
213   int32_t profile = static_cast<int32_t>(OH_AVCProfile::AVC_PROFILE_BASELINE);
214   // Configure the encoding bit rate mode.
215   int32_t rateMode = static_cast<int32_t>(OH_VideoEncodeBitrateMode::CBR);
216   // Configure the key frame interval, in milliseconds.
217   int32_t iFrameInterval = 23000;
218   // Configure the required encoding quality. Only an encoder in constant quality mode supports this configuration.
219   int32_t quality = 0;
220   // Configure the bit rate.
221   int64_t bitRate = 3000000;
222   // Set the format.
223   OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
224   OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, rangeFlag);
225   OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, primary);
226   OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, transfer);
227   OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, matrix);
228
229   OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, iFrameInterval);
230   OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, profile);
231   OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode);
232   OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
233   OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, quality);
234
235   int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
236   if (ret != AV_ERR_OK) {
237       // Exception handling.
238   }
239   ```
240
2418. Call **OH_VideoEncoder_PushInputData()** to push the stream to the input queue for encoding.
242
243   In the code snippet below, the following parameters are used:
244
245   - **mem**: parameter passed in by the callback function **OnNeedInputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
246   - **index**: index of the data queue, which is passed in by the callback function **OnNeedInputData**.
247
248   ```c++
249   // Process the file stream and obtain the frame length, and then write the data to encode to the memory of the specified index.
250   int32_t frameSize = OH_MD_KEY_WIDTH * OH_MD_KEY_HEIGHT * 3 / 2; // Formula for calculating the data size of each frame in YUV420P pixel format.
251   inputFile->read(reinterpret_cast<char *>(OH_AVMemory_GetAddr(mem)), frameSize);
252   // Configure the buffer information.
253   OH_AVCodecBufferAttr info;
254   info.size = frameSize;
255   info.offset = 0;
256   info.pts = 0;
257   info.flags = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
258   // Send the data to the input queue for encoding. The index is the subscript of the input queue.
259   int32_t ret = OH_VideoEncoder_PushInputData(videoEnc, index, info);
260   if (ret != AV_ERR_OK) {
261       // Exception handling.
262   }
263   ```
264
2659. Notify the encoder of EOS.
266
267   In the code snippet below, **index** specifies the index of the data queue, which is passed in by the callback function **OnNeedInputData**.  The API **OH_VideoEncoder_PushInputData** is used to notify the encoder of EOS. This API is also used in step 8 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.
268
269   ```c++
270   int32_t ret;
271   OH_AVCodecBufferAttr info;
272   info.size = 0;
273   info.offset = 0;
274   info.pts = 0;
275   info.flags = AVCODEC_BUFFER_FLAGS_EOS;
276   ret = OH_VideoEncoder_PushInputData(videoEnc, index, info);
277   if (ret != AV_ERR_OK) {
278       // Exception handling.
279   }
280   ```
281
28210. Call **OH_VideoEncoder_FreeOutputData()** to output the encoded frames.
283
284    In the code snippet below, the following parameters are used:
285
286    - **index**: index of the data queue, which is passed in by the callback function **OnNeedOutputData**.
287    - **attr**: buffer storing the output data, which is passed in by the callback function **OnNeedOutputData**.
288    - **mem**: parameter passed in by the callback function **OnNeedOutputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
289
290    ```c++
291    // Write the encoded frame data (specified by mem) to the output file.
292    outputFile->write(reinterpret_cast<char *>(OH_AVMemory_GetAddr(mem)), attr->size);
293    // Free the output buffer. The index is the subscript of the output queue.
294    int32_t ret = OH_VideoEncoder_FreeOutputData(videoEnc, index);
295    if (ret != AV_ERR_OK) {
296        // Exception handling.
297    }
298    ```
299
30011. (Optional) Call **OH_VideoEncoder_Flush()** to refresh the encoder.
301
302    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.
303
304    To continue encoding, you must call **OH_VideoEncoder_Start()** again.
305
306    ```c++
307    int32_t ret;
308    // Refresh the encoder.
309    ret = OH_VideoEncoder_Flush(videoEnc);
310    if (ret != AV_ERR_OK) {
311        // Exception handling.
312    }
313    // Start encoding again.
314    ret = OH_VideoEncoder_Start(videoEnc);
315    if (ret != AV_ERR_OK) {
316        // Exception handling.
317    }
318    ```
319
32012. (Optional) Call **OH_VideoEncoder_Reset()** to reset the encoder.
321
322    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()**.
323
324    ```c++
325    int32_t ret;
326    // Reset the encoder.
327    ret = OH_VideoEncoder_Reset(videoEnc);
328    if (ret != AV_ERR_OK) {
329        // Exception handling.
330    }
331    // Reconfigure the encoder.
332    ret = OH_VideoEncoder_Configure(videoEnc, format);
333    if (ret != AV_ERR_OK) {
334        // Exception handling.
335    }
336    ```
337
33813. (Optional) Call **OH_VideoEncoder_Stop()** to stop the encoder.
339
340    ```c++
341    int32_t ret;
342    // Stop the encoder.
343    ret = OH_VideoEncoder_Stop(videoEnc);
344    if (ret != AV_ERR_OK) {
345        // Exception handling.
346    }
347    ```
348
34914. Call **OH_VideoEncoder_Destroy()** to destroy the encoder instance and release resources.
350
351    > **NOTE**
352    >
353    > After the call, you must set a null pointer to the encoder to prevent program errors caused by wild pointers.
354    >
355
356    ```c++
357    int32_t ret;
358    // Call OH_VideoEncoder_Destroy to destroy the encoder.
359    ret = OH_VideoEncoder_Destroy(videoEnc);
360    videoEnc = nullptr;
361    if (ret != AV_ERR_OK) {
362        // Exception handling.
363    }
364    ```
365
366### Surface Input
367
368The 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.
369Currently, the **VideoEncoder** module supports only data transferring in asynchronous mode.
370
3711. Add the header files.
372
373   ```cpp
374   #include <multimedia/player_framework/native_avcodec_videoencoder.h>
375   #include <multimedia/player_framework/native_avcapability.h>
376   #include <multimedia/player_framework/native_avformat.h>
377   #include <multimedia/player_framework/native_avcodec_base.h>
378   ```
379
3802. Create an encoder instance.
381
382   You can create an encoder by name or MIME type.
383
384   ```c++
385   // To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
386   OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
387   ```
388
389   ```c++
390   // 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.
391   OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
392   const char *codecName = OH_AVCapability_GetName(capability);
393   OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
394   ```
395
3963. Call **OH_VideoEncoder_SetCallback()** to set callback functions.
397
398   > **NOTE**
399   >
400   > In the callback functions, pay attention to the multi-thread conflict for operations on the data queue.
401   >
402
403   Register the **OH_AVCodecAsyncCallback** struct that defines the following callback function pointers:
404
405   - **OH_AVCodecOnError**, a callback used to report a codec operation error
406   - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
407   - **OH_AVCodecOnNeedInputData**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
408   - **OH_AVCodecOnNewOutputData**, a callback used to report output data generated, which means that encoding is complete
409
410   ```c++
411   // Set the OnError callback function.
412   static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
413   {
414       (void)codec;
415       (void)errorCode;
416       (void)userData;
417   }
418
419   // Set the OnStreamChanged callback function.
420   static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
421   {
422       (void)codec;
423       (void)format;
424       (void)userData;
425   }
426
427   // Set the OnNeedInputData callback function, which is used to send an input frame to the data queue.
428   static void OnNeedInputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem, void *userData)
429   {
430       (void)userData;
431       (void)index;
432       (void)mem;
433       // In surface mode, this callback function does not take effect. You can input data by using the surface.
434   }
435
436   // Set the OnNeedOutputData callback function, which is used to send an encoded frame to the output queue.
437   static void OnNeedOutputData(OH_AVCodec *codec, uint32_t index, OH_AVMemory *mem,
438                                OH_AVCodecBufferAttr *attr, void *userData)
439   {
440       (void)userData;
441       // The index of the output frame buffer is sent to outIndexQueue.
442       // The encoded frame data (specified by mem) is sent to outBufferQueue.
443       // The data format of the encoded frame is sent to outAttrQueue.
444       // Perform data processing. For details, see
445       // - Output the encoded frames.
446   }
447
448   // Call OH_VideoEncoder_SetCallback to set the callback functions.
449   OH_AVCodecAsyncCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputData, &OnNeedOutputData};
450   int32_t ret = OH_VideoEncoder_SetCallback(videoEnc, cb, NULL);
451   if (ret != AV_ERR_OK) {
452       // Exception handling.
453   }
454   ```
455
4564. Call **OH_VideoEncoder_Configure()** to configure the encoder.
457
458   Currently, the following options must be configured for all supported formats: video frame width, video frame height, and video pixel format. In the code snippet below, the following data is used:
459
460   - **DEFAULT_WIDTH**: 320 pixels
461   - **DEFAULT_HEIGHT**: 240 pixels
462
463   ```c++
464   // (Mandatory) Configure the video frame width.
465   constexpr uint32_t DEFAULT_WIDTH = 320;
466   // (Mandatory) Configure the video frame height.
467   constexpr uint32_t DEFAULT_HEIGHT = 240;
468   OH_AVFormat *format = OH_AVFormat_Create();
469   // Set the format.
470   OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
471   OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
472   OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT);
473   // Configure the encoder.
474   int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
475   if (ret != AV_ERR_OK) {
476       // Exception handling.
477   }
478   ```
479
4805. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
481
482
483
484   ```c++
485   ret = OH_VideoEncoder_Prepare(videoEnc);
486   if (ret != AV_ERR_OK) {
487       // Exception handling.
488   }
489   ```
490
4916. Obtain a surface.
492
493   Obtain the **OHNativeWindow** input in surface input mode. The surface must be obtained before the encoder starts.
494
495   ```c++
496   int32_t ret;
497   // Obtain the surface used for data input.
498   OHNativeWindow *nativeWindow;
499   ret =  OH_VideoEncoder_GetSurface(videoEnc, &nativeWindow);
500   if (ret != AV_ERR_OK) {
501       // Exception handling.
502   }
503   // Configure the surface of the input data through the OHNativeWindow* variable type.
504   ```
505
506   For details about how to use the **OHNativeWindow*** variable type, see [OHNativeWindow](../reference/native-apis/_native_window.md#ohnativewindow).
5077. Call **OH_VideoEncoder_Start()** to start the encoder.
508
509   ```c++
510   int32_t ret;
511   // Start the encoder to start encoding.
512   ret = OH_VideoEncoder_Start(videoEnc);
513   if (ret != AV_ERR_OK) {
514       // Exception handling.
515   }
516   ```
517
5188. (Optional) Dynamically configure the encoder instance.
519
520   ```c++
521   OH_AVFormat *format = OH_AVFormat_Create();
522   // Configure the video frame rate.
523   double frameRate = 30.0;
524   // Configure the video YUV range flag.
525   bool rangeFlag = false;
526   // Configure the video primary color.
527   int32_t primary = static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709);
528   // Configure the transfer features.
529   int32_t transfer = static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709);
530   // Configure the maximum matrix coefficient.
531   int32_t matrix = static_cast<int32_t>(OH_MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY);
532   // Configure the encoding profile.
533   int32_t profile = static_cast<int32_t>(OH_AVCProfile::AVC_PROFILE_BASELINE);
534   // Configure the encoding bit rate mode.
535   int32_t rateMode = static_cast<int32_t>(OH_VideoEncodeBitrateMode::CBR);
536   // Configure the key frame interval, in milliseconds.
537   int32_t iFrameInterval = 23000;
538   // Configure the required encoding quality. Only an encoder in constant quality mode supports this configuration.
539   int32_t quality = 0;
540   // Configure the bit rate.
541   int64_t bitRate = 3000000;
542   // Set the format.
543   OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
544   OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, rangeFlag);
545   OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, primary);
546   OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, transfer);
547   OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, matrix);
548
549   OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, iFrameInterval);
550   OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, profile);
551   OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode);
552   OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
553   OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, quality);
554
555   int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
556   if (ret != AV_ERR_OK) {
557       // Exception handling.
558   }
559   ```
560
5619. Write the stream to encode.
562
563   In step 6, you have configured the **OHNativeWindow*** variable type returned by **OH_VideoEncoder_GetSurface**. 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.
564
56510. Call **OH_VideoEncoder_NotifyEndOfStream()** to notify the encoder of EOS.
566
567    ```c++
568    int32_t ret;
569    // In surface input mode, you only need to call this API to notify the encoder of EOS.
570    // 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.
571    ret = OH_VideoEncoder_NotifyEndOfStream(videoEnc);
572    if (ret != AV_ERR_OK) {
573        // Exception handling.
574    }
575    ```
576
57711. Call **OH_VideoEncoder_FreeOutputData()** to output the encoded frames.
578
579    In the code snippet below, the following parameters are used:
580
581    - **index**: index of the data queue, which is passed in by the callback function **OnNeedOutputData**.
582    - **attr**: buffer storing the output data, which is passed in by the callback function **OnNeedOutputData**.
583    - **mem**: parameter passed in by the callback function **OnNeedOutputData**. You can call **OH_AVMemory_GetAddr** to obtain the pointer to the shared memory address.
584
585    ```c++
586    // Write the encoded frame data (specified by mem) to the output file.
587    outputFile->write(reinterpret_cast<char *>(OH_AVMemory_GetAddr(mem)), attr->size);
588    // Free the output buffer. The index is the subscript of the output queue.
589    int32_t ret = OH_VideoEncoder_FreeOutputData(videoEnc, index);
590    if (ret != AV_ERR_OK) {
591        // Exception handling.
592    }
593    ```
594
595The subsequent processes (including refreshing, resetting, stopping, and destroying the encoder) are the same as those in buffer input mode. For details, see steps 11-14 in [Buffer Input](#buffer-input).
596