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