• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![Call relationship of synchronous audio encoding](figures/synchronous-audio.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> **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