• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Audio Encoding
2
3You can call the native APIs provided by the AudioCodec module to encode audio, that is, to compress audio PCM data into a desired format.
4
5PCM 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.
6
7For details about the supported encoding capabilities, see [AVCodec Supported Formats](avcodec-support-formats.md#audio-encoding).
8
9**Usage Scenario**
10
11- Audio recording
12
13  Record incoming PCM data, encode it into the desired stream format, and then [wrap](audio-video-muxer.md#media-data-muxing) it in the target file format.
14- Audio editing
15
16  When exporting edited PCM data as an audio file, the PCM data must be encoded into the appropriate audio format and then [wrapped](audio-video-muxer.md#media-data-muxing) into a file.
17> **NOTE**
18>
19> AAC encoders adopt the VBR mode by default, which may differ in the configured parameters.
20
21## How to Develop
22
23Read [AudioCodec](../../reference/apis-avcodec-kit/_audio_codec.md) for the API reference.
24
25Refer to the code snippet below to complete the entire audio encoding process, including creating an encoder, setting encoding parameters (such as the sampling rate, bit rate, and number of audio channels), and starting, refreshing, resetting, and destroying the encoder.
26
27During application development, you must call the APIs in the defined sequence. Otherwise, an exception or undefined behavior may occur.
28
29The figure below shows the call relationship of audio encoding.
30
31- The dotted line indicates an optional operation.
32
33- The solid line indicates a mandatory operation.
34
35![Call relationship of audio encoding](figures/audio-codec.png)
36
37### Linking the Dynamic Libraries in the CMake Script
38
39```cmake
40target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
41target_link_libraries(sample PUBLIC libnative_media_core.so)
42target_link_libraries(sample PUBLIC libnative_media_acodec.so)
43```
44
45### How to Develop
46
471. Add the header files.
48
49    ```cpp
50    #include <multimedia/player_framework/native_avcodec_audiocodec.h>
51    #include <multimedia/native_audio_channel_layout.h>
52    #include <multimedia/player_framework/native_avcapability.h>
53    #include <multimedia/player_framework/native_avcodec_base.h>
54    #include <multimedia/player_framework/native_avformat.h>
55    #include <multimedia/player_framework/native_avbuffer.h>
56    ```
57
582. Create an encoder instance. In the code snippet below, **OH_AVCodec *** is the pointer to the encoder instance created.
59
60   You can create an encoder by name or MIME type.
61
62    ```cpp
63    // Namespace of the C++ standard library.
64    using namespace std;
65    // Create an encoder by name.
66    OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true);
67    const char *name = OH_AVCapability_GetName(capability);
68    OH_AVCodec *audioEnc_ = OH_AudioCodec_CreateByName(name);
69    ```
70
71    ```cpp
72    // Specify whether encoding is used. The value true means encoding.
73    bool isEncoder = true;
74    // Create an encoder by MIME type.
75    OH_AVCodec *audioEnc_ = OH_AudioCodec_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_AAC, isEncoder);
76    ```
77
78    ```cpp
79    // Initialize the queues.
80    class AEncBufferSignal {
81    public:
82        std::mutex inMutex_;
83        std::mutex outMutex_;
84        std::mutex startMutex_;
85        std::condition_variable inCond_;
86        std::condition_variable outCond_;
87        std::condition_variable startCond_;
88        std::queue<uint32_t> inQueue_;
89        std::queue<uint32_t> outQueue_;
90        std::queue<OH_AVBuffer *> inBufferQueue_;
91        std::queue<OH_AVBuffer *> outBufferQueue_;
92    };
93    AEncBufferSignal *signal_;
94    ```
95
963. Call **OH_AudioCodec_RegisterCallback()** to register callback functions.
97
98   Register the **OH_AVCodecCallback** struct that defines the following callback function pointers:
99
100   - **OH_AVCodecOnError**, a callback used to report a codec operation error
101   - **OH_AVCodecOnStreamChanged**. This callback is not supported by the audio encoder.
102   - **OH_AVCodecOnNeedInputBuffer**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
103   - **OH_AVCodecOnNewOutputBuffer**, a callback used to report output data generated, which means that encoding is complete
104
105   You need to process the callback functions to ensure that the encoder runs properly.
106
107   > **NOTE**
108   >
109   > You are not advised to perform time-consuming operations in the callback.
110
111    ```cpp
112    // Implement the OH_AVCodecOnError callback function.
113    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
114    {
115        (void)codec;
116        (void)errorCode;
117        (void)userData;
118    }
119    // Implement the OH_AVCodecOnStreamChanged callback function.
120    static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
121    {
122        (void)codec;
123        (void)format;
124        (void)userData;
125    }
126    // Implement the OH_AVCodecOnNeedInputBuffer callback function.
127    static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
128    {
129        (void)codec;
130        // The input stream is sent to the InputBuffer queue.
131        AEncBufferSignal *signal = static_cast<AEncBufferSignal *>(userData);
132        unique_lock<mutex> lock(signal->inMutex_);
133        signal->inQueue_.push(index);
134        signal->inBufferQueue_.push(data);
135        signal->inCond_.notify_all();
136    }
137    // Implement the OH_AVCodecOnNewOutputBuffer callback function.
138    static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
139    {
140        (void)codec;
141        // The index of the output buffer is sent to OutputQueue_.
142        // The encoded data is sent to the outBuffer queue.
143        AEncBufferSignal *signal = static_cast<AEncBufferSignal *>(userData);
144        unique_lock<mutex> lock(signal->outMutex_);
145        signal->outQueue_.push(index);
146        signal->outBufferQueue_.push(data);
147    }
148    signal_ = new AEncBufferSignal();
149    OH_AVCodecCallback cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
150    // Set the asynchronous callbacks.
151    int32_t ret = OH_AudioCodec_RegisterCallback(audioEnc_, cb_, signal_);
152    if (ret != AV_ERR_OK) {
153        // Handle exceptions.
154    }
155    ```
156
1574. Call **OH_AudioCodec_Configure** to configure the encoder.
158
159   The following options are mandatory: sampling rate, bit rate, number of audio channels, audio channel type, and bit depth.
160
161   The maximum input length is optional.
162
163   For FLAC encoding, the compliance level and sampling precision are also mandatory.
164
165   The sample below lists the value range of each audio encoding type.
166   | Audio Encoding Type| Sampling Rate (Hz)                                                                      |       Audio Channel Count      |
167   | ----------- | ------------------------------------------------------------------------------- | :----------------: |
168   | <!--DelRow-->AAC         | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000| 1, 2, 3, 4, 5, 6, and 8|
169   | FLAC       | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000|        1–8        |
170   | MP3         | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000                    |        1–2        |
171   | G711mu      | 8000                                                                            |         1          |
172   <!--RP3--><!--RP3End-->
173
174   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 sampling rate, 2-channel stereo, and SAMPLE_S16LE sampling format.
175
176    <!--RP4-->
177    ```cpp
178    int32_t ret;
179    // (Mandatory) Configure the audio sampling rate.
180    constexpr uint32_t DEFAULT_SAMPLERATE = 44100;
181    // (Mandatory) Configure the audio bit rate.
182    constexpr uint64_t DEFAULT_BITRATE = 32000;
183    // (Mandatory) Configure the number of audio channels.
184    constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2;
185    // (Mandatory) Configure the audio channel type.
186    constexpr OH_AudioChannelLayout CHANNEL_LAYOUT = OH_AudioChannelLayout::CH_LAYOUT_STEREO;
187    // (Mandatory) Configure the audio bit depth.
188    constexpr OH_BitsPerSample SAMPLE_FORMAT = OH_BitsPerSample::SAMPLE_S16LE;
189    // A frame of audio data takes 20 ms.
190    constexpr float TIME_PER_FRAME = 0.02;
191    // (Optional) Configure the maximum input length and the size of each audio frame.
192    constexpr uint32_t DEFAULT_MAX_INPUT_SIZE = DEFAULT_SAMPLERATE * TIME_PER_FRAME * DEFAULT_CHANNEL_COUNT * sizeof(short); // aac
193    OH_AVFormat *format = OH_AVFormat_Create();
194    // Set the format.
195    OH_AVFormat_SetIntValue(format,OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
196    OH_AVFormat_SetIntValue(format,OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE);
197    OH_AVFormat_SetLongValue(format,OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
198    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT);
199    OH_AVFormat_SetLongValue(format,OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT);
200    OH_AVFormat_SetIntValue(format,OH_MD_KEY_MAX_INPUT_SIZE, DEFAULT_MAX_INPUT_SIZE);
201    // Configure the encoder.
202    ret = OH_AudioCodec_Configure(audioEnc_, format);
203    if (ret != AV_ERR_OK) {
204        // Handle exceptions.
205    }
206    ```
207    <!--RP4End-->
208    The following shows the API call process in the case of FLAC encoding.
209
210    ```cpp
211    int32_t ret;
212    // (Mandatory) Configure the audio sampling rate.
213    constexpr uint32_t DEFAULT_SAMPLERATE = 44100;
214    // (Mandatory) Configure the audio bit rate.
215    constexpr uint64_t DEFAULT_BITRATE = 261000;
216    // (Mandatory) Configure the number of audio channels.
217    constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2;
218    // (Mandatory) Configure the audio channel type.
219    constexpr OH_AudioChannelLayout CHANNEL_LAYOUT = OH_AudioChannelLayout::CH_LAYOUT_STEREO;
220    // (Mandatory) Configure the audio bit depth. Only SAMPLE_S16LE and SAMPLE_S32LE are available for FLAC encoding.
221    constexpr OH_BitsPerSample SAMPLE_FORMAT = OH_BitsPerSample::SAMPLE_S32LE;
222    // Configure the audio compliance level. The default value is 0, and the value ranges from -2 to 2.
223    constexpr int32_t COMPLIANCE_LEVEL = 0;
224    // (Mandatory) Configure the audio sampling precision. SAMPLE_S16LE, SAMPLE_S24LE, and SAMPLE_S32LE are available.
225    constexpr OH_BitsPerSample BITS_PER_CODED_SAMPLE = OH_BitsPerSample::SAMPLE_S24LE;
226    OH_AVFormat *format = OH_AVFormat_Create();
227    // Set the format.
228    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
229    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE);
230    OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
231    OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITS_PER_CODED_SAMPLE, BITS_PER_CODED_SAMPLE);
232    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT);
233    OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT);
234    OH_AVFormat_SetLongValue(format, OH_MD_KEY_COMPLIANCE_LEVEL, COMPLIANCE_LEVEL);
235    // Configure the encoder.
236    ret = OH_AudioCodec_Configure(audioEnc_, format);
237    if (ret != AV_ERR_OK) {
238        // Handle exceptions.
239    }
240    ```
241
242    <!--RP2--><!--RP2End-->
243
2445. Call **OH_AudioCodec_Prepare()** to prepare internal resources for the encoder.
245
246    ```cpp
247    ret = OH_AudioCodec_Prepare(audioEnc_);
248    if (ret != AV_ERR_OK) {
249        // Handle exceptions.
250    }
251    ```
252
2536. Call **OH_AudioCodec_Start()** to start the encoder.
254
255    ```c++
256    unique_ptr<ifstream> inputFile_ = make_unique<ifstream>();
257    unique_ptr<ofstream> outFile_ = make_unique<ofstream>();
258    // Open the path of the binary file to be encoded. (A PCM file is used as an example.)
259    inputFile_->open(inputFilePath.data(), ios::in | ios::binary);
260    // Configure the path of the output file. (An encoded stream file is used as an example.)
261    outFile_->open(outputFilePath.data(), ios::out | ios::binary);
262    // Start encoding.
263    ret = OH_AudioCodec_Start(audioEnc_);
264    if (ret != AV_ERR_OK) {
265        // Handle exceptions.
266    }
267    ```
268
2697. Call **OH_AudioCodec_PushInputBuffer()** to write the data to encode. You should fill in complete input data before calling this API.
270
271   Set **SAMPLES_PER_FRAME** as follows:
272
273   For AAC encoding, set **SAMPLES_PER_FRAME** to the number of PCM samples every 20 ms, that is, sampling rate x 0.02.
274
275   For FLAC encoding, set **SAMPLES_PER_FRAME** based on the table below.
276
277   | Sampling Rate| Sample Count|
278   | :----: | :----: |
279   |  8000  |  576  |
280   | 16000 |  1152  |
281   | 22050 |  2304  |
282   | 24000 |  2304  |
283   | 32000 |  2304  |
284   | 44100 |  4608  |
285   | 48000 |  4608  |
286   | 88200 |  8192  |
287   | 96000 |  8192  |
288
289   > **NOTE**
290   >
291   > It is recommended that **SAMPLES_PER_FRAME** in AAC encoding be the number of PCM samples every 20 ms, that is, sampling rate x 0.02. In the case of FLAC encoding, if the number of samples is greater than the corresponding value provided in the table, an error code is returned. If the number is less than the corresponding value provided in the table, the encoded file may be damaged.
292
293   ```c++
294    // Number of samples per frame.
295    constexpr int32_t SAMPLES_PER_FRAME = DEFAULT_SAMPLERATE * TIME_PER_FRAME;
296    // Number of audio channels. For AMR encoding, only mono audio input is supported.
297    constexpr int32_t DEFAULT_CHANNEL_COUNT = 2;
298    // Length of the input data of each frame, that is, number of audio channels x number of samples per frame x number of bytes per sample (SAMPLE_S16LE used as an example).
299    // If the last frame of data does not meet the required length,you are advised to discard it or add padding.
300    constexpr int32_t INPUT_FRAME_BYTES = DEFAULT_CHANNEL_COUNT * SAMPLES_PER_FRAME * sizeof(short);
301    uint32_t index = signal_->inQueue_.front();
302    auto buffer = signal_->inBufferQueue_.front();
303    OH_AVCodecBufferAttr attr = {0};
304    if (!inputFile_->eof()) {
305        inputFile_->read((char *)OH_AVBuffer_GetAddr(buffer), INPUT_FRAME_BYTES);
306        attr.size = INPUT_FRAME_BYTES;
307        attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
308    } else {
309        attr.size = 0;
310        attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
311    }
312    OH_AVBuffer_SetBufferAttr(buffer, &attr);
313    // Send the data to the input queue for encoding. The index is the subscript of the queue.
314    ret = OH_AudioCodec_PushInputBuffer(audioEnc_, index);
315    if (ret != AV_ERR_OK) {
316        // Handle exceptions.
317    }
318    ```
319   In the preceding example, **attr.flags** indicates the type of the buffer flag.
320
321   To indicate the End of Stream (EOS), pass in the **AVCODEC_BUFFER_FLAGS_EOS** flag.
322
323   | Value| Description|
324   | -------- | -------- |
325   | AVCODEC_BUFFER_FLAGS_NONE | Common frame.|
326   | AVCODEC_BUFFER_FLAGS_EOS | The buffer is an end-of-stream frame.|
327   | AVCODEC_BUFFER_FLAGS_CODEC_DATA | The buffer contains codec-specific data.|
328
3298. Call **OH_AudioCodec_FreeOutputBuffer()** to release the encoded data.
330
331   Once you have retrieved the encoded stream, call **OH_AudioCodec_FreeOutputBuffer()** to free up the data.
332
333    ```c++
334    uint32_t index = signal_->outQueue_.front();
335    OH_AVBuffer *avBuffer = signal_->outBufferQueue_.front();
336    // Obtain the buffer attributes.
337    OH_AVCodecBufferAttr attr = {0};
338    ret = OH_AVBuffer_GetBufferAttr(avBuffer, &attr);
339    if (ret != AV_ERR_OK) {
340        // Handle exceptions.
341    }
342    // Write the encoded data (specified by data) to the output file.
343    outputFile_->write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(avBuffer)), attr.size);
344    // Release the output buffer.
345    ret = OH_AudioCodec_FreeOutputBuffer(audioEnc_, index);
346    if (ret != AV_ERR_OK) {
347        // Handle exceptions.
348    }
349    if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
350        // End.
351    }
352    ```
353
3549. (Optional) Call **OH_AudioCodec_Flush()** to refresh the encoder.
355
356   After **OH_AudioCodec_Flush()** is called, the current encoding queue is cleared.
357
358   To continue encoding, you must call **OH_AudioCodec_Start()** again.
359
360   You need to call **OH_AudioCodec_Flush()** in the following cases:
361
362   * The EOS of the file is reached.
363   * An error with **OH_AudioCodec_IsValid** set to **true** (indicating that the execution can continue) occurs.
364
365    ```c++
366    // Refresh the encoder.
367    ret = OH_AudioCodec_Flush(audioEnc_);
368    if (ret != AV_ERR_OK) {
369        // Handle exceptions.
370    }
371    // Start encoding again.
372    ret = OH_AudioCodec_Start(audioEnc_);
373    if (ret != AV_ERR_OK) {
374        // Handle exceptions.
375    }
376    ```
377
37810. (Optional) Call **OH_AudioCodec_Reset()** to reset the encoder.
379
380    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()**.
381
382    ```c++
383    // Reset the encoder.
384    ret = OH_AudioCodec_Reset(audioEnc_);
385    if (ret != AV_ERR_OK) {
386        // Handle exceptions.
387    }
388    // Reconfigure the encoder.
389    ret = OH_AudioCodec_Configure(audioEnc_, format);
390    if (ret != AV_ERR_OK) {
391        // Handle exceptions.
392    }
393    ```
394
39511. Call **OH_AudioCodec_Stop()** to stop the encoder.
396
397    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.
398
399    ```c++
400    // Stop the encoder.
401    ret = OH_AudioCodec_Stop(audioEnc_);
402    if (ret != AV_ERR_OK) {
403        // Handle exceptions.
404    }
405    ```
406
40712. Call **OH_AudioCodec_Destroy()** to destroy the encoder instance and release resources.
408
409    > **NOTE**
410    >
411    > You only need to call the API once.
412
413    ```c++
414    // Call OH_AudioCodec_Destroy to destroy the encoder.
415    ret = OH_AudioCodec_Destroy(audioEnc_);
416    if (ret != AV_ERR_OK) {
417        // Handle exceptions.
418    } else {
419        audioEnc_ = NULL; // The encoder cannot be destroyed repeatedly.
420    }
421    ```
422