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