1# Synchronous Audio Encoding 2 3<!--Kit: AVCodec Kit--> 4<!--Subsystem: Multimedia--> 5<!--Owner: @mr-chencxy--> 6<!--Designer: @dpy2650---> 7<!--Tester: @baotianhao--> 8<!--Adviser: @zengyawen--> 9 10Starting from API version 20, audio encoding in synchronous mode is supported. 11 12You can call native APIs to perform audio encoding, which compresses audio PCM data into a desired format. 13 14PCM data can be from any source. For example, you can use a microphone to record audio data or import edited PCM data. After audio encoding, you can output streams in the desired format and encapsulate the streams into a target file. 15 16For details about the supported encoding capabilities, see [AVCodec Supported Formats](avcodec-support-formats.md#audio-encoding). 17 18**When to Use** 19 20Asynchronous mode is generally recommended for most use cases. For details, see [Audio Encoding](audio-encoding.md). Synchronous mode can be used if you need to actively request buffers for PCM encoding. 21- Audio recording 22 23 Record PCM data, encode it into the desired format, and then multiplex it in the target file format. For details about multiplexing, see [Media Data Multiplexing](audio-video-muxer.md). 24- Audio editing 25 26 Export edited PCM data, encode it into the corresponding audio format, and then multiplex it into a file. For details about multiplexing, see [Media Data Multiplexing](audio-video-muxer.md). 27> **NOTE** 28> 29> AAC encoders adopt the VBR mode by default. This may result in differences from the expected bit rate. 30 31## Development Guidelines 32 33Read [AudioCodec](../../reference/apis-avcodec-kit/_audio_codec.md) for the API reference. 34 35Refer to the code snippet below to complete the entire audio encoding process, including creating an encoder, setting encoding parameters (such as the sample rate, bit rate, and audio channel count), and starting, refreshing, resetting, and destroying the encoder. 36 37During application development, you must call the APIs in the defined sequence. Otherwise, an exception or undefined behavior may occur. 38 39The figure below shows the call relationship of audio encoding in synchronous mode. 40 41- The dotted line indicates an optional operation. Audio encoding does not involve decryption. Therefore, you do not need to call **OH_AudioCodec_SetDecryptionConfig**. 42 43- The solid line indicates a mandatory operation. 44 45 46 47### Linking the Dynamic Libraries in the CMake Script 48 49```cmake 50target_link_libraries(sample PUBLIC libnative_media_codecbase.so) 51target_link_libraries(sample PUBLIC libnative_media_core.so) 52target_link_libraries(sample PUBLIC libnative_media_acodec.so) 53``` 54> **NOTE** 55> 56> The word **sample** in the preceding code snippet is only an example. Use the actual project directory name. 57 58### How to Develop 59 601. Add the header files and namespace. 61 62 ```cpp 63 #include <multimedia/player_framework/native_avcodec_audiocodec.h> 64 #include <multimedia/native_audio_channel_layout.h> 65 #include <multimedia/player_framework/native_avcapability.h> 66 #include <multimedia/player_framework/native_avcodec_base.h> 67 #include <multimedia/player_framework/native_avformat.h> 68 #include <multimedia/player_framework/native_avbuffer.h> 69 70 // Namespace of the C++ standard library. 71 using namespace std; 72 ``` 73 742. Create an encoder instance. In the code snippet below, **OH_AVCodec *** is the pointer to the encoder instance created. 75 76 You can create an encoder by MIME type or codec name. 77 78 Method 1: Create an encoder by MIME type. 79 ```cpp 80 // Create an encoder by MIME type. The following example creates an AAC encoder. The second parameter is set to true to indicate encoding. 81 OH_AVCodec *audioEnc_ = OH_AudioCodec_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true); 82 ``` 83 Method 2: Create an encoder by codec name. 84 ```cpp 85 // Create an encoder by name. 86 OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true); 87 const char *name = OH_AVCapability_GetName(capability); 88 OH_AVCodec *audioEnc_ = OH_AudioCodec_CreateByName(name); 89 ``` 90 913. Call **OH_AudioCodec_Configure** to configure the encoder. 92 93 Key values of configuration options are described as follows: 94 95 <!--RP1--> 96 | Key | Description | AAC | FLAC| MPEG (MP3) | G711mu | 97 | ----------------------------- | :--------------: | :---: | :---: | :------: | :---: | 98 | OH_MD_KEY_AUD_SAMPLE_RATE | Sample rate. | Mandatory | Mandatory| Mandatory | Mandatory | 99 | OH_MD_KEY_AUD_CHANNEL_COUNT | Audio channel count. | Mandatory | Mandatory| Mandatory | Mandatory | 100 | OH_MD_KEY_AUDIO_SAMPLE_FORMAT | Output audio stream format. | Mandatory | Mandatory| Mandatory | Mandatory | 101 | OH_MD_KEY_BITRATE | Bit rate. | Optional | Mandatory| Mandatory | - | 102 | OH_MD_KEY_CHANNEL_LAYOUT | Audio channel layout. | Optional | Mandatory| - | - | 103 | OH_MD_KEY_MAX_INPUT_SIZE | Maximum input size. | Optional | Optional| Optional | Optional | 104 | OH_MD_KEY_AAC_IS_ADTS | ADTS or not. | Optional | - | - | - | 105 | OH_MD_KEY_COMPLIANCE_LEVEL | Compatibility level. | - | Optional| - | - | 106 <!--RP1End--> 107 108 The sample below lists the value range of each audio encoding type. 109 | Audio Encoding Type| Sample Rate (Hz) | Audio Channel Count | 110 | ----------- | ------------------------------------------------------------------------------- | :----------------: | 111 | <!--DelRow-->AAC | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000| 1, 2, 3, 4, 5, 6, and 8| 112 | FLAC | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000| 1–8 | 113 | MP3 | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 | 1–2 | 114 | G711mu | 8000 | 1 | 115 <!--RP2--><!--RP2End--> 116 117 The code snippet below shows the API call process, where AAC encoding at the bit rate of 32000 bit/s is carried out on the PCM audio with the 44100 Hz sample rate, 2-channel stereo, and SAMPLE_S16LE sample format. 118 <!--RP3--> 119 ```cpp 120 OH_AVErrCode ret; 121 // (Mandatory) Configure the audio sample rate. 122 constexpr uint32_t DEFAULT_SAMPLERATE = 44100; 123 // (Mandatory) Configure the audio bit rate. 124 constexpr uint64_t DEFAULT_BITRATE = 32000; 125 // (Mandatory) Configure the audio channel count. 126 constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2; 127 // (Mandatory) Configure the audio bit depth. 128 constexpr OH_BitsPerSample SAMPLE_FORMAT = OH_BitsPerSample::SAMPLE_S16LE; 129 // (Optional) Configure the layout of audio channels. 130 constexpr OH_AudioChannelLayout CHANNEL_LAYOUT = OH_AudioChannelLayout::CH_LAYOUT_STEREO; 131 132 OH_AVFormat *format = OH_AVFormat_Create(); 133 // Set the format. 134 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT); 135 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE); 136 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE); 137 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT); 138 OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT); 139 OH_AVFormat_SetIntValue(format, OH_MD_KEY_ENABLE_SYNC_MODE, 1); // Set the synchronous mode. 140 // Configure the encoder. 141 ret = OH_AudioCodec_Configure(audioEnc_, format); 142 if (ret != AV_ERR_OK) { 143 // Handle exceptions. 144 } 145 ``` 146 <!--RP3End--> 147 FLAC encoding example: 148 149 ```cpp 150 OH_AVErrCode ret; 151 // (Mandatory) Configure the audio sample rate. 152 constexpr uint32_t DEFAULT_SAMPLERATE = 44100; 153 // (Mandatory) Configure the audio bit rate. 154 constexpr uint64_t DEFAULT_BITRATE = 261000; 155 // (Mandatory) Configure the audio channel count. 156 constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2; 157 // (Mandatory) Configure the layout of audio channels. 158 // The value can be CH_LAYOUT_MONO, CH_LAYOUT_STEREO, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0, CH_LAYOUT_5POINT1, CH_LAYOUT_6POINT1, or CH_LAYOUT_7POINT1. 159 constexpr OH_AudioChannelLayout CHANNEL_LAYOUT = OH_AudioChannelLayout::CH_LAYOUT_STEREO; 160 // (Mandatory) Configure the audio bit depth. Only SAMPLE_S16LE and SAMPLE_S32LE are available for FLAC encoding. 161 constexpr OH_BitsPerSample SAMPLE_FORMAT = OH_BitsPerSample::SAMPLE_S32LE; 162 // Configure the audio compliance level. The default value is 0, and the value range is [-2,2]. 163 constexpr int32_t COMPLIANCE_LEVEL = 0; 164 165 OH_AVFormat *format = OH_AVFormat_Create(); 166 // Set the format. 167 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT); 168 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE); 169 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE); 170 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT); 171 OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT); 172 OH_AVFormat_SetLongValue(format, OH_MD_KEY_COMPLIANCE_LEVEL, COMPLIANCE_LEVEL); 173 OH_AVFormat_SetIntValue(format, OH_MD_KEY_ENABLE_SYNC_MODE, 1); // Set the synchronous mode. 174 // Configure the encoder. 175 ret = OH_AudioCodec_Configure(audioEnc_, format); 176 if (ret != AV_ERR_OK) { 177 // Handle exceptions. 178 } 179 ``` 180 1814. Call **OH_AudioCodec_Prepare()** to prepare internal resources for the encoder. 182 183 ```cpp 184 OH_AVErrCode ret = OH_AudioCodec_Prepare(audioEnc_); 185 if (ret != AV_ERR_OK) { 186 // Handle exceptions. 187 } 188 ``` 189 1905. Call **OH_AudioCodec_Start()** to start the encoder. 191 192 Add the header file. 193 ```c++ 194 #include <fstream> 195 ``` 196 The sample code is as follows: 197 ```c++ 198 ifstream inputFile_; 199 ofstream outFile_; 200 201 // Set the input file path based on the actual situation. 202 const char* inputFilePath = "/"; 203 // Set the output file path based on the actual situation. 204 const char* outputFilePath = "/"; 205 // Open the path of the binary file to be encoded. (A PCM file is used as an example.) 206 inputFile_.open(inputFilePath, ios::in | ios::binary); 207 // Set the path of the output file. (In this example, the output file is an encoded stream file, instead of a playable audio file. To create a playable audio file, you must encapsulate the audio bit stream into a container). 208 outFile_.open(outputFilePath, ios::out | ios::binary); 209 // Start encoding. 210 OH_AVErrCode ret = OH_AudioCodec_Start(audioEnc_); 211 if (ret != AV_ERR_OK) { 212 // Handle exceptions. 213 } 214 ``` 215 2166. Invoke synchronous mode to write PCM samples to encode and obtain the encoded audio frames. 217 218 The method for determining the number of samples per frame (**SAMPLES_PER_FRAME**) is as follows: 219 220 AAC-LC encodes 1024 PCM samples per frame. Therefore, you are advised to input exactly 1024 samples at a time. 221 222 <!--RP4--><!--RP4End--> 223 224 For FLAC encoding, set **SAMPLES_PER_FRAME** based on the table below. 225 226 | Sample Rate| Sample Count| 227 | :----: | :----: | 228 | 8000 | 576 | 229 | 16000 | 1152 | 230 | 22050 | 2304 | 231 | 24000 | 2304 | 232 | 32000 | 2304 | 233 | 44100 | 4608 | 234 | 48000 | 4608 | 235 | 88200 | 8192 | 236 | 96000 | 8192 | 237 238 Data volume (in bytes) of a single encoding input: Number of samples (**SAMPLES_PER_FRAME**) * Number of channels * Number of bytes per sample. 239 240 The sample code is as follows: 241 ```c++ 242 int32_t SAMPLES_PER_FRAME = 1024; 243 // AAC LC encoding involves 1024 samples per frame, 2 channels, and uses S16LE format for the input data. Each 16-bit sample occupies 2 bytes. 244 int32_t inputFrameBytes = SAMPLES_PER_FRAME * 2 * 2; 245 bool inputFinished = false; 246 OH_AVErrCode ret; 247 OH_AVCodecBufferAttr attr; 248 249 for (;;) { 250 uint32_t index = 0; 251 if (!inputFinished) { 252 ret = OH_AudioCodec_QueryInputBuffer(audioEnc_, &index, 20000); // 20000us 253 if (ret == AV_ERR_TRY_AGAIN_LATER) { 254 continue; 255 } 256 if (ret != AV_ERR_OK) { 257 // Handle exceptions. 258 break; 259 } 260 OH_AVBuffer *inputBuf = OH_AudioCodec_GetInputBuffer(audioEnc_, index); 261 if (inputBuf == nullptr) { 262 // Handle exceptions. 263 break; 264 } 265 memset(&attr, 0, sizeof(attr)); 266 if (!inputFile_.eof()) { 267 inputFile_.read((char *)OH_AVBuffer_GetAddr(inputBuf), inputFrameBytes); 268 int32_t readSize = inputFile_.gcount(); 269 attr.size = readSize; 270 attr.flags = readSize != 0 ? AVCODEC_BUFFER_FLAGS_NONE : AVCODEC_BUFFER_FLAGS_EOS; 271 } else { 272 inputFinished = true; 273 attr.size = 0; 274 attr.flags = AVCODEC_BUFFER_FLAGS_EOS; 275 } 276 if (OH_AVBuffer_SetBufferAttr(inputBuf, &attr) != AV_ERR_OK) { 277 // Handle exceptions. 278 } 279 if (OH_AudioCodec_PushInputBuffer(audioEnc_, index) != AV_ERR_OK) { 280 // Handle exceptions. 281 } 282 } 283 // If the input data can generate multiple encoded frames, you need to call the output buffer several times to obtain all the encoded data. 284 ret = OH_AudioCodec_QueryOutputBuffer(audioEnc_, &index, 20000); // 20000us 285 if (ret == AV_ERR_TRY_AGAIN_LATER) { 286 // Timeout: There is not enough input data to encode a frame, or the timeout period is too short. 287 continue; 288 } 289 if (ret != AV_ERR_OK) { 290 // Handle exceptions. 291 break; 292 } 293 OH_AVBuffer *outputBuf = OH_AudioCodec_GetOutputBuffer(audioEnc_, index); 294 if (outputBuf == nullptr) { 295 // Handle exceptions. 296 break; 297 } 298 if (OH_AVBuffer_GetBufferAttr(outputBuf, &attr) != AV_ERR_OK) { 299 // Handle exceptions. 300 break; 301 } 302 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) { 303 // The output ends. 304 break; 305 } 306 // In this example, the data is written to a file for logging purposes. To encapsulate the data into an audio file, call OH_AVMuxer_WriteSampleBuffer. 307 outFile_.write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(outputBuf)), attr.size); 308 OH_AudioCodec_FreeOutputBuffer(audioEnc_, index); 309 } 310 ``` 311 312 In the preceding example, **attr.flags** indicates the type of the buffer flag. 313 314 To indicate the End of Stream (EOS), pass in the **AVCODEC_BUFFER_FLAGS_EOS** flag. 315 316 | Value| Description| 317 | -------- | -------- | 318 | AVCODEC_BUFFER_FLAGS_NONE | Common frame.| 319 | AVCODEC_BUFFER_FLAGS_EOS | The buffer is an end-of-stream frame.| 320 | AVCODEC_BUFFER_FLAGS_CODEC_DATA | The buffer contains codec-specific data.| 321 3227. (Optional) Call **OH_AudioCodec_Reset()** to reset the encoder. 323 324 After **OH_AudioCodec_Reset()** is called, the encoder returns to the initialized state. To continue encoding, you must call **OH_AudioCodec_Configure()** and then **OH_AudioCodec_Start()**. 325 326 ```c++ 327 // Reset the encoder. 328 OH_AVErrCode ret = OH_AudioCodec_Reset(audioEnc_); 329 if (ret != AV_ERR_OK) { 330 // Handle exceptions. 331 } 332 // Reconfigure the encoder. 333 ret = OH_AudioCodec_Configure(audioEnc_, format); 334 if (ret != AV_ERR_OK) { 335 // Handle exceptions. 336 } 337 ``` 338 3398. (Optional) Call **OH_AudioCodec_Stop()** to stop the encoder. 340 341 After the encoder is stopped, you can call **Start** to start it again. If you have passed specific data in the previous **Start** for the encoder, you must pass it again. 342 343 ```c++ 344 // Stop the encoder. 345 OH_AVErrCode ret = OH_AudioCodec_Stop(audioEnc_); 346 if (ret != AV_ERR_OK) { 347 // Handle exceptions. 348 } 349 ``` 350 3519. Call **OH_AudioCodec_Destroy()** to destroy the encoder instance and release resources. 352 353 > **NOTE** 354 > 355 > You only need to call this API once. 356 357 ```c++ 358 // Call OH_AudioCodec_Destroy to destroy the encoder. 359 OH_AVErrCode ret = OH_AudioCodec_Destroy(audioEnc_); 360 if (ret != AV_ERR_OK) { 361 // Handle exceptions. 362 } else { 363 audioEnc_ = NULL; // The encoder cannot be destroyed repeatedly. 364 } 365 ``` 366