• 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
7Currently, the following encoding capabilities are supported:
8
9| Container Format| Audio Encoding Type      |
10| -------- | :--------------- |
11| mp4      | AAC, FLAC       |
12| m4a      | AAC              |
13| flac     | FLAC            |
14| aac      | AAC              |
15| mp3      | MP3              |
16| raw      | G711mu           |
17<!--RP1--><!--RP1End-->
18
19**Usage Scenario**
20
21- Audio recording
22
23  Record and pass in PCM data, and encode the data into streams in the desired format.
24- Audio editing
25
26  Export edited PCM data, and encode the data into streams in the desired format.
27> **NOTE**
28>
29> AAC encoders adopt the VBR mode by default, which may differ in the configured parameters.
30
31## How to Develop
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 sampling rate, bit rate, and number of audio channels), 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.
40
41- The dotted line indicates an optional operation.
42
43- The solid line indicates a mandatory operation.
44
45![Call relationship of audio encoding](figures/audio-codec.png)
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
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 name or MIME type.
71
72    ```cpp
73    // Namespace of the C++ standard library.
74    using namespace std;
75    // Create an encoder by name.
76    OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, true);
77    const char *name = OH_AVCapability_GetName(capability);
78    OH_AVCodec *audioEnc_ = OH_AudioCodec_CreateByName(name);
79    ```
80
81    ```cpp
82    // Specify whether encoding is used. The value true means encoding.
83    bool isEncoder = true;
84    // Create an encoder by MIME type.
85    OH_AVCodec *audioEnc_ = OH_AudioCodec_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_AAC, isEncoder);
86    ```
87
88    ```cpp
89    // Initialize the queues.
90    class AEncBufferSignal {
91    public:
92        std::mutex inMutex_;
93        std::mutex outMutex_;
94        std::mutex startMutex_;
95        std::condition_variable inCond_;
96        std::condition_variable outCond_;
97        std::condition_variable startCond_;
98        std::queue<uint32_t> inQueue_;
99        std::queue<uint32_t> outQueue_;
100        std::queue<OH_AVBuffer *> inBufferQueue_;
101        std::queue<OH_AVBuffer *> outBufferQueue_;
102    };
103    AEncBufferSignal *signal_;
104    ```
105
1063. Call **OH_AudioCodec_RegisterCallback()** to register callback functions.
107
108   Register the **OH_AVCodecCallback** struct that defines the following callback function pointers:
109
110   - **OH_AVCodecOnError**, a callback used to report a codec operation error
111   - **OH_AVCodecOnStreamChanged**, a callback used to report a codec stream change, for example, audio channel change
112   - **OH_AVCodecOnNeedInputBuffer**, a callback used to report input data required, which means that the encoder is ready for receiving PCM data
113   - **OH_AVCodecOnNewOutputBuffer**, a callback used to report output data generated, which means that encoding is complete
114
115   You need to process the callback functions to ensure that the encoder runs properly.
116
117    ```cpp
118    // Implement the OH_AVCodecOnError callback function.
119    static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
120    {
121        (void)codec;
122        (void)errorCode;
123        (void)userData;
124    }
125    // Implement the OH_AVCodecOnStreamChanged callback function.
126    static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
127    {
128        (void)codec;
129        (void)format;
130        (void)userData;
131    }
132    // Implement the OH_AVCodecOnNeedInputBuffer callback function.
133    static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
134    {
135        (void)codec;
136        // The input stream is sent to the InputBuffer queue.
137        AEncBufferSignal *signal = static_cast<AEncBufferSignal *>(userData);
138        unique_lock<mutex> lock(signal->inMutex_);
139        signal->inQueue_.push(index);
140        signal->inBufferQueue_.push(data);
141        signal->inCond_.notify_all();
142    }
143    // Implement the OH_AVCodecOnNewOutputBuffer callback function.
144    static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
145    {
146        (void)codec;
147        // The index of the output buffer is sent to OutputQueue_.
148        // The encoded data is sent to the outBuffer queue.
149        AEncBufferSignal *signal = static_cast<AEncBufferSignal *>(userData);
150        unique_lock<mutex> lock(signal->outMutex_);
151        signal->outQueue_.push(index);
152        signal->outBufferQueue_.push(data);
153    }
154    signal_ = new AEncBufferSignal();
155    OH_AVCodecCallback cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
156    // Set the asynchronous callbacks.
157    int32_t ret = OH_AudioCodec_RegisterCallback(audioEnc_, cb_, signal_);
158    if (ret != AV_ERR_OK) {
159        // Exception handling.
160    }
161    ```
162
1634. Call **OH_AudioCodec_Configure** to configure the encoder.
164
165   The following options are mandatory: sampling rate, bit rate, number of audio channels, audio channel type, and bit depth.
166
167   The maximum input length is optional.
168
169   For FLAC encoding, the compliance level and sampling precision are also mandatory.
170
171   The sample below lists the value range of each audio encoding type.
172   | Audio Encoding Type| Sampling Rate (Hz)                                                                      |       Audio Channel Count      |
173   | ----------- | ------------------------------------------------------------------------------- | :----------------: |
174   | AAC         | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000| 1, 2, 3, 4, 5, 6, and 8|
175   | FLAC       | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000|        1–8        |
176   | MP3         | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000                    |        1–2        |
177   | G711mu      | 8000                                                                            |         1          |
178   <!--RP3--><!--RP3End-->
179
180   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.
181
182    ```cpp
183    int32_t ret;
184    // (Mandatory) Configure the audio sampling rate.
185    constexpr uint32_t DEFAULT_SAMPLERATE = 44100;
186    // (Mandatory) Configure the audio bit rate.
187    constexpr uint64_t DEFAULT_BITRATE = 32000;
188    // (Mandatory) Configure the number of audio channels.
189    constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2;
190    // (Mandatory) Configure the audio channel type.
191    constexpr OH_AudioChannelLayout CHANNEL_LAYOUT = OH_AudioChannelLayout::CH_LAYOUT_STEREO;
192    // (Mandatory) Configure the audio bit depth.
193    constexpr OH_BitsPerSample SAMPLE_FORMAT = OH_BitsPerSample::SAMPLE_S16LE;
194    // Configure the audio compliance level. The default value is 0, and the value ranges from -2 to 2.
195    constexpr int32_t COMPLIANCE_LEVEL = 0;
196    // (Mandatory) Configure the audio sampling precision (SAMPLE_S16LE used as an example).
197    constexpr OH_BitsPerSample BITS_PER_CODED_SAMPLE = OH_BitsPerSample::SAMPLE_S16LE;
198    // A frame of audio data takes 20 ms.
199    constexpr float TIME_PER_FRAME = 0.02;
200    // (Optional) Configure the maximum input length and the size of each frame of audio data.
201    constexpr uint32_t DEFAULT_MAX_INPUT_SIZE = DEFAULT_SAMPLERATE * TIME_PER_FRAME * DEFAULT_CHANNEL_COUNT * sizeof(short); // aac
202    OH_AVFormat *format = OH_AVFormat_Create();
203    // Set the format.
204    OH_AVFormat_SetIntValue(format,OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
205    OH_AVFormat_SetIntValue(format,OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE);
206    OH_AVFormat_SetLongValue(format,OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
207    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT);
208    OH_AVFormat_SetLongValue(format,OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT);
209    OH_AVFormat_SetIntValue(format,OH_MD_KEY_MAX_INPUT_SIZE, DEFAULT_MAX_INPUT_SIZE);
210    // Configure the encoder.
211    ret = OH_AudioCodec_Configure(audioEnc_, format);
212    if (ret != AV_ERR_OK) {
213        // Exception handling.
214    }
215    ```
216
217    The following shows the API call process in the case of FLAC encoding.
218
219    ```cpp
220    int32_t ret;
221    // (Mandatory) Configure the audio sampling rate.
222    constexpr uint32_t DEFAULT_SAMPLERATE = 44100;
223    // (Mandatory) Configure the audio bit rate.
224    constexpr uint64_t DEFAULT_BITRATE = 261000;
225    // (Mandatory) Configure the number of audio channels.
226    constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2;
227    // (Mandatory) Configure the audio channel type.
228    constexpr OH_AudioChannelLayout CHANNEL_LAYOUT = OH_AudioChannelLayout::CH_LAYOUT_STEREO;
229    // (Mandatory) Configure the audio bit depth. Only SAMPLE_S16LE and SAMPLE_S32LE are available for FLAC encoding.
230    constexpr OH_BitsPerSample SAMPLE_FORMAT = OH_BitsPerSample::SAMPLE_S32LE;
231    // Configure the audio compliance level. The default value is 0, and the value ranges from -2 to 2.
232    constexpr int32_t COMPLIANCE_LEVEL = 0;
233    // (Mandatory) Configure the audio sampling precision. SAMPLE_S16LE, SAMPLE_S24LE, and SAMPLE_S32LE are available.
234    constexpr OH_BitsPerSample BITS_PER_CODED_SAMPLE = OH_BitsPerSample::SAMPLE_S24LE;
235    OH_AVFormat *format = OH_AVFormat_Create();
236    // Set the format.
237    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
238    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE);
239    OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
240    OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITS_PER_CODED_SAMPLE, BITS_PER_CODED_SAMPLE);
241    OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_FORMAT);
242    OH_AVFormat_SetLongValue(format, OH_MD_KEY_CHANNEL_LAYOUT, CHANNEL_LAYOUT);
243    OH_AVFormat_SetLongValue(format, OH_MD_KEY_COMPLIANCE_LEVEL, COMPLIANCE_LEVEL);
244    // Configure the encoder.
245    ret = OH_AudioCodec_Configure(audioEnc_, format);
246    if (ret != AV_ERR_OK) {
247        // Exception handling.
248    }
249    ```
250
251    <!--RP2--><!--RP2End-->
252
2535. Call **OH_AudioCodec_Prepare()** to prepare internal resources for the encoder.
254
255    ```cpp
256    ret = OH_AudioCodec_Prepare(audioEnc_);
257    if (ret != AV_ERR_OK) {
258        // Exception handling.
259    }
260    ```
261
2626. Call **OH_AudioCodec_Start()** to start the encoder.
263
264    ```c++
265    unique_ptr<ifstream> inputFile_ = make_unique<ifstream>();
266    unique_ptr<ofstream> outFile_ = make_unique<ofstream>();
267    // Open the path of the binary file to be encoded. (A PCM file is used as an example.)
268    inputFile_->open(inputFilePath.data(), ios::in | ios::binary);
269    // Configure the path of the output file. (An encoded stream file is used as an example.)
270    outFile_->open(outputFilePath.data(), ios::out | ios::binary);
271    // Start encoding.
272    ret = OH_AudioCodec_Start(audioEnc_);
273    if (ret != AV_ERR_OK) {
274        // Exception handling.
275    }
276    ```
277
2787. Call **OH_AudioCodec_PushInputBuffer()** to write the data to encode.
279
280   To indicate the End of Stream (EOS), pass in the **AVCODEC_BUFFER_FLAGS_EOS** flag.
281
282   For AAC encoding, set **SAMPLES_PER_FRAME** to the number of PCM samples every 20 ms, that is, sampling rate x 0.02.
283
284   For FLAC encoding, set **SAMPLES_PER_FRAME** based on the table below.
285
286   | Sampling Rate| Sample Count|
287   | :----: | :----: |
288   |  8000  |  576  |
289   | 16000 |  1152  |
290   | 22050 |  2304  |
291   | 24000 |  2304  |
292   | 32000 |  2304  |
293   | 44100 |  4608  |
294   | 48000 |  4608  |
295   | 88200 |  8192  |
296   | 96000 |  8192  |
297
298   > **NOTE**
299   >
300   > 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.
301
302   ```c++
303    // Number of samples per frame.
304    constexpr int32_t SAMPLES_PER_FRAME = DEFAULT_SAMPLERATE * TIME_PER_FRAME;
305    // Number of audio channels. For AMR encoding, only mono audio input is supported.
306    constexpr int32_t DEFAULT_CHANNEL_COUNT = 2;
307    // 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).
308    constexpr int32_t INPUT_FRAME_BYTES = DEFAULT_CHANNEL_COUNT * SAMPLES_PER_FRAME * sizeof(short);
309    uint32_t index = signal_->inQueue_.front();
310    auto buffer = signal_->inBufferQueue_.front();
311    OH_AVCodecBufferAttr attr = {0};
312    if (!inputFile_->eof()) {
313        inputFile_->read((char *)OH_AVBuffer_GetAddr(buffer), INPUT_FRAME_BYTES);
314        attr.size = INPUT_FRAME_BYTES;
315        attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
316    } else {
317        attr.size = 0;
318        attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
319    }
320    OH_AVBuffer_SetBufferAttr(buffer, &attr);
321    // Send the data to the input queue for encoding. The index is the subscript of the queue.
322    ret = OH_AudioCodec_PushInputBuffer(audioEnc_, index);
323    if (ret != AV_ERR_OK) {
324        // Exception handling.
325    }
326    ```
327
3288. Call **OH_AudioCodec_FreeOutputBuffer()** to output the encoded stream.
329
330    ```c++
331    uint32_t index = signal_->outQueue_.front();
332    OH_AVBuffer *avBuffer = signal_->outBufferQueue_.front();
333    // Obtain the buffer attributes.
334    OH_AVCodecBufferAttr attr = {0};
335    ret = OH_AVBuffer_GetBufferAttr(avBuffer, &attr);
336    if (ret != AV_ERR_OK) {
337        // Exception handling.
338    }
339    // Write the encoded data (specified by data) to the output file.
340    outputFile_->write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(avBuffer)), attr.size);
341    // Release the output buffer.
342    ret = OH_AudioCodec_FreeOutputBuffer(audioEnc_, index);
343    if (ret != AV_ERR_OK) {
344        // Exception handling.
345    }
346    if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) {
347        // End
348    }
349    ```
350
3519. (Optional) Call **OH_AudioCodec_Flush()** to refresh the encoder.
352
353   After **OH_AudioCodec_Flush()** is called, the current encoding queue is cleared.
354
355   To continue encoding, you must call **OH_AudioCodec_Start()** again.
356
357   You need to call **OH_AudioCodec_Flush()** in the following cases:
358
359   * The EOS of the file is reached.
360   * An error with **OH_AudioCodec_IsValid** set to **true** (indicating that the execution can continue) occurs.
361
362    ```c++
363    // Refresh the encoder.
364    ret = OH_AudioCodec_Flush(audioEnc_);
365    if (ret != AV_ERR_OK) {
366        // Exception handling.
367    }
368    // Start encoding again.
369    ret = OH_AudioCodec_Start(audioEnc_);
370    if (ret != AV_ERR_OK) {
371        // Exception handling.
372    }
373    ```
374
37510. (Optional) Call **OH_AudioCodec_Reset()** to reset the encoder.
376
377    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()**.
378
379    ```c++
380    // Reset the encoder.
381    ret = OH_AudioCodec_Reset(audioEnc_);
382    if (ret != AV_ERR_OK) {
383        // Exception handling.
384    }
385    // Reconfigure the encoder.
386    ret = OH_AudioCodec_Configure(audioEnc_, format);
387    if (ret != AV_ERR_OK) {
388        // Exception handling.
389    }
390    ```
391
39211. Call **OH_AudioCodec_Stop()** to stop the encoder.
393
394    ```c++
395    // Stop the encoder.
396    ret = OH_AudioCodec_Stop(audioEnc_);
397    if (ret != AV_ERR_OK) {
398        // Exception handling.
399    }
400    ```
401
40212. Call **OH_AudioCodec_Destroy()** to destroy the encoder instance and release resources.
403
404    > **NOTE**
405    >
406    > You only need to call the API once.
407
408    ```c++
409    // Call OH_AudioCodec_Destroy to destroy the encoder.
410    ret = OH_AudioCodec_Destroy(audioEnc_);
411    if (ret != AV_ERR_OK) {
412        // Exception handling.
413    } else {
414        audioEnc_ = NULL; // The encoder cannot be destroyed repeatedly.
415    }
416    ```
417