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