• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Video Encoding (C/C++)
2
3You can call the native APIs provided by the VideoEncoder module to encode a video, that is, to compress video data into a video stream.
4
5Currently, the following encoding capabilities are supported:
6
7| Container Specification| Video Encoding Type                |
8| -------- | ---------------------------- |
9| mp4      | HEVC (H.265) and AVC (H.264)|
10| m4a      | HEVC (H.265) and AVC (H.264)|
11
12Currently, only hardware encoding is supported. When an encoder is created based on the MIME type, H.264 (OH_AVCODEC_MIMETYPE_VIDEO_AVC) and H.265 (OH_AVCODEC_MIMETYPE_VIDEO_HEVC) are supported.
13
14## Surface Input and Buffer Input
15
16Surface input and buffer input differ in data sources.
17
18Surface input indicates that the OHNativeWindow is used to transfer passed-in data. It supports connection with other modules, such as the camera module.
19
20Buffer input refers to a pre-allocated memory area. The caller needs to copy original data to this memory area. It is more applicable to scenarios such as reading video data from files.
21
22The two also differ slightly in the API calling modes:
23
24- In buffer mode, an application calls **OH_VideoEncoder_PushInputBuffer()** to input data. In surface mode, an application, before the encoder is ready, calls **OH_VideoEncoder_GetSurface()** to obtain the OHNativeWindow for video data transmission.
25- In buffer mode, an application calls **OH_VideoEncoder_PushInputBuffer()** to pass in the End of Stream (EOS) flag, and the encoder stops when it reads the last frame. In surface mode, an application calls **OH_VideoEncoder_NotifyEndOfStream()** to notify the encoder of EOS.
26
27For details about the development procedure, see [Surface Input](#surface-input) and [Buffer Input](#buffer-input).
28
29## How to Develop
30
31Read [VideoEncoder](../reference/apis-avcodec-kit/_video_encoder.md) for the API reference.
32
33The figure below shows the call relationship of video encoding.
34
35![Call relationship of video encoding](figures/video-encode.png)
36
37### Linking the Dynamic Library in the CMake Script
38
39```cmake
40target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
41target_link_libraries(sample PUBLIC libnative_media_core.so)
42target_link_libraries(sample PUBLIC libnative_media_venc.so)
43```
44
45### Surface Input
46
47The following walks you through how to implement the entire video encoding process in surface mode. In this example, surface data is input and encoded into a H.264 stream.
48
49Currently, the VideoEncoder module supports only data rotation in asynchronous mode.
50
511. Add the header files.
52
53    ```cpp
54    #include <multimedia/player_framework/native_avcodec_videoencoder.h>
55    #include <multimedia/player_framework/native_avcapability.h>
56    #include <multimedia/player_framework/native_avcodec_base.h>
57    #include <multimedia/player_framework/native_avformat.h>
58    #include <multimedia/player_framework/native_avbuffer.h>
59    ```
60
612. Create an encoder instance.
62
63    You can create an encoder by name or MIME type. In the code snippet below, the following variables are used:
64
65    - **videoEnc**: pointer to the video encoder instance.
66    - **capability**: pointer to the encoder's capability.
67    - **OH_AVCODEC_MIMETYPE_VIDEO_AVC**: name of an AVC video stream.
68
69    ```c++
70    // 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.
71    OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
72    const char *codecName = OH_AVCapability_GetName(capability);
73    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
74    ```
75
76    ```c++
77    // To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
78    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
79    ```
80
813. Call **OH_VideoEncoder_RegisterCallback()** to register the callback functions.
82
83    > **NOTE**
84    >
85    > In the callback functions, pay attention to multi-thread synchronization for operations on the data queue.
86    >
87
88    Register the **OH_AVCodecCallback** struct that defines the following callback function pointers:
89
90    - **OH_AVCodecOnError**, a callback used to report a codec operation error.
91    - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, format change.
92    - **OH_AVCodecOnNeedInputBuffer**, a callback used to report input data required. This callback does not take effect, since you input data through the obtained surface.
93    - **OH_AVCodecOnNewOutputBuffer**, a callback used to report output data generated, which means that encoding is complete.
94
95    ```c++
96    // Set the OH_AVCodecOnError callback function.
97    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
98    {
99        (void)codec;
100        (void)errorCode;
101        (void)userData;
102    }
103
104    // Set the OH_AVCodecOnStreamChanged callback function.
105    static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
106    {
107        (void)codec;
108        (void)format;
109        (void)userData;
110    }
111
112    // Set the OH_AVCodecOnNeedInputBuffer callback function, which is used to send an input frame to the data queue.
113    static void OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
114    {
115        (void)userData;
116        (void)index;
117        (void)buffer;
118        // In surface mode, this callback function does not take effect. You can input data by using the obtained surface.
119    }
120
121    // Set the OH_AVCodecOnNewOutputBuffer callback function, which is used to send an encoded frame to the output queue.
122    static void OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
123    {
124        // The index of the output frame buffer is sent to outIndexQueue.
125        // The encoded frame data (specified by buffer) is sent to outBufferQueue.
126        // Perform data processing. For details, see
127        // - Release the encoded frame.
128    }
129
130    // Call OH_VideoEncoder_SetCallback() to set the callback functions.
131    OH_AVCodecCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputBuffer, &OnNewOutputBuffer};
132    int32_t ret = OH_VideoEncoder_RegisterCallback(videoEnc, cb, NULL);
133    if (ret != AV_ERR_OK) {
134        // Exception handling.
135    }
136    ```
137
1384. Call **OH_VideoEncoder_Configure()** to configure the encoder.
139
140    For details about the configurable options, see [Variables](../reference/apis-avcodec-kit/_codec_base.md#variables).
141
142    Currently, the following options must be configured for all supported formats: video frame width, video frame height, and video color format. In the code snippet below, the following variables are used:
143
144    - **DEFAULT_WIDTH**: 320 pixels
145    - **DEFAULT_HEIGHT**: 240 pixels
146    - **DEFAULT_PIXELFORMAT**: **AV_PIXEL_FORMAT_NV12** (the color format of the YUV file is NV12)
147
148    ```c++
149    // (Mandatory) Configure the video frame width.
150    constexpr uint32_t DEFAULT_WIDTH = 320;
151    // (Mandatory) Configure the video frame height.
152    constexpr uint32_t DEFAULT_HEIGHT = 240;
153    // (Mandatory) Configure the video color format.
154    constexpr OH_AVPixelFormat DEFAULT_PIXELFORMAT = AV_PIXEL_FORMAT_NV12;
155    // Configure the video frame rate.
156    double frameRate = 30.0;
157    // Configure the video YUV range flag.
158    bool rangeFlag = false;
159    // Configure the video primary color.
160    int32_t primary = static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709);
161    // Configure the transfer features.
162    int32_t transfer = static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709);
163    // Configure the maximum matrix coefficient.
164    int32_t matrix = static_cast<int32_t>(OH_MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY);
165    // Configure the encoding profile.
166    int32_t profile = static_cast<int32_t>(OH_AVCProfile::AVC_PROFILE_BASELINE);
167    // Configure the encoding bit rate mode.
168    int32_t rateMode = static_cast<int32_t>(OH_VideoEncodeBitrateMode::CBR);
169    // Configure the key frame interval, in milliseconds.
170    int32_t iFrameInterval = 23000;
171    // Configure the required encoding quality. Only an encoder in constant quality mode supports this configuration.
172    int32_t quality = 0;
173    // Configure the bit rate.
174    int64_t bitRate = 3000000;
175
176    OH_AVFormat *format = OH_AVFormat_Create();
177    OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
178    OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
179    OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT);
180
181    OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
182    OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, rangeFlag);
183    OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, primary);
184    OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, transfer);
185    OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, matrix);
186    OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, iFrameInterval);
187    OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, profile);
188    OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode);
189    OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
190    OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, quality);
191    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
192    if (ret != AV_ERR_OK) {
193        // Exception handling.
194    }
195    OH_AVFormat_Destroy(format);
196    ```
197
1985. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
199
200   ```c++
201ret = OH_VideoEncoder_Prepare(videoEnc);
202    if (ret != AV_ERR_OK) {
203        // Exception handling.
204    }
205   ```
206
2076. Obtain a surface.
208
209    Obtain the OHNativeWindow in surface mode. The surface must be obtained before the encoder starts.
210
211    ```c++
212    int32_t ret;
213    // Obtain the surface used for data input.
214    OHNativeWindow *nativeWindow;
215    ret =  OH_VideoEncoder_GetSurface(videoEnc, &nativeWindow);
216    if (ret != AV_ERR_OK) {
217        // Exception handling.
218    }
219    // Configure the surface of the input data through the OHNativeWindow* variable type.
220    ```
221
222    For details about how to use the **OHNativeWindow*** variable type, see [OHNativeWindow](../reference/apis-arkgraphics2d/_native_window.md#ohnativewindow).
223
2247. Call **OH_VideoEncoder_Start()** to start the encoder.
225
226    ```c++
227    int32_t ret;
228    // Start the encoder.
229    ret = OH_VideoEncoder_Start(videoEnc);
230    if (ret != AV_ERR_OK) {
231        // Exception handling.
232    }
233    ```
234
2358. (Optional) Dynamically configure encoder parameters during running.
236
237    ```c++
238    OH_AVFormat *format = OH_AVFormat_Create();
239    OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, true); // Currently, dynamically requesting for IDR frames is supported only.
240    int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
241    if (ret != AV_ERR_OK) {
242        // Exception handling.
243    }
244    ```
245
2469. Write the stream to encode.
247
248   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 **OnNeedInputBuffer** callback function or use **OH_VideoEncoder_PushInputBuffer** to input data.
249
25011. Call **OH_VideoEncoder_NotifyEndOfStream()** to notify the encoder of EOS.
251
252     ```c++
253     int32_t ret;
254     // In surface mode, you only need to call this API to notify the encoder of EOS.
255     // In buffer mode, you need to set the AVCODEC_BUFFER_FLAGS_EOS flag and then call OH_VideoEncoder_PushInputBuffer to notify the encoder of EOS.
256     ret = OH_VideoEncoder_NotifyEndOfStream(videoEnc);
257     if (ret != AV_ERR_OK) {
258         // Exception handling.
259     }
260     ```
261
26212. Call **OH_VideoEncoder_FreeOutputBuffer()** to release encoded frames.
263
264     In the code snippet below, the following variables are used:
265
266     - **index**: index of the data queue, which is passed in by the callback function **OnNewOutputBuffer**.
267     - **buffer**: parameter passed in by the callback function **OnNewOutputBuffer**. You can call **OH_AVBuffer_GetAddr()** to obtain the pointer to the shared memory address.
268
269     ```c++
270     int32_t ret;
271     // Obtain the encoded information.
272     OH_AVCodecBufferAttr info;
273     ret = OH_AVBuffer_GetBufferAttr(buffer, &info);
274     if (ret != AV_ERR_OK) {
275         // Exception handling.
276     }
277     // Write the encoded frame data (specified by buffer) to the output file.
278     outputFile->write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(buffer)), info.size);
279     // Free the output buffer. index is the index of the buffer.
280     ret = OH_VideoEncoder_FreeOutputBuffer(videoEnc, index);
281     if (ret != AV_ERR_OK) {
282         // Exception handling.
283     }
284     ```
285
28613. (Optional) Call **OH_VideoEncoder_Flush()** to refresh the encoder.
287
288    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.
289
290    To continue encoding, you must call **OH_VideoEncoder_Start()** again.
291
292     ```c++
293     int32_t ret;
294     // Refresh the encoder.
295     ret = OH_VideoEncoder_Flush(videoEnc);
296     if (ret != AV_ERR_OK) {
297         // Exception handling.
298     }
299     // Start encoding again.
300     ret = OH_VideoEncoder_Start(videoEnc);
301     if (ret != AV_ERR_OK) {
302         // Exception handling.
303     }
304     ```
305
30614. (Optional) Call **OH_VideoEncoder_Reset()** to reset the encoder.
307
308    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()**.
309
310     ```c++
311     int32_t ret;
312     // Reset the encoder.
313     ret = OH_VideoEncoder_Reset(videoEnc);
314     if (ret != AV_ERR_OK) {
315         // Exception handling.
316     }
317     // Reconfigure the encoder.
318     ret = OH_VideoEncoder_Configure(videoEnc, format);
319     if (ret != AV_ERR_OK) {
320         // Exception handling.
321     }
322     ```
323
32415. (Optional) Call **OH_VideoEncoder_Stop()** to stop the encoder.
325
326     ```c++
327     int32_t ret;
328     // Stop the encoder.
329     ret = OH_VideoEncoder_Stop(videoEnc);
330     if (ret != AV_ERR_OK) {
331         // Exception handling.
332     }
333     ```
334
33516. Call **OH_VideoEncoder_Destroy()** to destroy the encoder instance and release resources.
336
337     > **NOTE**
338     >
339     > This API cannot be called in the callback function.
340     > After the call, you must set a null pointer to the encoder to prevent program errors caused by wild pointers.
341     >
342
343     ```c++
344     int32_t ret;
345     // Call OH_VideoEncoder_Destroy to destroy the encoder.
346     ret = OH_VideoEncoder_Destroy(videoEnc);
347     videoEnc = nullptr;
348     if (ret != AV_ERR_OK) {
349         // Exception handling.
350     }
351     ```
352
353### Buffer Input
354
355The following walks you through how to implement the entire video encoding process in buffer mode. It uses the YUV file input and H.264 encoding format as an example.
356
357Currently, the VideoEncoder module supports only data rotation in asynchronous mode.
358
3591. Add the header files.
360
361    ```cpp
362    #include <multimedia/player_framework/native_avcodec_videoencoder.h>
363    #include <multimedia/player_framework/native_avcapability.h>
364    #include <multimedia/player_framework/native_avcodec_base.h>
365    #include <multimedia/player_framework/native_avformat.h>
366    #include <multimedia/player_framework/native_avbuffer.h>
367    ```
368
3692. Create an encoder instance.
370
371    The procedure is the same as that in surface mode and is not described here.
372
373    ```c++
374    // 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.
375    OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
376    const char *codecName = OH_AVCapability_GetName(capability);
377    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
378    ```
379
380    ```c++
381    // To create an encoder by MIME type, call OH_VideoEncoder_CreateByMime. The system creates the most appropriate encoder based on the MIME type.
382    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
383    ```
384
3853. Call **OH_VideoEncoder_RegisterCallback()** to register the callback functions.
386
387    > **NOTE**
388    >
389    > In the callback functions, pay attention to multi-thread synchronization for operations on the data queue.
390    >
391
392    Register the **OH_AVCodecCallback** struct that defines the following callback function pointers:
393
394    - **OH_AVCodecOnError**, a callback used to report a codec operation error.
395    - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, format change.
396    - **OH_AVCodecOnNeedInputBuffer**, a callback used to report input data required, which means that the encoder is ready for receiving YUV/RGB data.
397    - **OH_AVCodecOnNewOutputBuffer**, a callback used to report output data generated, which means that encoding is complete.
398
399    You need to process the callback functions to ensure that the encoder runs properly.
400
401    ```c++
402    // Implement the OH_AVCodecOnError callback function.
403    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
404    {
405        (void)codec;
406        (void)errorCode;
407        (void)userData;
408    }
409
410    // Implement the OH_AVCodecOnStreamChanged callback function.
411    static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
412    {
413        (void)codec;
414        (void)format;
415        (void)userData;
416    }
417
418    // Implement the OH_AVCodecOnNeedInputBuffer callback function.
419    static void OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
420    {
421        // The index of the input frame buffer is sent to InIndexQueue.
422        // The input frame data (specified by buffer) is sent to InBufferQueue.
423        // Perform data processing. For details, see
424        // - Write the stream to encode.
425        // - Notify the encoder of EOS.
426    }
427
428    // Implement the OH_AVCodecOnNewOutputBuffer callback function.
429    static void OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
430    {
431        // The index of the output frame buffer is sent to outIndexQueue.
432        // The encoded frame data (specified by buffer) is sent to outBufferQueue.
433        // Perform data processing. For details, see
434        // - Release the encoded frame.
435    }
436
437    // Call OH_VideoEncoder_RegisterCallback() to register the callback functions.
438    OH_AVCodecCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputBuffer, &OnNewOutputBuffer};
439    int32_t ret = OH_VideoEncoder_RegisterCallback(videoEnc, cb, NULL);
440    if (ret != AV_ERR_OK) {
441        // Exception handling.
442    }
443    ```
444
4454. Call **OH_VideoEncoder_Configure()** to configure the encoder.
446
447    The procedure is the same as that in surface mode and is not described here.
448
449    ```c++
450    // (Mandatory) Configure the video frame width.
451    constexpr uint32_t DEFAULT_WIDTH = 320;
452    // (Mandatory) Configure the video frame height.
453    constexpr uint32_t DEFAULT_HEIGHT = 240;
454    // (Mandatory) Configure the video color format.
455    constexpr OH_AVPixelFormat DEFAULT_PIXELFORMAT = AV_PIXEL_FORMAT_NV12;
456
457    OH_AVFormat *format = OH_AVFormat_Create();
458    // Set the format.
459    OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
460    OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
461    OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT);
462    // Configure the encoder.
463    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
464    if (ret != AV_ERR_OK) {
465        // Exception handling.
466    }
467        OH_AVFormat_Destroy(format);
468    ```
469
4705. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
471
472   ```c++
473ret = OH_VideoEncoder_Prepare(videoEnc);
474    if (ret != AV_ERR_OK) {
475        // Exception handling.
476    }
477   ```
478
4796. Call **OH_VideoEncoder_Start()** to start the encoder.
480
481    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.
482
483    ```c++
484    // Configure the paths of the input and output files.
485    std::string_view inputFilePath = "/*yourpath*.yuv";
486    std::string_view outputFilePath = "/*yourpath*.h264";
487    std::unique_ptr<std::ifstream> inputFile = std::make_unique<std::ifstream>();
488    std::unique_ptr<std::ofstream> outputFile = std::make_unique<std::ofstream>();
489    inputFile->open(inputFilePath.data(), std::ios::in | std::ios::binary);
490    outputFile->open(outputFilePath.data(), std::ios::out | std::ios::binary | std::ios::ate);
491    // Start the encoder.
492    int32_t ret = OH_VideoEncoder_Start(videoEnc);
493    if (ret != AV_ERR_OK) {
494        // Exception handling.
495    }
496    ```
497
4987. (Optional) Dynamically configure encoder parameters during running.
499
500    ```c++
501    OH_AVFormat *format = OH_AVFormat_Create();
502    OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, true); // Currently, dynamically requesting for IDR frames is supported only.
503    int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
504    if (ret != AV_ERR_OK) {
505        // Exception handling.
506    }
507    ```
508
5098. Call **OH_VideoEncoder_PushInputBuffer()** to push the stream to the input queue for encoding.
510
511    In the code snippet below, the following variables are used:
512
513    - **buffer**: parameter passed in by the callback function **OnNeedInputBuffer**. You can call **OH_AVBuffer_GetAddr()** to obtain the pointer to the shared memory address.
514    - **index**: index of the data queue, which is passed in by the callback function **OnNeedInputBuffer**.
515    - **flags**: type of the buffer flag. For details, see [OH_AVCodecBufferFlags](../reference/apis-avcodec-kit/_core.md#oh_avcodecbufferflags).
516    - **stride**: stride of the obtained buffer data.
517
518    ```c++
519        if (stride == DEFAULT_WIDTH) {
520            // Process the file stream and obtain the frame length, and then write the data to encode to the buffer of the specified index.
521            int32_t frameSize = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3 / 2; // Formula for calculating the data size of each frame in NV12 color format.
522            inputFile->read(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(buffer)), frameSize);
523        } else {
524            // If the stride is not equal to the width, you need to perform the offset based on the stride.
525        }
526        // Configure the buffer information.
527        OH_AVCodecBufferAttr info;
528        info.size = frameSize;
529        info.offset = 0;
530        info.pts = 0;
531        info.flags = flags;
532        ret = OH_AVBuffer_SetBufferAttr(buffer, &info);
533        if (ret != AV_ERR_OK) {
534            // Exception handling.
535        }
536        // Send the data to the input buffer for encoding. index is the index of the buffer.
537        int32_t ret = OH_VideoEncoder_PushInputBuffer(videoEnc, index);
538        if (ret != AV_ERR_OK) {
539            // Exception handling.
540        }
541    ```
542
543    When processing the buffer data (before pushing the data) during hardware encoding, the system must obtain the width, height, and stride of the data to ensure correct processing of the data to encode. For details, see [OH_NativeBuffer](../reference/apis-arkgraphics2d/_o_h___native_buffer.md) of the graphics module.
544
545    ```c++
546        // OH_NativeBuffer * You can obtain information such as the width, height, and stride of the data by calling the APIs of the graphics module.
547        OH_NativeBuffer *ohNativeBuffer = OH_AVBuffer_GetNativeBuffer(buffer);
548        if (ohNativeBuffer != nullptr) {
549            // Obtain the OH_NativeBuffer_Config struct, including the OH_NativeBuffer data information.
550            OH_NativeBuffer_Config config;
551            OH_NativeBuffer_GetConfig(ohNativeBuffer, &config);
552
553            // Free the OH_NativeBuffer.
554            ret = OH_NativeBuffer_Unreference(ohNativeBuffer);
555            if (ret != AV_ERR_OK) {
556                // Exception handling.
557            }
558            ohNativeBuffer = nullptr;
559        }
560    ```
561
5629. Notify the encoder of EOS.
563
564    In the code snippet below, **index** specifies the index of the data queue, which is passed in by the callback function **OnNeedInputBuffer**.
565
566    The API **OH_VideoEncoder_PushInputBuffer** 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.
567
568    ```c++
569    int32_t ret;
570    OH_AVCodecBufferAttr info;
571    info.size = 0;
572    info.offset = 0;
573    info.pts = 0;
574    info.flags = AVCODEC_BUFFER_FLAGS_EOS;
575    ret = OH_AVBuffer_SetBufferAttr(buffer, &info);
576    if (ret != AV_ERR_OK) {
577        // Exception handling.
578    }
579    ret = OH_VideoEncoder_PushInputBuffer(videoEnc, index, info);
580    if (ret != AV_ERR_OK) {
581        // Exception handling.
582    }
583    ```
584
58510. Call **OH_VideoEncoder_FreeOutputBuffer()** to release encoded frames.
586
587
588The procedure is the same as that in surface mode and is not described here.
589
590    ```c++
591    int32_t ret;
592    // Obtain the encoded information.
593    OH_AVCodecBufferAttr info;
594    ret = OH_AVBuffer_GetBufferAttr(buffer, &info);
595    if (ret != AV_ERR_OK) {
596        // Exception handling.
597    }
598    // Write the encoded frame data (specified by buffer) to the output file.
599    outputFile->write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(buffer)), info.size);
600    // Free the output buffer. index is the index of the buffer.
601    ret = OH_VideoEncoder_FreeOutputBuffer(videoEnc, index);
602    if (ret != AV_ERR_OK) {
603        // Exception handling.
604    }
605    ```
606
607The subsequent processes (including refreshing, resetting, stopping, and destroying the encoder) are the same as those in surface mode. For details, see steps 12-15 in [Surface Input](#surface-input).
608