1e41f4b71Sopenharmony_ci# Video Encoding
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ciYou can call the native APIs provided by the VideoEncoder module to encode a video, that is, to compress video data into video streams.
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci<!--RP3--><!--RP3End-->
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciCurrently, the following encoding capabilities are supported:
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci| Container Format| Video Encoding Type                |
10e41f4b71Sopenharmony_ci| -------- | ---------------------------- |
11e41f4b71Sopenharmony_ci| mp4      | HEVC (H.265) and AVC (H.264)|
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ciOnly 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.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ciYou can perform a [capability query](obtain-supported-codecs.md) to obtain the encoding capability range.
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci<!--RP1--><!--RP1End-->
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ciThe following table lists the video encoding capabilities supported:
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci<!--RP4-->
22e41f4b71Sopenharmony_ci|          Capability                      |                              How to Use                                           |
23e41f4b71Sopenharmony_ci| --------------------------------------- | ---------------------------------------------------------------------------------- |
24e41f4b71Sopenharmony_ci| Layered encoding<br>Setting the LTR frame and reference frame                     | For details, see [Temporally Scalable Video Coding](video-encoding-temporal-scalability.md).       |
25e41f4b71Sopenharmony_ci<!--RP4End-->
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ci## Restrictions
28e41f4b71Sopenharmony_ci- The buffer mode does not support 10-bit image data.
29e41f4b71Sopenharmony_ci- Due to limited hardware encoder resources, you must call **OH_VideoEncoder_Destroy** to destroy every encoder instance when it is no longer needed.
30e41f4b71Sopenharmony_ci- Once **Flush**, **Reset**, or **Stop** is called, the system reclaims the OH_AVBuffer. Therefore, do not continue to operate the OH_AVBuffer obtained through the previous callback function.
31e41f4b71Sopenharmony_ci- The buffer mode and surface mode use the same APIs. Therefore, the surface mode is described as an example.
32e41f4b71Sopenharmony_ci- In buffer mode, after obtaining the pointer to an OH_AVBuffer object through the callback function **OH_AVCodecOnNeedInputBuffer**, call **OH_VideoEncoder_PushInputBuffer** to notify the system that the buffer has been fully utilized. In this way, the system will proceed with encoding the data contained in the buffer. If the OH_NativeBuffer object is obtained through **OH_AVBuffer_GetNativeBuffer** and its lifecycle extends beyond that of the OH_AVBuffer pointer object, you mut perform data duplication. In this case, you should manage the lifecycle of the newly generated OH_NativeBuffer object to ensure that the object can be correctly used and released.
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci## Surface Input and Buffer Input
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci- Surface input and buffer input differ in data sources.
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci- They are applicable to different scenarios.
40e41f4b71Sopenharmony_ci  - Surface input indicates that the OHNativeWindow is used to transfer passed-in data. It supports connection with other modules, such as the camera module.
41e41f4b71Sopenharmony_ci  - Buffer 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.
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci- The two also differ slightly in the API calling modes:
44e41f4b71Sopenharmony_ci  - In buffer mode, the caller calls **OH_VideoEncoder_PushInputBuffer** to input data. In surface mode, the caller, before the encoder is ready, calls **OH_VideoEncoder_GetSurface** to obtain the OHNativeWindow for video data transmission.
45e41f4b71Sopenharmony_ci  - In buffer mode, the caller uses **attr** in **OH_AVBuffer** to pass in the End of Stream (EOS) flag, and the encoder stops when it reads the last frame. In surface mode, the caller calls **OH_VideoEncoder_NotifyEndOfStream** to notify the encoder of EOS.
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ciFor details about the development procedure, see [Surface Input](#surface-input) and [Buffer Input](#buffer-input).
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci## State Machine Interaction
50e41f4b71Sopenharmony_ciThe following figure shows the interaction between states.
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci![Invoking relationship of state](figures/state-invocation.png)
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci1. An encoder enters the Initialized state in either of the following ways:
56e41f4b71Sopenharmony_ci   - When an encoder instance is initially created, the encoder enters the Initialized state.
57e41f4b71Sopenharmony_ci   - When **OH_VideoEncoder_Reset** is called in any state, the encoder returns to the Initialized state.
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci2. When the encoder is in the Initialized state, you can call **OH_VideoEncoder_Configure** to configure the encoder. After the configuration, the encoder enters the Configured state.
60e41f4b71Sopenharmony_ci3. When the encoder is in the Configured state, you can call **OH_VideoEncoder_Prepare()** to switch it to the Prepared state.
61e41f4b71Sopenharmony_ci4. When the encoder is in the Prepared state, you can call **OH_VideoEncoder_Start** to switch it to the Executing state.
62e41f4b71Sopenharmony_ci   - When the encoder is in the Executing state, you can call **OH_VideoEncoder_Stop** to switch it back to the Prepared state.
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci5. In rare cases, the encoder may encounter an error and enter the Error state. If this is the case, an invalid value can be returned or an exception can be thrown through a queue operation.
65e41f4b71Sopenharmony_ci   - When the encoder is in the Error state, you can either call **OH_VideoEncoder_Reset** to switch it to the Initialized state or call **OH_VideoEncoder_Destroy** to switch it to the Released state.
66e41f4b71Sopenharmony_ci
67e41f4b71Sopenharmony_ci6. The Executing state has three substates: Flushed, Running, and End-of-Stream.
68e41f4b71Sopenharmony_ci   - After **OH_VideoEncoder_Start** is called, the encoder enters the Running substate immediately.
69e41f4b71Sopenharmony_ci   - When the encoder is in the Executing state, you can call **OH_VideoEncoder_Flush** to switch it to the Flushed substate.
70e41f4b71Sopenharmony_ci   - After all data to be processed is transferred to the encoder, the **AVCODEC_BUFFER_FLAGS_EOS** flag is added to the last input buffer in the input buffers queue. Once this flag is detected, the encoder transits to the End-of-Stream substate. In this state, the encoder does not accept new inputs, but continues to generate outputs until it reaches the tail frame.
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci7. When the encoder is no longer needed, you must call **OH_VideoEncoder_Destroy** to destroy the encoder instance. Then the encoder enters the Released state.
73e41f4b71Sopenharmony_ci
74e41f4b71Sopenharmony_ci## How to Develop
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ciRead [VideoEncoder](../../reference/apis-avcodec-kit/_video_encoder.md) for the API reference.
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ciThe figure below shows the call relationship of video encoding.
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci- The dotted line indicates an optional operation.
81e41f4b71Sopenharmony_ci
82e41f4b71Sopenharmony_ci- The solid line indicates a mandatory operation.
83e41f4b71Sopenharmony_ci
84e41f4b71Sopenharmony_ci![Call relationship of video encoding](figures/video-encode.png)
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci### Linking the Dynamic Libraries in the CMake Script
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci```cmake
89e41f4b71Sopenharmony_citarget_link_libraries(sample PUBLIC libnative_media_codecbase.so)
90e41f4b71Sopenharmony_citarget_link_libraries(sample PUBLIC libnative_media_core.so)
91e41f4b71Sopenharmony_citarget_link_libraries(sample PUBLIC libnative_media_venc.so)
92e41f4b71Sopenharmony_ci```
93e41f4b71Sopenharmony_ci> **NOTE**
94e41f4b71Sopenharmony_ci>
95e41f4b71Sopenharmony_ci> The word 'sample' in the preceding code snippet is only an example. Use the actual project directory name.
96e41f4b71Sopenharmony_ci>
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci### Surface Input
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ciThe 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.
101e41f4b71Sopenharmony_ci
102e41f4b71Sopenharmony_ciCurrently, the VideoEncoder module supports only data rotation in asynchronous mode.
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ci1. Add the header files.
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci    ```cpp
107e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avcodec_videoencoder.h>
108e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avcapability.h>
109e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avcodec_base.h>
110e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avformat.h>
111e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avbuffer.h>
112e41f4b71Sopenharmony_ci    #include <fstream>
113e41f4b71Sopenharmony_ci    ```
114e41f4b71Sopenharmony_ci
115e41f4b71Sopenharmony_ci2. Configure global variables.
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ci    ```c++
118e41f4b71Sopenharmony_ci    // (Mandatory) Configure the video frame width.
119e41f4b71Sopenharmony_ci    int32_t width = 320; 
120e41f4b71Sopenharmony_ci    // (Mandatory) Configure the video frame height.
121e41f4b71Sopenharmony_ci    int32_t height = 240;
122e41f4b71Sopenharmony_ci    // (Mandatory) Configure the video pixel format.
123e41f4b71Sopenharmony_ci    constexpr OH_AVPixelFormat DEFAULT_PIXELFORMAT = AV_PIXEL_FORMAT_NV12;
124e41f4b71Sopenharmony_ci    int32_t widthStride = 0;
125e41f4b71Sopenharmony_ci    int32_t heightStride = 0;
126e41f4b71Sopenharmony_ci    ```
127e41f4b71Sopenharmony_ci   
128e41f4b71Sopenharmony_ci3. Create an encoder instance.
129e41f4b71Sopenharmony_ci
130e41f4b71Sopenharmony_ci    You can create an encoder by name or MIME type. In the code snippet below, the following variables are used:
131e41f4b71Sopenharmony_ci
132e41f4b71Sopenharmony_ci    - **videoEnc**: pointer to the video encoder instance.
133e41f4b71Sopenharmony_ci    - **capability**: pointer to the encoder's capability.
134e41f4b71Sopenharmony_ci    - **OH_AVCODEC_MIMETYPE_VIDEO_AVC**: AVC video codec.
135e41f4b71Sopenharmony_ci
136e41f4b71Sopenharmony_ci    The following is an example:
137e41f4b71Sopenharmony_ci
138e41f4b71Sopenharmony_ci    ```c++
139e41f4b71Sopenharmony_ci    // Create an encoder by name. 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.
140e41f4b71Sopenharmony_ci    OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
141e41f4b71Sopenharmony_ci    // Create a hardware encoder instance.
142e41f4b71Sopenharmony_ci    OH_AVCapability *capability= OH_AVCodec_GetCapabilityByCategory(OH_AVCODEC_MIMETYPE_VIDEO_AVC, false, HARDWARE);
143e41f4b71Sopenharmony_ci    const char *codecName = OH_AVCapability_GetName(capability);
144e41f4b71Sopenharmony_ci    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
145e41f4b71Sopenharmony_ci    ```
146e41f4b71Sopenharmony_ci
147e41f4b71Sopenharmony_ci    ```c++
148e41f4b71Sopenharmony_ci    // Create an encoder by MIME type. Only specific codecs recommended by the system can be created in this way.
149e41f4b71Sopenharmony_ci    // Only hardware encoders can be created.
150e41f4b71Sopenharmony_ci    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
151e41f4b71Sopenharmony_ci    ```
152e41f4b71Sopenharmony_ci
153e41f4b71Sopenharmony_ci4. Call **OH_VideoEncoder_RegisterCallback()** to register the callback functions.
154e41f4b71Sopenharmony_ci
155e41f4b71Sopenharmony_ci    Register the **OH_AVCodecCallback** struct that defines the following callback function pointers:
156e41f4b71Sopenharmony_ci
157e41f4b71Sopenharmony_ci    - **OH_AVCodecOnError**, a callback used to report a codec operation error. For details about the error codes, see [OH_AVCodecOnError](../../reference/apis-avcodec-kit/_codec_base.md#oh_avcodeconerror).
158e41f4b71Sopenharmony_ci    - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, format change.
159e41f4b71Sopenharmony_ci    - **OH_AVCodecOnNeedInputBuffer**, a callback used to report input data required. This callback does not take effect, since you input data through the obtained surface.
160e41f4b71Sopenharmony_ci    - **OH_AVCodecOnNewOutputBuffer**, a callback used to report output data generated, which means that encoding is complete.
161e41f4b71Sopenharmony_ci
162e41f4b71Sopenharmony_ci    <!--RP2--><!--RP2End-->
163e41f4b71Sopenharmony_ci
164e41f4b71Sopenharmony_ci    The following is an example:
165e41f4b71Sopenharmony_ci
166e41f4b71Sopenharmony_ci    <!--RP5-->
167e41f4b71Sopenharmony_ci    ```c++
168e41f4b71Sopenharmony_ci    // Set the OH_AVCodecOnError callback function, which is used to report a codec operation error.
169e41f4b71Sopenharmony_ci    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
170e41f4b71Sopenharmony_ci    {
171e41f4b71Sopenharmony_ci        // Process the error code in the callback.
172e41f4b71Sopenharmony_ci        (void)codec;
173e41f4b71Sopenharmony_ci        (void)errorCode;
174e41f4b71Sopenharmony_ci        (void)userData;
175e41f4b71Sopenharmony_ci    }
176e41f4b71Sopenharmony_ci    ```
177e41f4b71Sopenharmony_ci    <!--RP5End-->
178e41f4b71Sopenharmony_ci
179e41f4b71Sopenharmony_ci    <!--RP12-->
180e41f4b71Sopenharmony_ci    ```c++
181e41f4b71Sopenharmony_ci    // Set the OH_AVCodecOnStreamChanged callback function, which is used to report an encoding stream change.
182e41f4b71Sopenharmony_ci    static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
183e41f4b71Sopenharmony_ci    {
184e41f4b71Sopenharmony_ci        // This callback is useless in encoding scenarios.
185e41f4b71Sopenharmony_ci        (void)codec;
186e41f4b71Sopenharmony_ci        (void)format;
187e41f4b71Sopenharmony_ci        (void)userData;
188e41f4b71Sopenharmony_ci    }
189e41f4b71Sopenharmony_ci    ```
190e41f4b71Sopenharmony_ci    <!--RP12End-->
191e41f4b71Sopenharmony_ci
192e41f4b71Sopenharmony_ci    ```c++
193e41f4b71Sopenharmony_ci    // Set the OH_AVCodecOnNeedInputBuffer callback function, which is used to send an input frame to the data queue.
194e41f4b71Sopenharmony_ci    static void OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
195e41f4b71Sopenharmony_ci    {
196e41f4b71Sopenharmony_ci        // In surface mode, this callback function does not take effect. Data is input through the obtained surface.
197e41f4b71Sopenharmony_ci        (void)userData;
198e41f4b71Sopenharmony_ci        (void)index;
199e41f4b71Sopenharmony_ci        (void)buffer;
200e41f4b71Sopenharmony_ci    }
201e41f4b71Sopenharmony_ci    ```
202e41f4b71Sopenharmony_ci
203e41f4b71Sopenharmony_ci    <!--RP6-->
204e41f4b71Sopenharmony_ci    ```c++
205e41f4b71Sopenharmony_ci    // Set the OH_AVCodecOnNewOutputBuffer callback function, which is used to send an encoded frame to the output queue.
206e41f4b71Sopenharmony_ci    static void OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
207e41f4b71Sopenharmony_ci    {
208e41f4b71Sopenharmony_ci        // The index of the output frame buffer is sent to outIndexQueue.
209e41f4b71Sopenharmony_ci        // The encoded frame data (specified by buffer) is sent to outBufferQueue.
210e41f4b71Sopenharmony_ci        // Process the data.
211e41f4b71Sopenharmony_ci        // Release the encoded frame.
212e41f4b71Sopenharmony_ci    }
213e41f4b71Sopenharmony_ci    ```
214e41f4b71Sopenharmony_ci    <!--RP6End-->
215e41f4b71Sopenharmony_ci
216e41f4b71Sopenharmony_ci    ```c++
217e41f4b71Sopenharmony_ci    // Call OH_VideoEncoder_RegisterCallback() to register the callback functions.
218e41f4b71Sopenharmony_ci    OH_AVCodecCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputBuffer, &OnNewOutputBuffer};
219e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_RegisterCallback(videoEnc, cb, NULL); // NULL: userData is null.
220e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
221e41f4b71Sopenharmony_ci        // Exception handling.
222e41f4b71Sopenharmony_ci    }
223e41f4b71Sopenharmony_ci    ```
224e41f4b71Sopenharmony_ci
225e41f4b71Sopenharmony_ci    > **NOTE**
226e41f4b71Sopenharmony_ci    > 
227e41f4b71Sopenharmony_ci    > In the callback functions, pay attention to multi-thread synchronization for operations on the data queue.
228e41f4b71Sopenharmony_ci
229e41f4b71Sopenharmony_ci5. (Optional) Call **OH_VideoEncoder_RegisterParameterCallback()** to register the frame-specific parameter callback function.
230e41f4b71Sopenharmony_ci
231e41f4b71Sopenharmony_ci    For details, see [Temporally Scalable Video Coding](video-encoding-temporal-scalability.md).
232e41f4b71Sopenharmony_ci
233e41f4b71Sopenharmony_ci    <!--RP7-->
234e41f4b71Sopenharmony_ci    ```c++
235e41f4b71Sopenharmony_ci    // 5.1 Implement the OH_VideoEncoder_OnNeedInputParameter callback function.
236e41f4b71Sopenharmony_ci    static void OnNeedInputParameter(OH_AVCodec *codec, uint32_t index, OH_AVFormat *parameter, void *userData)
237e41f4b71Sopenharmony_ci    {
238e41f4b71Sopenharmony_ci        // The index of the input frame parameter is sent to InParameterIndexQueue.
239e41f4b71Sopenharmony_ci        // The input frame data (specified by parameter) is sent to InParameterQueue.
240e41f4b71Sopenharmony_ci        // Process the data.
241e41f4b71Sopenharmony_ci        // Write the frame-specific parameter.
242e41f4b71Sopenharmony_ci    }
243e41f4b71Sopenharmony_ci
244e41f4b71Sopenharmony_ci    // 5.2 Register the frame-specific parameter callback function.
245e41f4b71Sopenharmony_ci    OH_VideoEncoder_OnNeedInputParameter inParaCb = OnNeedInputParameter;
246e41f4b71Sopenharmony_ci    OH_VideoEncoder_RegisterParameterCallback(videoEnc, inParaCb, NULL); // NULL: userData is null.
247e41f4b71Sopenharmony_ci    ```
248e41f4b71Sopenharmony_ci    <!--RP7End-->
249e41f4b71Sopenharmony_ci
250e41f4b71Sopenharmony_ci6. Call **OH_VideoEncoder_Configure()** to configure the encoder.
251e41f4b71Sopenharmony_ci
252e41f4b71Sopenharmony_ci    For details about the configurable options, see [Video Dedicated Key-Value Paris](../../reference/apis-avcodec-kit/_codec_base.md#media-data-key-value-pairs).
253e41f4b71Sopenharmony_ci    
254e41f4b71Sopenharmony_ci    For details about the parameter verification rules, see [OH_VideoEncoder_Configure()](../../reference/apis-avcodec-kit/_video_encoder.md#oh_videoencoder_configure).
255e41f4b71Sopenharmony_ci
256e41f4b71Sopenharmony_ci    The parameter value ranges can be obtained through the capability query interface. For details, see [Obtaining Supported Codecs](obtain-supported-codecs.md).
257e41f4b71Sopenharmony_ci
258e41f4b71Sopenharmony_ci    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 variables are used:
259e41f4b71Sopenharmony_ci
260e41f4b71Sopenharmony_ci    - **DEFAULT_WIDTH**: 320 pixels
261e41f4b71Sopenharmony_ci    - **DEFAULT_HEIGHT**: 240 pixels
262e41f4b71Sopenharmony_ci    - **DEFAULT_PIXELFORMAT**: **AV_PIXEL_FORMAT_NV12** (the pixel format of the YUV file is NV12)
263e41f4b71Sopenharmony_ci
264e41f4b71Sopenharmony_ci    ```c++
265e41f4b71Sopenharmony_ci    // Configure the video frame rate.
266e41f4b71Sopenharmony_ci    double frameRate = 30.0;
267e41f4b71Sopenharmony_ci    // Configure the video YUV range flag.
268e41f4b71Sopenharmony_ci    bool rangeFlag = false;
269e41f4b71Sopenharmony_ci    // Configure the video primary color.
270e41f4b71Sopenharmony_ci    int32_t primary = static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709);
271e41f4b71Sopenharmony_ci    // Configure the transfer characteristics.
272e41f4b71Sopenharmony_ci    int32_t transfer = static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709);
273e41f4b71Sopenharmony_ci    // Configure the maximum matrix coefficient.
274e41f4b71Sopenharmony_ci    int32_t matrix = static_cast<int32_t>(OH_MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY);
275e41f4b71Sopenharmony_ci    // Configure the encoding profile.
276e41f4b71Sopenharmony_ci    int32_t profile = static_cast<int32_t>(OH_AVCProfile::AVC_PROFILE_BASELINE);
277e41f4b71Sopenharmony_ci    // Configure the encoding bit rate mode.
278e41f4b71Sopenharmony_ci    int32_t rateMode = static_cast<int32_t>(OH_VideoEncodeBitrateMode::CBR);
279e41f4b71Sopenharmony_ci    // Configure the key frame interval, in milliseconds.
280e41f4b71Sopenharmony_ci    int32_t iFrameInterval = 23000;
281e41f4b71Sopenharmony_ci    // Configure the bit rate.
282e41f4b71Sopenharmony_ci    int64_t bitRate = 3000000;
283e41f4b71Sopenharmony_ci    // Set the encoding quality.
284e41f4b71Sopenharmony_ci    int64_t quality = 0;
285e41f4b71Sopenharmony_ci
286e41f4b71Sopenharmony_ci    OH_AVFormat *format = OH_AVFormat_Create();
287e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue (format, OH_MD_KEY_WIDTH, width); // Mandatory
288e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, height); // Mandatory
289e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT); // Mandatory
290e41f4b71Sopenharmony_ci
291e41f4b71Sopenharmony_ci    OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
292e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, rangeFlag);
293e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, primary);
294e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, transfer);
295e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, matrix);
296e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, iFrameInterval);
297e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, profile);
298e41f4b71Sopenharmony_ci    // Configure OH_MD_KEY_QUALITY only when OH_MD_KEY_BITRATE = CQ is used.
299e41f4b71Sopenharmony_ci    if (rateMode == static_cast<int32_t>(OH_VideoEncodeBitrateMode::CQ)) {
300e41f4b71Sopenharmony_ci        OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, quality);
301e41f4b71Sopenharmony_ci    } else if (rateMode == static_cast<int32_t>(OH_VideoEncodeBitrateMode::CBR) ||
302e41f4b71Sopenharmony_ci               rateMode == static_cast<int32_t>(OH_VideoEncodeBitrateMode::VBR)){
303e41f4b71Sopenharmony_ci        OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
304e41f4b71Sopenharmony_ci    }
305e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode);
306e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
307e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
308e41f4b71Sopenharmony_ci        // Exception handling.
309e41f4b71Sopenharmony_ci    }
310e41f4b71Sopenharmony_ci    OH_AVFormat_Destroy(format);
311e41f4b71Sopenharmony_ci    ```
312e41f4b71Sopenharmony_ci
313e41f4b71Sopenharmony_ci    > **NOTE**
314e41f4b71Sopenharmony_ci    > 
315e41f4b71Sopenharmony_ci    > If an optional parameter is incorrectly configured, the error code **AV_ERR_INVAILD_VAL** is returned. However, **OH_VideoEncoder_Configure()** does not fail. Instead, its execution continues with the default value.
316e41f4b71Sopenharmony_ci
317e41f4b71Sopenharmony_ci7. Obtain a surface.
318e41f4b71Sopenharmony_ci
319e41f4b71Sopenharmony_ci    Obtain the OHNativeWindow in surface mode. The surface must be obtained before the encoder is prepared.
320e41f4b71Sopenharmony_ci
321e41f4b71Sopenharmony_ci    ```c++
322e41f4b71Sopenharmony_ci    // Obtain the surface used for data input.
323e41f4b71Sopenharmony_ci    OHNativeWindow *nativeWindow;
324e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_GetSurface(videoEnc, &nativeWindow);
325e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
326e41f4b71Sopenharmony_ci        // Exception handling.
327e41f4b71Sopenharmony_ci    }
328e41f4b71Sopenharmony_ci    // Use the OHNativeWindow* variable to obtain the address of the data to be filled through the producer interface.
329e41f4b71Sopenharmony_ci    ```
330e41f4b71Sopenharmony_ci    For details about how to use the OHNativeWindow* variable-type, see [OHNativeWindow](../../reference/apis-arkgraphics2d/_native_window.md#ohnativewindow).
331e41f4b71Sopenharmony_ci
332e41f4b71Sopenharmony_ci8. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
333e41f4b71Sopenharmony_ci
334e41f4b71Sopenharmony_ci    ```c++
335e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Prepare(videoEnc);
336e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
337e41f4b71Sopenharmony_ci        // Exception handling.
338e41f4b71Sopenharmony_ci    }
339e41f4b71Sopenharmony_ci    ```
340e41f4b71Sopenharmony_ci
341e41f4b71Sopenharmony_ci9. Call **OH_VideoEncoder_Start()** to start the encoder.
342e41f4b71Sopenharmony_ci
343e41f4b71Sopenharmony_ci    ```c++
344e41f4b71Sopenharmony_ci    // Configure the paths of the input and output files.
345e41f4b71Sopenharmony_ci    std::string_view outputFilePath = "/*yourpath*.h264";
346e41f4b71Sopenharmony_ci    std::unique_ptr<std::ofstream> outputFile = std::make_unique<std::ofstream>();
347e41f4b71Sopenharmony_ci    outputFile->open(outputFilePath.data(), std::ios::out | std::ios::binary | std::ios::ate);
348e41f4b71Sopenharmony_ci    // Start the encoder.
349e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Start(videoEnc);
350e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
351e41f4b71Sopenharmony_ci        // Exception handling.
352e41f4b71Sopenharmony_ci    }
353e41f4b71Sopenharmony_ci    ```
354e41f4b71Sopenharmony_ci
355e41f4b71Sopenharmony_ci10. (Optional) Call **OH_VideoEncoder_SetParameter()** to dynamically configure encoder parameters during running.
356e41f4b71Sopenharmony_ci    
357e41f4b71Sopenharmony_ci    For details about the configurable options, see [Video Dedicated Key-Value Paris](../../reference/apis-avcodec-kit/_codec_base.md#media-data-key-value-pairs).
358e41f4b71Sopenharmony_ci
359e41f4b71Sopenharmony_ci    <!--RP8-->
360e41f4b71Sopenharmony_ci    ```c++
361e41f4b71Sopenharmony_ci    OH_AVFormat *format = OH_AVFormat_Create();
362e41f4b71Sopenharmony_ci    // Dynamically request IDR frames.
363e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, true);
364e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
365e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
366e41f4b71Sopenharmony_ci        // Exception handling.
367e41f4b71Sopenharmony_ci    }
368e41f4b71Sopenharmony_ci    OH_AVFormat_Destroy(format);
369e41f4b71Sopenharmony_ci    ```
370e41f4b71Sopenharmony_ci    <!--RP8End-->
371e41f4b71Sopenharmony_ci
372e41f4b71Sopenharmony_ci11. Write the image to encode.
373e41f4b71Sopenharmony_ci
374e41f4b71Sopenharmony_ci    In step 7, you have configured the OHNativeWindow* variable 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.
375e41f4b71Sopenharmony_ci    <!--RP13--><!--RP13End-->
376e41f4b71Sopenharmony_ci
377e41f4b71Sopenharmony_ci12. (Optional) Call **OH_VideoEncoder_PushInputParameter()** to notify the encoder that the frame-specific parameter configuration is complete.
378e41f4b71Sopenharmony_ci
379e41f4b71Sopenharmony_ci    In step 5, you have registered the frame-specific parameter callback function.
380e41f4b71Sopenharmony_ci
381e41f4b71Sopenharmony_ci    In the code snippet below, the following variables are used:
382e41f4b71Sopenharmony_ci
383e41f4b71Sopenharmony_ci    - **index**: parameter passed by the callback function **OnNeedInputParameter**, which uniquely corresponds to the buffer.
384e41f4b71Sopenharmony_ci
385e41f4b71Sopenharmony_ci    ```c++
386e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_PushInputParameter(videoEnc, index);
387e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
388e41f4b71Sopenharmony_ci        // Exception handling.
389e41f4b71Sopenharmony_ci    }
390e41f4b71Sopenharmony_ci    ```
391e41f4b71Sopenharmony_ci
392e41f4b71Sopenharmony_ci13. Call **OH_VideoEncoder_NotifyEndOfStream()** to notify the encoder of EOS.
393e41f4b71Sopenharmony_ci
394e41f4b71Sopenharmony_ci    ```c++
395e41f4b71Sopenharmony_ci    // In surface mode, you only need to call this API to notify the encoder of EOS.
396e41f4b71Sopenharmony_ci    // 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.
397e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_NotifyEndOfStream(videoEnc);
398e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
399e41f4b71Sopenharmony_ci        // Exception handling.
400e41f4b71Sopenharmony_ci    }
401e41f4b71Sopenharmony_ci    ```
402e41f4b71Sopenharmony_ci
403e41f4b71Sopenharmony_ci14. Call **OH_VideoEncoder_FreeOutputBuffer()** to release encoded frames.
404e41f4b71Sopenharmony_ci
405e41f4b71Sopenharmony_ci    In the code snippet below, the following variables are used:
406e41f4b71Sopenharmony_ci
407e41f4b71Sopenharmony_ci    - **index**: parameter passed by the callback function **OnNewOutputBuffer**, which uniquely corresponds to the buffer.
408e41f4b71Sopenharmony_ci    - **buffer**: parameter passed by the callback function **OnNewOutputBuffer**. In surface mode, you cannot obtain the virtual address of the image by calling **OH_AVBuffer_GetAddr**.
409e41f4b71Sopenharmony_ci    ```c++
410e41f4b71Sopenharmony_ci    // Obtain the encoded information.
411e41f4b71Sopenharmony_ci    OH_AVCodecBufferAttr info;
412e41f4b71Sopenharmony_ci    int32_t ret = OH_AVBuffer_GetBufferAttr(buffer, &info);
413e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
414e41f4b71Sopenharmony_ci        // Exception handling.
415e41f4b71Sopenharmony_ci    }
416e41f4b71Sopenharmony_ci    // Write the encoded frame data (specified by buffer) to the output file.
417e41f4b71Sopenharmony_ci    outputFile->write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(buffer)), info.size);
418e41f4b71Sopenharmony_ci    // Free the output buffer. index is the index of the buffer.
419e41f4b71Sopenharmony_ci    ret = OH_VideoEncoder_FreeOutputBuffer(videoEnc, index);
420e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
421e41f4b71Sopenharmony_ci        // Exception handling.
422e41f4b71Sopenharmony_ci    }
423e41f4b71Sopenharmony_ci    ```
424e41f4b71Sopenharmony_ci
425e41f4b71Sopenharmony_ci15. (Optional) Call **OH_VideoEncoder_Flush()** to refresh the encoder.
426e41f4b71Sopenharmony_ci
427e41f4b71Sopenharmony_ci    After **OH_VideoEncoder_Flush** is called, the encoder remains in the Running state, but the input and output data and parameter set (such as the H.264 PPS/SPS) buffered in the encoder are cleared.
428e41f4b71Sopenharmony_ci
429e41f4b71Sopenharmony_ci    To continue encoding, you must call **OH_VideoEncoder_Start** again.
430e41f4b71Sopenharmony_ci
431e41f4b71Sopenharmony_ci    ```c++
432e41f4b71Sopenharmony_ci    // Refresh the encoder.
433e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Flush(videoEnc);
434e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
435e41f4b71Sopenharmony_ci        // Exception handling.
436e41f4b71Sopenharmony_ci    }
437e41f4b71Sopenharmony_ci    // Start encoding again.
438e41f4b71Sopenharmony_ci    ret = OH_VideoEncoder_Start(videoEnc);
439e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
440e41f4b71Sopenharmony_ci        // Exception handling.
441e41f4b71Sopenharmony_ci    }
442e41f4b71Sopenharmony_ci    ```
443e41f4b71Sopenharmony_ci
444e41f4b71Sopenharmony_ci16. (Optional) Call **OH_VideoEncoder_Reset()** to reset the encoder.
445e41f4b71Sopenharmony_ci
446e41f4b71Sopenharmony_ci    After **OH_VideoEncoder_Reset** is called, the encoder returns to the Initialized state. To continue, you must call **OH_VideoEncoder_Configure** and **OH_VideoEncoder_Prepare** again.
447e41f4b71Sopenharmony_ci
448e41f4b71Sopenharmony_ci    ```c++
449e41f4b71Sopenharmony_ci    // Reset the encoder.
450e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Reset(videoEnc);
451e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
452e41f4b71Sopenharmony_ci        // Exception handling.
453e41f4b71Sopenharmony_ci    }
454e41f4b71Sopenharmony_ci    // Reconfigure the encoder.
455e41f4b71Sopenharmony_ci    ret = OH_VideoEncoder_Configure(videoEnc, format);
456e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
457e41f4b71Sopenharmony_ci        // Exception handling.
458e41f4b71Sopenharmony_ci    }
459e41f4b71Sopenharmony_ci    // The encoder is ready again.
460e41f4b71Sopenharmony_ci    ret = OH_VideoEncoder_Prepare(videoEnc);
461e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
462e41f4b71Sopenharmony_ci        // Exception handling.
463e41f4b71Sopenharmony_ci    }
464e41f4b71Sopenharmony_ci    ```
465e41f4b71Sopenharmony_ci
466e41f4b71Sopenharmony_ci17. (Optional) Call **OH_VideoEncoder_Stop()** to stop the encoder.
467e41f4b71Sopenharmony_ci
468e41f4b71Sopenharmony_ci    After **OH_VideoEncoder_Stop** is called, the encoder retains the encoding instance and releases the input and output buffers. You can directly call **OH_VideoEncoder_Start** to continue encoding.
469e41f4b71Sopenharmony_ci
470e41f4b71Sopenharmony_ci    The first **buffer** passed must carry the parameter set, starting from the IDR frame.
471e41f4b71Sopenharmony_ci
472e41f4b71Sopenharmony_ci    ```c++
473e41f4b71Sopenharmony_ci    // Stop the encoder.
474e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Stop(videoEnc);
475e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
476e41f4b71Sopenharmony_ci        // Exception handling.
477e41f4b71Sopenharmony_ci    }
478e41f4b71Sopenharmony_ci    ```
479e41f4b71Sopenharmony_ci
480e41f4b71Sopenharmony_ci18. Call **OH_VideoEncoder_Destroy()** to destroy the encoder instance and release resources.
481e41f4b71Sopenharmony_ci
482e41f4b71Sopenharmony_ci    > **NOTE**
483e41f4b71Sopenharmony_ci    >
484e41f4b71Sopenharmony_ci    > This API cannot be called in the callback function.
485e41f4b71Sopenharmony_ci    > After the call, you must set the encoder to NULL to prevent program errors caused by wild pointers.
486e41f4b71Sopenharmony_ci
487e41f4b71Sopenharmony_ci    ```c++
488e41f4b71Sopenharmony_ci    // Release the nativeWindow instance.
489e41f4b71Sopenharmony_ci    if(nativeWindow != NULL){
490e41f4b71Sopenharmony_ci        int32_t ret = OH_NativeWindow_DestroyNativeWindow(nativeWindow);
491e41f4b71Sopenharmony_ci        nativeWindow = NULL;
492e41f4b71Sopenharmony_ci    }
493e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
494e41f4b71Sopenharmony_ci        // Exception handling.
495e41f4b71Sopenharmony_ci    }
496e41f4b71Sopenharmony_ci    // Call OH_VideoEncoder_Destroy to destroy the encoder.
497e41f4b71Sopenharmony_ci    if (videoEnc != NULL) {
498e41f4b71Sopenharmony_ci        ret = OH_VideoEncoder_Destroy(videoEnc);
499e41f4b71Sopenharmony_ci        videoEnc = NULL;
500e41f4b71Sopenharmony_ci    }
501e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
502e41f4b71Sopenharmony_ci        // Exception handling.
503e41f4b71Sopenharmony_ci    }
504e41f4b71Sopenharmony_ci    ```
505e41f4b71Sopenharmony_ci
506e41f4b71Sopenharmony_ci### Buffer Input
507e41f4b71Sopenharmony_ci
508e41f4b71Sopenharmony_ciThe 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.
509e41f4b71Sopenharmony_ciCurrently, the VideoEncoder module supports only data rotation in asynchronous mode.
510e41f4b71Sopenharmony_ci
511e41f4b71Sopenharmony_ci1. Add the header files.
512e41f4b71Sopenharmony_ci
513e41f4b71Sopenharmony_ci    ```cpp
514e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avcodec_videoencoder.h>
515e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avcapability.h>
516e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avcodec_base.h>
517e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avformat.h>
518e41f4b71Sopenharmony_ci    #include <multimedia/player_framework/native_avbuffer.h>
519e41f4b71Sopenharmony_ci    #include <fstream>
520e41f4b71Sopenharmony_ci    ```
521e41f4b71Sopenharmony_ci
522e41f4b71Sopenharmony_ci2. Create an encoder instance.
523e41f4b71Sopenharmony_ci
524e41f4b71Sopenharmony_ci    The procedure is the same as that in surface mode and is not described here.
525e41f4b71Sopenharmony_ci
526e41f4b71Sopenharmony_ci    ```c++
527e41f4b71Sopenharmony_ci    // Create an encoder by name. 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.
528e41f4b71Sopenharmony_ci    OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
529e41f4b71Sopenharmony_ci    const char *codecName = OH_AVCapability_GetName(capability);
530e41f4b71Sopenharmony_ci    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByName(codecName);
531e41f4b71Sopenharmony_ci    ```
532e41f4b71Sopenharmony_ci
533e41f4b71Sopenharmony_ci    ```c++
534e41f4b71Sopenharmony_ci    // Create an encoder by MIME type. Only specific codecs recommended by the system can be created in this way.
535e41f4b71Sopenharmony_ci    // If multiple codecs need to be created, create hardware encoder instances first. If the hardware resources are insufficient, create software encoder instances.
536e41f4b71Sopenharmony_ci    OH_AVCodec *videoEnc = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
537e41f4b71Sopenharmony_ci    ```
538e41f4b71Sopenharmony_ci
539e41f4b71Sopenharmony_ci3. Call **OH_VideoEncoder_RegisterCallback()** to register the callback functions.
540e41f4b71Sopenharmony_ci
541e41f4b71Sopenharmony_ci    Register the **OH_AVCodecCallback** struct that defines the following callback function pointers:
542e41f4b71Sopenharmony_ci    - **OH_AVCodecOnError**, a callback used to report a codec operation error. For details about the error codes, see [OH_AVCodecOnError](../../reference/apis-avcodec-kit/_codec_base.md#oh_avcodeconerror).
543e41f4b71Sopenharmony_ci    - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, format change.
544e41f4b71Sopenharmony_ci    - **OH_AVCodecOnNeedInputBuffer**, a callback used to report input data required, which means that the encoder is ready for receiving YUV/RGB data.
545e41f4b71Sopenharmony_ci    - **OH_AVCodecOnNewOutputBuffer**, a callback used to report output data generated, which means that encoding is complete.
546e41f4b71Sopenharmony_ci
547e41f4b71Sopenharmony_ci    You need to process the callback functions to ensure that the encoder runs properly.
548e41f4b71Sopenharmony_ci
549e41f4b71Sopenharmony_ci    <!--RP2--><!--RP2End-->
550e41f4b71Sopenharmony_ci
551e41f4b71Sopenharmony_ci    <!--RP9-->
552e41f4b71Sopenharmony_ci    ```c++
553e41f4b71Sopenharmony_ci    bool isFirstFrame = true;
554e41f4b71Sopenharmony_ci    ```
555e41f4b71Sopenharmony_ci    <!--RP9End-->
556e41f4b71Sopenharmony_ci    
557e41f4b71Sopenharmony_ci    ```c++
558e41f4b71Sopenharmony_ci    // Implement the OH_AVCodecOnError callback function.
559e41f4b71Sopenharmony_ci    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
560e41f4b71Sopenharmony_ci    {
561e41f4b71Sopenharmony_ci        // Process the error code in the callback.
562e41f4b71Sopenharmony_ci        (void)codec;
563e41f4b71Sopenharmony_ci        (void)errorCode;
564e41f4b71Sopenharmony_ci        (void)userData;
565e41f4b71Sopenharmony_ci    }
566e41f4b71Sopenharmony_ci    ```
567e41f4b71Sopenharmony_ci    
568e41f4b71Sopenharmony_ci    ```c++
569e41f4b71Sopenharmony_ci    // Implement the OH_AVCodecOnStreamChanged callback function.
570e41f4b71Sopenharmony_ci    static void OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
571e41f4b71Sopenharmony_ci    {
572e41f4b71Sopenharmony_ci        // This callback is useless in encoding scenarios.
573e41f4b71Sopenharmony_ci        (void)codec;
574e41f4b71Sopenharmony_ci        (void)format;
575e41f4b71Sopenharmony_ci        (void)userData;
576e41f4b71Sopenharmony_ci    }
577e41f4b71Sopenharmony_ci    ```
578e41f4b71Sopenharmony_ci    
579e41f4b71Sopenharmony_ci    ```c++
580e41f4b71Sopenharmony_ci    // Implement the OH_AVCodecOnNeedInputBuffer callback function.
581e41f4b71Sopenharmony_ci    static void OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
582e41f4b71Sopenharmony_ci    {
583e41f4b71Sopenharmony_ci        // The index of the input frame buffer is sent to InIndexQueue.
584e41f4b71Sopenharmony_ci        // The input frame data (specified by buffer) is sent to InBufferQueue.
585e41f4b71Sopenharmony_ci        // Obtain the video width stride and height stride.
586e41f4b71Sopenharmony_ci        if (isFirstFrame) {
587e41f4b71Sopenharmony_ci            OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(codec);
588e41f4b71Sopenharmony_ci            OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, &widthStride);
589e41f4b71Sopenharmony_ci            OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, &heightStride);
590e41f4b71Sopenharmony_ci            OH_AVFormat_Destroy(format);
591e41f4b71Sopenharmony_ci            isFirstFrame = false;
592e41f4b71Sopenharmony_ci        }
593e41f4b71Sopenharmony_ci        // Process the data.
594e41f4b71Sopenharmony_ci        // Write the image to encode.
595e41f4b71Sopenharmony_ci        // Notify the encoder of EOS.
596e41f4b71Sopenharmony_ci    }
597e41f4b71Sopenharmony_ci    ```
598e41f4b71Sopenharmony_ci    
599e41f4b71Sopenharmony_ci    <!--RP10-->
600e41f4b71Sopenharmony_ci    ```c++
601e41f4b71Sopenharmony_ci    // Implement the OH_AVCodecOnNewOutputBuffer callback function.
602e41f4b71Sopenharmony_ci    static void OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
603e41f4b71Sopenharmony_ci    {
604e41f4b71Sopenharmony_ci        // The index of the output frame buffer is sent to outIndexQueue.
605e41f4b71Sopenharmony_ci        // The encoded frame data (specified by buffer) is sent to outBufferQueue.
606e41f4b71Sopenharmony_ci        // Process the data.
607e41f4b71Sopenharmony_ci        // Release the encoded frame.
608e41f4b71Sopenharmony_ci    }
609e41f4b71Sopenharmony_ci    ```
610e41f4b71Sopenharmony_ci    <!--RP10End-->
611e41f4b71Sopenharmony_ci    
612e41f4b71Sopenharmony_ci    ```c++
613e41f4b71Sopenharmony_ci    // Call OH_VideoEncoder_RegisterCallback() to register the callback functions.
614e41f4b71Sopenharmony_ci    OH_AVCodecCallback cb = {&OnError, &OnStreamChanged, &OnNeedInputBuffer, &OnNewOutputBuffer};
615e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_RegisterCallback(videoEnc, cb, NULL);
616e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
617e41f4b71Sopenharmony_ci        // Exception handling.
618e41f4b71Sopenharmony_ci    }
619e41f4b71Sopenharmony_ci    ```
620e41f4b71Sopenharmony_ci
621e41f4b71Sopenharmony_ci    > **NOTE**
622e41f4b71Sopenharmony_ci    >
623e41f4b71Sopenharmony_ci    > In the callback functions, pay attention to multi-thread synchronization for operations on the data queue.
624e41f4b71Sopenharmony_ci    >
625e41f4b71Sopenharmony_ci
626e41f4b71Sopenharmony_ci4. Call **OH_VideoEncoder_Configure()** to configure the encoder.
627e41f4b71Sopenharmony_ci
628e41f4b71Sopenharmony_ci    The procedure is the same as that in surface mode and is not described here.
629e41f4b71Sopenharmony_ci
630e41f4b71Sopenharmony_ci    ```c++
631e41f4b71Sopenharmony_ci    OH_AVFormat *format = OH_AVFormat_Create();
632e41f4b71Sopenharmony_ci    // Set the format.
633e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, width);
634e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, height);
635e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT);
636e41f4b71Sopenharmony_ci    // Configure the encoder.
637e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Configure(videoEnc, format);
638e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
639e41f4b71Sopenharmony_ci        // Exception handling.
640e41f4b71Sopenharmony_ci    }
641e41f4b71Sopenharmony_ci    OH_AVFormat_Destroy(format);
642e41f4b71Sopenharmony_ci    ```
643e41f4b71Sopenharmony_ci
644e41f4b71Sopenharmony_ci5. Call **OH_VideoEncoder_Prepare()** to prepare internal resources for the encoder.
645e41f4b71Sopenharmony_ci
646e41f4b71Sopenharmony_ci    ```c++
647e41f4b71Sopenharmony_ci    ret = OH_VideoEncoder_Prepare(videoEnc);
648e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
649e41f4b71Sopenharmony_ci        // Exception handling.
650e41f4b71Sopenharmony_ci    }
651e41f4b71Sopenharmony_ci    ```
652e41f4b71Sopenharmony_ci
653e41f4b71Sopenharmony_ci6. Call **OH_VideoEncoder_Start()** to start the encoder.
654e41f4b71Sopenharmony_ci
655e41f4b71Sopenharmony_ci    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.
656e41f4b71Sopenharmony_ci
657e41f4b71Sopenharmony_ci    ```c++
658e41f4b71Sopenharmony_ci    // Configure the paths of the input and output files.
659e41f4b71Sopenharmony_ci    std::string_view inputFilePath = "/*yourpath*.yuv";
660e41f4b71Sopenharmony_ci    std::string_view outputFilePath = "/*yourpath*.h264";
661e41f4b71Sopenharmony_ci    std::unique_ptr<std::ifstream> inputFile = std::make_unique<std::ifstream>();
662e41f4b71Sopenharmony_ci    std::unique_ptr<std::ofstream> outputFile = std::make_unique<std::ofstream>();
663e41f4b71Sopenharmony_ci    inputFile->open(inputFilePath.data(), std::ios::in | std::ios::binary);
664e41f4b71Sopenharmony_ci    outputFile->open(outputFilePath.data(), std::ios::out | std::ios::binary | std::ios::ate);
665e41f4b71Sopenharmony_ci    // Start the encoder.
666e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_Start(videoEnc);
667e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
668e41f4b71Sopenharmony_ci        // Exception handling.
669e41f4b71Sopenharmony_ci    }
670e41f4b71Sopenharmony_ci    ```
671e41f4b71Sopenharmony_ci
672e41f4b71Sopenharmony_ci7. (Optional) Dynamically configure encoder parameters during running.
673e41f4b71Sopenharmony_ci
674e41f4b71Sopenharmony_ci   <!--RP11-->
675e41f4b71Sopenharmony_ci    ```c++
676e41f4b71Sopenharmony_ci    OH_AVFormat *format = OH_AVFormat_Create();
677e41f4b71Sopenharmony_ci    // Dynamically request IDR frames.
678e41f4b71Sopenharmony_ci    OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, true);
679e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_SetParameter(videoEnc, format);
680e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
681e41f4b71Sopenharmony_ci        // Exception handling.
682e41f4b71Sopenharmony_ci    }
683e41f4b71Sopenharmony_ci    OH_AVFormat_Destroy(format);
684e41f4b71Sopenharmony_ci    ```
685e41f4b71Sopenharmony_ci    <!--RP11End-->
686e41f4b71Sopenharmony_ci
687e41f4b71Sopenharmony_ci8. Call **OH_VideoEncoder_PushInputBuffer()** to push the image to the input queue for encoding.
688e41f4b71Sopenharmony_ci
689e41f4b71Sopenharmony_ci    In the code snippet below, the following variables are used:
690e41f4b71Sopenharmony_ci
691e41f4b71Sopenharmony_ci    - **buffer**: parameter passed in by the callback function **OnNeedInputBuffer**. You can call **OH_AVBuffer_GetAddr()** to obtain the pointer to the shared memory address.
692e41f4b71Sopenharmony_ci    - **index**: parameter passed by the callback function **OnNeedInputBuffer**, which uniquely corresponds to the buffer.
693e41f4b71Sopenharmony_ci    - **flags**: type of the buffer flag. For details, see [OH_AVCodecBufferFlags](../../reference/apis-avcodec-kit/_core.md#oh_avcodecbufferflags).
694e41f4b71Sopenharmony_ci    - **stride**: stride of the obtained buffer data.
695e41f4b71Sopenharmony_ci
696e41f4b71Sopenharmony_ci    ```c++
697e41f4b71Sopenharmony_ci    if (stride == width) {
698e41f4b71Sopenharmony_ci        // Process the file stream and obtain the frame length, and then write the data to encode to the buffer of the specified index.
699e41f4b71Sopenharmony_ci        int32_t frameSize = width * height * 3 / 2; // Formula for calculating the data size of each frame in NV12 pixel format.
700e41f4b71Sopenharmony_ci        inputFile->read(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(buffer)), frameSize);
701e41f4b71Sopenharmony_ci    } else {
702e41f4b71Sopenharmony_ci        // If the stride is not equal to the width, perform offset based on the stride. For details, see the following example.
703e41f4b71Sopenharmony_ci    }
704e41f4b71Sopenharmony_ci    // Configure the buffer information.
705e41f4b71Sopenharmony_ci    OH_AVCodecBufferAttr info;
706e41f4b71Sopenharmony_ci    info.size = frameSize;
707e41f4b71Sopenharmony_ci    info.offset = 0;
708e41f4b71Sopenharmony_ci    info.pts = 0;
709e41f4b71Sopenharmony_ci    info.flags = flags;
710e41f4b71Sopenharmony_ci    ret = OH_AVBuffer_SetBufferAttr(buffer, &info);
711e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
712e41f4b71Sopenharmony_ci        // Exception handling.
713e41f4b71Sopenharmony_ci    }
714e41f4b71Sopenharmony_ci    // Send the data to the input buffer for encoding. index is the index of the buffer.
715e41f4b71Sopenharmony_ci    int32_t ret = OH_VideoEncoder_PushInputBuffer(videoEnc, index);
716e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
717e41f4b71Sopenharmony_ci        // Exception handling.
718e41f4b71Sopenharmony_ci    }
719e41f4b71Sopenharmony_ci    ```
720e41f4b71Sopenharmony_ci    Offset the stride. The following uses an NV12 image as an example, presenting the image layout of **width**, **height**, **wStride**, and **hStride**.
721e41f4b71Sopenharmony_ci
722e41f4b71Sopenharmony_ci    - **OH_MD_KEY_VIDEO_PIC_WIDTH** corresponds to **width**.
723e41f4b71Sopenharmony_ci    - **OH_MD_KEY_VIDEO_PIC_HEIGHT** corresponds to **height**.
724e41f4b71Sopenharmony_ci    - **OH_MD_KEY_VIDEO_STRIDE** corresponds to **wStride**.
725e41f4b71Sopenharmony_ci    - **OH_MD_KEY_VIDEO_SLICE_HEIGHT** corresponds to **hStride**.
726e41f4b71Sopenharmony_ci
727e41f4b71Sopenharmony_ci    ![copy by line](figures/copy-by-line.png)
728e41f4b71Sopenharmony_ci
729e41f4b71Sopenharmony_ci    Add the header files.
730e41f4b71Sopenharmony_ci
731e41f4b71Sopenharmony_ci    ```c++
732e41f4b71Sopenharmony_ci    #include <string.h>
733e41f4b71Sopenharmony_ci    ```
734e41f4b71Sopenharmony_ci    The following is the sample code:
735e41f4b71Sopenharmony_ci
736e41f4b71Sopenharmony_ci    ```c++
737e41f4b71Sopenharmony_ci    struct Rect // Width and height of the source buffer. They are set by the caller.
738e41f4b71Sopenharmony_ci    {
739e41f4b71Sopenharmony_ci        int32_t width;
740e41f4b71Sopenharmony_ci        int32_t height;
741e41f4b71Sopenharmony_ci    };
742e41f4b71Sopenharmony_ci
743e41f4b71Sopenharmony_ci    struct DstRect // Width stride and height stride of the destination buffer. They are obtained by calling OnNeedInputBuffer.
744e41f4b71Sopenharmony_ci    {
745e41f4b71Sopenharmony_ci        int32_t wStride;
746e41f4b71Sopenharmony_ci        int32_t hStride;
747e41f4b71Sopenharmony_ci    };
748e41f4b71Sopenharmony_ci
749e41f4b71Sopenharmony_ci    struct SrcRect // Width stride and height stride of the source buffer. They are set by the caller.
750e41f4b71Sopenharmony_ci    {
751e41f4b71Sopenharmony_ci        int32_t wStride;
752e41f4b71Sopenharmony_ci        int32_t hStride;
753e41f4b71Sopenharmony_ci    };
754e41f4b71Sopenharmony_ci
755e41f4b71Sopenharmony_ci    Rect rect = {320, 240};
756e41f4b71Sopenharmony_ci    DstRect dstRect = {320, 250};
757e41f4b71Sopenharmony_ci    SrcRect srcRect = {320, 250};
758e41f4b71Sopenharmony_ci    uint8_t* dst = new uint8_t[dstRect.hStride * dstRect.wStride]; // Pointer to the target memory area.
759e41f4b71Sopenharmony_ci    uint8_t* src = new uint8_t[srcRect.hStride * srcRect.wStride]; // Pointer to the source memory area.
760e41f4b71Sopenharmony_ci
761e41f4b71Sopenharmony_ci    // Y: Copy the source data in the Y region to the target data in another region.
762e41f4b71Sopenharmony_ci    for (int32_t i = 0; i < rect.height; ++i) {
763e41f4b71Sopenharmony_ci        // Copy a row of data from the source to a row of the target.
764e41f4b71Sopenharmony_ci        memcpy_s(dst, src, rect.width);
765e41f4b71Sopenharmony_ci        // Update the pointers to the source data and target data to copy the next row. The pointers to the source data and target data are moved downwards by one wStride each time the source data and target data are updated.
766e41f4b71Sopenharmony_ci        dst += dstRect.wStride;
767e41f4b71Sopenharmony_ci        src += srcRect.wStride;
768e41f4b71Sopenharmony_ci    }
769e41f4b71Sopenharmony_ci    // padding
770e41f4b71Sopenharmony_ci    // Update the pointers to the source data and target data. The pointers move downwards by one padding.
771e41f4b71Sopenharmony_ci    dst += (dstRect.hStride - rect.height) * dstRect.wStride;
772e41f4b71Sopenharmony_ci    src += (srcRect.hStride - rect.height) * srcRect.wStride;
773e41f4b71Sopenharmony_ci    rect.height >>= 1;
774e41f4b71Sopenharmony_ci    // UV: Copy the source data in the UV region to the target data in another region.
775e41f4b71Sopenharmony_ci    for (int32_t i = 0; i < rect.height; ++i) {
776e41f4b71Sopenharmony_ci        memcpy_s(dst, src, rect.width);
777e41f4b71Sopenharmony_ci        dst += dstRect.wStride;
778e41f4b71Sopenharmony_ci        src += srcRect.wStride;
779e41f4b71Sopenharmony_ci    }
780e41f4b71Sopenharmony_ci
781e41f4b71Sopenharmony_ci    delete[] dst;
782e41f4b71Sopenharmony_ci    dst = nullptr;
783e41f4b71Sopenharmony_ci    delete[] src;
784e41f4b71Sopenharmony_ci    src = nullptr;
785e41f4b71Sopenharmony_ci    ```
786e41f4b71Sopenharmony_ci    When processing buffer data (before pushing data) during hardware encoding, you must copy the image data after width and height alignment to the input callback AVBuffer. Generally, copy the image width, height, stride, and pixel format to ensure correct processing of the data to encode. For details, see step 3 in [Buffer Input](#buffer-input).
787e41f4b71Sopenharmony_ci
788e41f4b71Sopenharmony_ci9. Notify the encoder of EOS.
789e41f4b71Sopenharmony_ci
790e41f4b71Sopenharmony_ci    In the code snippet below, the following variables are used:
791e41f4b71Sopenharmony_ci    - **index**: parameter passed by the callback function **OnNeedInputBuffer**, which uniquely corresponds to the buffer.
792e41f4b71Sopenharmony_ci    - **buffer**: parameter passed in by the callback function **OnNeedInputBuffer**. You can call **OH_AVBuffer_GetAddr()** to obtain the pointer to the shared memory address.
793e41f4b71Sopenharmony_ci
794e41f4b71Sopenharmony_ci    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.
795e41f4b71Sopenharmony_ci
796e41f4b71Sopenharmony_ci    ```c++
797e41f4b71Sopenharmony_ci    OH_AVCodecBufferAttr info;
798e41f4b71Sopenharmony_ci    info.size = 0;
799e41f4b71Sopenharmony_ci    info.offset = 0;
800e41f4b71Sopenharmony_ci    info.pts = 0;
801e41f4b71Sopenharmony_ci    info.flags = AVCODEC_BUFFER_FLAGS_EOS;
802e41f4b71Sopenharmony_ci    int32_t ret = OH_AVBuffer_SetBufferAttr(buffer, &info);
803e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
804e41f4b71Sopenharmony_ci        // Exception handling.
805e41f4b71Sopenharmony_ci    }
806e41f4b71Sopenharmony_ci    ret = OH_VideoEncoder_PushInputBuffer(videoEnc, index);
807e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
808e41f4b71Sopenharmony_ci        // Exception handling.
809e41f4b71Sopenharmony_ci    }
810e41f4b71Sopenharmony_ci    ```
811e41f4b71Sopenharmony_ci
812e41f4b71Sopenharmony_ci10. Call **OH_VideoEncoder_FreeOutputBuffer()** to release encoded frames.
813e41f4b71Sopenharmony_ci    
814e41f4b71Sopenharmony_ci    The procedure is the same as that in surface mode and is not described here.
815e41f4b71Sopenharmony_ci
816e41f4b71Sopenharmony_ci    ```c++
817e41f4b71Sopenharmony_ci    // Obtain the encoded information.
818e41f4b71Sopenharmony_ci    OH_AVCodecBufferAttr info;
819e41f4b71Sopenharmony_ci    int32_t ret = OH_AVBuffer_GetBufferAttr(buffer, &info);
820e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
821e41f4b71Sopenharmony_ci        // Exception handling.
822e41f4b71Sopenharmony_ci    }
823e41f4b71Sopenharmony_ci    // Write the encoded frame data (specified by buffer) to the output file.
824e41f4b71Sopenharmony_ci    outputFile->write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(buffer)), info.size);
825e41f4b71Sopenharmony_ci    // Free the output buffer. index is the index of the buffer.
826e41f4b71Sopenharmony_ci    ret = OH_VideoEncoder_FreeOutputBuffer(videoEnc, index);
827e41f4b71Sopenharmony_ci    if (ret != AV_ERR_OK) {
828e41f4b71Sopenharmony_ci        // Exception handling.
829e41f4b71Sopenharmony_ci    }
830e41f4b71Sopenharmony_ci    ```
831e41f4b71Sopenharmony_ci
832e41f4b71Sopenharmony_ciThe subsequent processes (including refreshing, resetting, stopping, and destroying the encoder) are the same as those in surface mode. For details, see steps 15–18 in [Surface Input](#surface-input).
833