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 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