• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Synchronous Audio Decoding
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 decoding in synchronous mode is supported.
11
12You can call native APIs to perform audio decoding in synchronous mode, which decodes media data into PCM streams.
13
14For details about the supported decoding capabilities, see [AVCodec Supported Formats](avcodec-support-formats.md#audio-decoding).
15
16**When to Use**
17
18Asynchronous mode is generally recommended for most use cases. For details, see [Audio Decoding](audio-decoding.md). Synchronous mode can be used if you need to actively request buffers for frame delivery.
19Decoding an audio/video file into a PCM stream typically involves the following steps: [media data demultiplexing](audio-video-demuxer.md) -> audio decoding.
20
21This guide outlines the audio decoding process: inputting audio frames and decoding them into PCM streams.
22
23## Development Guidelines
24
25Read [AudioCodec](../../reference/apis-avcodec-kit/_audio_codec.md) for the API reference.
26
27Refer to the code snippet below to complete the entire audio decoding process, including creating a decoder, setting decoding parameters (such as the sample rate, bit rate, and audio channel count), and starting, refreshing, resetting, and destroying the decoder.
28
29During application development, you must call the APIs in the defined sequence. Otherwise, an exception or undefined behavior may occur.
30
31The figure below shows the call relationship of audio decoding in synchronous mode.
32
33- The dotted line indicates an optional operation.
34
35- The solid line indicates a mandatory operation.
36
37![Call relationship of synchronous audio decoding](figures/synchronous-audio.png)
38
39### Linking the Dynamic Libraries in the CMake Script
40
41```cmake
42target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
43target_link_libraries(sample PUBLIC libnative_media_core.so)
44target_link_libraries(sample PUBLIC libnative_media_acodec.so)
45```
46> **NOTE**
47>
48> The word **sample** in the preceding code snippet is only an example. Use the actual project directory name.
49
50### How to Develop
51
521. Add the header files and namespace.
53
54    ```cpp
55    #include <multimedia/player_framework/native_avcodec_audiocodec.h>
56    #include <multimedia/native_audio_channel_layout.h>
57    #include <multimedia/player_framework/native_avcapability.h>
58    #include <multimedia/player_framework/native_avcodec_base.h>
59    #include <multimedia/player_framework/native_avformat.h>
60    #include <multimedia/player_framework/native_avbuffer.h>
61
62    // Namespace of the C++ standard library.
63    using namespace std;
64    ```
65
662. Create a decoder instance. In the code snippet below, **OH_AVCodec *** is the pointer to the decoder instance created.
67
68   You can create a decoder by MIME type or codec name.
69
70   Method 1: Create a decoder by MIME type.
71    ```c++
72    // Create a decoder by MIME type. The following example creates an AAC decoder. The second parameter is set to false to indicate decoding.
73    OH_AVCodec *audioDec_ = OH_AudioCodec_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_AAC, false);
74    ```
75   Method 2: Create a decoder by codec name.
76    ```c++
77    // Create a decoder by name.
78    OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_AAC, false);
79    const char *name = OH_AVCapability_GetName(capability);
80    OH_AVCodec *audioDec_ = OH_AudioCodec_CreateByName(name);
81    ```
82
833. (Optional) Call **OH_AudioCodec_SetDecryptionConfig** to set the decryption configuration.
84
85    Call this API after the media key system information is obtained but before **Prepare()** is called. For details about how to obtain such information, see step 4 in [Media Data Demultiplexing](audio-video-demuxer.md).
86
87    For details about DRM APIs, see [DRM](../../reference/apis-drm-kit/capi-drm.md).
88
89     Add the header files.
90
91    ```c++
92#include <multimedia/drm_framework/native_mediakeysystem.h>
93    #include <multimedia/drm_framework/native_mediakeysession.h>
94    #include <multimedia/drm_framework/native_drm_err.h>
95    #include <multimedia/drm_framework/native_drm_common.h>
96    ```
97    Link the dynamic libraries in the CMake script.
98
99    ``` cmake
100target_link_libraries(sample PUBLIC libnative_drm.so)
101    ```
102
103    The sample code is as follows:
104```c++
105    // Create a media key system based on the media key system information. The following uses com.clearplay.drm as an example.
106    MediaKeySystem *system = nullptr;
107    int32_t ret = OH_MediaKeySystem_Create("com.clearplay.drm", &system);
108    if (system == nullptr) {
109        printf("create media key system failed");
110        return;
111    }
112
113    // Create a media key session.
114MediaKeySession *session = nullptr;
115    DRM_ContentProtectionLevel contentProtectionLevel = CONTENT_PROTECTION_LEVEL_SW_CRYPTO;
116    ret = OH_MediaKeySystem_CreateMediaKeySession(system, &contentProtectionLevel, &session);
117    if (ret != DRM_OK) {
118        // If the creation fails, refer to the DRM interface document and check logs.
119        printf("create media key session failed.");
120        return;
121    }
122    if (session == nullptr) {
123        printf("media key session is nullptr.");
124        return;
125    }
126    // Generate a media key request and set the response to the media key request.
127    // Set the decryption configuration, that is, assign the decryption session to the decoder. Currently, audio decryption does not support secure decoders. Therefore, set the secureAudio parameter to false.
128    bool secureAudio = false;
129    ret = OH_AudioCodec_SetDecryptionConfig(audioDec_, session, secureAudio);
130    ```
131
1324. Call **OH_AudioCodec_Configure()** to configure the decoder.
133
134   Key values of configuration options are described as follows:
135
136   |             Key             |       Description      |                AAC                 | FLAC|               Vorbis               | MPEG |       G711mu        |          AMR (AMR-NB and AMR-WB)        | APE |          G711a          |
137   | ---------------------------- | :--------------: | :--------------------------------: | :--: | :--------------------------------: | :--: | :-----------------: | :-------------------------------: | :--: | :----------------------: |
138   | OH_MD_KEY_ENABLE_SYNC_MODE   |   Synchronous mode. It must be set to **1** if synchronization mode is enabled.  | Mandatory for synchronous mode| Mandatory for synchronous mode| Mandatory for synchronous mode| Mandatory for synchronous mode| Mandatory for synchronous mode| Mandatory for synchronous mode| Mandatory for synchronous mode| Mandatory for synchronous mode|
139   | OH_MD_KEY_AUD_SAMPLE_RATE    |      Sample rate.     |                Mandatory               | Mandatory|                Mandatory                | Mandatory|        Mandatory         |                Mandatory               | Mandatory|           Mandatory          |
140   | OH_MD_KEY_AUD_CHANNEL_COUNT  |      Audio channel count.     |                Mandatory               | Mandatory|                Mandatory                | Mandatory|        Mandatory         |                Mandatory               | Mandatory|           Mandatory          |
141   | OH_MD_KEY_MAX_INPUT_SIZE     |    Maximum input size.  |                Optional               | Optional|                Optional                | Optional|        Optional          |               Optional               | Optional|          Optional           |
142   | OH_MD_KEY_AAC_IS_ADTS        |     ADTS or not.    |             Optional (defaults to **1**)            |  -   |                 -                  |  -   |         -             |               -                  |  -  |         -                |
143   | OH_MD_KEY_AUDIO_SAMPLE_FORMAT   |  Output audio stream format. | Optional (SAMPLE_S16LE, SAMPLE_F32LE)| Optional| Optional (SAMPLE_S16LE, SAMPLE_F32LE)|  Optional| Optional (default: SAMPLE_S16LE)| Optional (SAMPLE_S16LE, SAMPLE_F32LE)| Optional| Optional (default: SAMPLE_S16LE)|
144   | OH_MD_KEY_BITRATE               |       Bit rate.     |                Optional               | Optional|                Optional               | Optional|         Optional          |              Optional                | Optional|         Optional          |
145   | OH_MD_KEY_IDENTIFICATION_HEADER |    ID header.   |                 -                  |  -   |    Mandatory (Either this parameter or **MD_KEY_CODEC_CONFIG** must be set.)   |  -   |          -            |                -                  |  -  |           -            |
146   | OH_MD_KEY_SETUP_HEADER          |   Setup header. |                 -                  |  -   |    Mandatory (Either this parameter or **MD_KEY_CODEC_CONFIG** must be set.)   |  -   |          -            |                -                 |  -  |            -            |
147   | OH_MD_KEY_CODEC_CONFIG          | Codec-specific data.|                Optional                |  -   |   Mandatory (Either this parameter or the combination of **MD_KEY_IDENTIFICATION_HEADER** and **MD_KEY_SETUP_HEADER** must be selected.)   |  -   |           -            |                -                 | Optional|           -            |
148
149   The sample below lists the value range of each audio decoding type.
150
151   | Audio Decoding Type|                                          Sample Rate (Hz)                                             | Audio Channel Count|
152   | ----------- | ----------------------------------------------------------------------------------------------  | :----: |
153   | AAC         | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000                |  1–8  |
154   | FLAC       | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000        |  1–8  |
155   | Vorbis      | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000|  1–8  |
156   | MPEG (MP3)   | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000                                    |  1–2  |
157   | G711mu      | 8000                                                                                            |   1    |
158   | AMR (amrnb)  | 8000                                                                                            |   1    |
159   | AMR (amrwb)  | 16000                                                                                           |   1    |
160   | APE         | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000|  1–2  |
161   | G711a       | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000                                    |  1–6  |
162   <!--RP4-->
163   <!--RP4End-->
164
165   ```c++
166   // (Mandatory) Configure the audio sample rate.
167   constexpr uint32_t DEFAULT_SAMPLERATE = 44100;
168   // (Mandatory) Configure the audio channel count.
169   constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2;
170   // Configure whether to use ADTS decoding (optional for AAC decoding).
171   constexpr uint32_t DEFAULT_AAC_TYPE = 1;
172   OH_AVFormat *format = OH_AVFormat_Create();
173   // Set the format.
174   OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE);
175   OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT);
176   OH_AVFormat_SetIntValue(format, OH_MD_KEY_AAC_IS_ADTS, DEFAULT_AAC_TYPE);
177   OH_AVFormat_SetIntValue(format, OH_MD_KEY_ENABLE_SYNC_MODE, 1); // Set synchronous mode.
178   // Configure the decoder.
179   OH_AVErrCode ret = OH_AudioCodec_Configure(audioDec_, format);
180   if (ret != AV_ERR_OK) {
181       // Handle exceptions.
182   }
183   ```
184
1855. Call **OH_AudioCodec_Prepare()** to prepare internal resources for the decoder.
186
187   ```c++
188   OH_AVErrCode ret = OH_AudioCodec_Prepare(audioDec_);
189   if (ret != AV_ERR_OK) {
190       // Handle exceptions.
191   }
192   ```
193
1946. Call **OH_AudioCodec_Start()** to start the decoder.
195
196   Add the header file.
197    ```c++
198    #include <fstream>
199    ```
200
201   The sample code is as follows:
202    ```c++
203    ifstream inputFile_;
204    ofstream outFile_;
205
206    // Set the input file path based on the actual situation. To demonstrate audio decoding, the input file here contains audio frames and related information (not a directly playable audio file).
207    const char* inputFilePath = "/";
208    // Set the output file path based on the actual situation. This guide only demonstrates audio decoding; decoded PCM data is saved to a file without further processing.
209    const char* outputFilePath = "/";
210    // Open the path of the binary file to be decoded.
211    inputFile_.open(inputFilePath, ios::in | ios::binary);
212    // Set the path of the output file.
213    outFile_.open(outputFilePath, ios::out | ios::binary);
214    // Start decoding.
215    OH_AVErrCode ret = OH_AudioCodec_Start(audioDec_);
216    if (ret != AV_ERR_OK) {
217        // Handle exceptions.
218    }
219    ```
220
2217. (Optional) Call **OH_AVCencInfo_SetAVBuffer()** to set the Common Encryption Scheme (CENC) information.
222
223    If the content being played is DRM encrypted and [demultiplexing](audio-video-demuxer.md) is performed by the upper-layer application, call **OH_AVCencInfo_SetAVBuffer()** to set the CENC information to the AVBuffer for media data decryption.
224
225    Add the header file.
226
227    ```c++
228    #include <multimedia/player_framework/native_cencinfo.h>
229    ```
230    Link the dynamic libraries in the CMake script.
231
232    ``` cmake
233    target_link_libraries(sample PUBLIC libnative_media_avcencinfo.so)
234    ```
235
236    The sample code is as follows:
237    ```c++
238    auto buffer = signal_->inBufferQueue_.front();
239    uint32_t keyIdLen = DRM_KEY_ID_SIZE;
240    uint8_t keyId[] = {
241        0xd4, 0xb2, 0x01, 0xe4, 0x61, 0xc8, 0x98, 0x96,
242        0xcf, 0x05, 0x22, 0x39, 0x8d, 0x09, 0xe6, 0x28};
243    uint32_t ivLen = DRM_KEY_IV_SIZE;
244    uint8_t iv[] = {
245        0xbf, 0x77, 0xed, 0x51, 0x81, 0xde, 0x36, 0x3e,
246        0x52, 0xf7, 0x20, 0x4f, 0x72, 0x14, 0xa3, 0x95};
247    uint32_t encryptedBlockCount = 0;
248    uint32_t skippedBlockCount = 0;
249    uint32_t firstEncryptedOffset = 0;
250    uint32_t subsampleCount = 1;
251    DrmSubsample subsamples[1] = { {0x10, 0x16} };
252    // Create a CencInfo instance.
253    OH_AVCencInfo *cencInfo = OH_AVCencInfo_Create();
254    if (cencInfo == nullptr) {
255        // Handle exceptions.
256    }
257    // Set the decryption algorithm.
258    OH_AVErrCode errNo = OH_AVCencInfo_SetAlgorithm(cencInfo, DRM_ALG_CENC_AES_CTR);
259    if (errNo != AV_ERR_OK) {
260        // Handle exceptions.
261    }
262    // Set KeyId and Iv.
263    errNo = OH_AVCencInfo_SetKeyIdAndIv(cencInfo, keyId, keyIdLen, iv, ivLen);
264    if (errNo != AV_ERR_OK) {
265        // Handle exceptions.
266    }
267    // Set the sample information.
268    errNo = OH_AVCencInfo_SetSubsampleInfo(cencInfo, encryptedBlockCount, skippedBlockCount, firstEncryptedOffset,
269        subsampleCount, subsamples);
270    if (errNo != AV_ERR_OK) {
271        // Handle exceptions.
272    }
273    // Set the mode. KeyId, Iv, and SubSamples have been set.
274    errNo = OH_AVCencInfo_SetMode(cencInfo, DRM_CENC_INFO_KEY_IV_SUBSAMPLES_SET);
275    if (errNo != AV_ERR_OK) {
276        // Handle exceptions.
277    }
278    // Set CencInfo to the AVBuffer.
279    errNo = OH_AVCencInfo_SetAVBuffer(cencInfo, buffer);
280    if (errNo != AV_ERR_OK) {
281        // Handle exceptions.
282    }
283    // Destroy the CencInfo instance.
284    errNo = OH_AVCencInfo_Destroy(cencInfo);
285    if (errNo != AV_ERR_OK) {
286        // Handle exceptions.
287    }
288    ```
289
2908. Invoke synchronous mode to write the data to decode and obtain the decoded output.
291
292   Read data:
293   ```c++
294   // size is the length of each frame of the data to decode. pts is the timestamp of each frame and is used to indicate when the audio should be played.
295   // The values of size and pts are obtained from an audio and video resource file or data stream to decode.
296   // In the case of an audio and video resource file, the values are obtained from the buffer in the demultiplexed OH_AVDemuxer_ReadSampleBuffer.
297   // In the case of a data stream, the values are obtained from the data stream provider.
298   // In this example, the values of size and pts are obtained from the test file.
299   bool DecoderFillInputBuffer(OH_AVBuffer *buffer, ifstream &inputFile)
300   {
301       OH_AVCodecBufferAttr attr;
302       memset(&attr, 0, sizeof(attr));
303       attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
304       bool finished = true;
305       do {
306           int64_t size;
307           inputFile.read(reinterpret_cast<char *>(&size), sizeof(size));
308           if (inputFile.eof() || inputFile.gcount() != sizeof(size)) {
309               break;
310           }
311           inputFile.read(reinterpret_cast<char *>(&attr.pts), sizeof(attr.pts));
312           if (inputFile.gcount() != sizeof(attr.pts)) {
313               break;
314           }
315           attr.size = static_cast<int32_t>(size);
316           if (attr.size > 0) {
317               inputFile.read((char *)OH_AVBuffer_GetAddr(buffer), attr.size);
318               attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
319               finished = false;
320           }
321       } while (0);
322       OH_AVBuffer_SetBufferAttr(buffer, &attr);
323       return finished;
324   }
325   bool InputOneFrame(OH_AVCodec *codec, ifstream &inputFile)
326   {
327       uint32_t index = 0;
328       bool finished = true;
329       OH_AVErrCode ret = OH_AudioCodec_QueryInputBuffer(codec, &index, 20000); // 20000us
330       if (ret == AV_ERR_TRY_AGAIN_LATER) {
331           // Timeout: exception handling. The timeout period is too short, or input/output buffers are not consumed/released (causing decoding blocking).
332           return finished;
333       }
334       if (ret != AV_ERR_OK) {
335           // Handle exceptions.
336           return finished;
337       }
338       OH_AVBuffer *inputBuf = OH_AudioCodec_GetInputBuffer(codec, index);
339       if (inputBuf == nullptr) {
340           // Handle exceptions.
341           return finished;
342       }
343       finished = DecoderFillInputBuffer(inputBuf, inputFile);
344       OH_AudioCodec_PushInputBuffer(codec, index);
345       return finished;
346   }
347
348   ```
349
350   You should fill in complete input data before calling this API.
351
352   When finished, set the flags to **AVCODEC_BUFFER_FLAGS_EOS**.
353
354    ```c++
355    bool inputFinished = false;
356    for (;;) {
357        if (!inputFinished) {
358            inputFinished = InputOneFrame(audioDec_, inputFile_);
359        }
360        uint32_t index;
361        OH_AVErrCode ret = OH_AudioCodec_QueryOutputBuffer(audioDec_, &index, 20000); // 20000us
362        if (ret == AV_ERR_TRY_AGAIN_LATER) {
363            // Timeout: exception handling. The timeout period is too short, or input/output buffers are not consumed/released (causing decoding blocking).
364            continue;
365        } else if (ret == AV_ERR_STREAM_CHANGED) {
366            // Callback processing after the decoding output parameters are changed. The application performs processing as required.
367            OH_AVFormat *outFormat = OH_AudioCodec_GetOutputDescription(audioDec_);
368            int32_t sampleRate;
369            int32_t channelCount;
370            int32_t sampleFormat;
371            if (OH_AVFormat_GetIntValue(outFormat, OH_MD_KEY_AUD_SAMPLE_RATE, &sampleRate)) {
372                // Check whether the sample rate changes and perform processing as required.
373            }
374            if (OH_AVFormat_GetIntValue(outFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, &channelCount)) {
375                // Check whether the audio channel count changes and perform processing as required.
376            }
377            if (OH_AVFormat_GetIntValue(outFormat, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, &sampleFormat)) {
378                // Check whether the audio sample format changes and perform processing as required.
379            }
380            continue;
381        }
382        if (ret != AV_ERR_OK) {
383            // Handle exceptions.
384            break;
385        }
386        OH_AVBuffer *outputBuf = OH_AudioCodec_GetOutputBuffer(audioDec_, index);
387        if (outputBuf == nullptr) {
388            // Handle exceptions.
389            break;
390        }
391        OH_AVCodecBufferAttr attr;
392        if (OH_AVBuffer_GetBufferAttr(outputBuf, &attr) != AV_ERR_OK) {
393            // Handle exceptions.
394            break;
395        }
396        if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
397            OH_AudioCodec_FreeOutputBuffer(audioDec_, index);
398            // Decoding output completed.
399            break;
400        }
401        outFile_.write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(outputBuf)), attr.size);
402        OH_AudioCodec_FreeOutputBuffer(audioDec_, index);
403    }
404    ```
405
4069. (Optional) Call **OH_AudioCodec_Flush()** to refresh the decoder.
407
408    After **OH_AudioCodec_Flush()** is called, the decoder remains in the running state, but the current queue is cleared and the buffer storing the decoded data is freed. The input and output buffers obtained before flushing cannot be reused.
409
410    To continue decoding, you must call **OH_AudioCodec_Start()** again.
411
412    You need to call **OH_AudioCodec_Start()** in the following cases:
413    * Previously input data is no longer needed, for example, after seeking during demultiplexing.
414    * The EOS of the file is reached.
415    * An error with **OH_AudioCodec_IsValid** set to **true** (indicating that the execution can continue) occurs.
416
417    ```c++
418    // Refresh the decoder.
419    OH_AVErrCode ret = OH_AudioCodec_Flush(audioDec_);
420    if (ret != AV_ERR_OK) {
421        // Handle exceptions.
422    }
423    // Start decoding again.
424    ret = OH_AudioCodec_Start(audioDec_);
425    if (ret != AV_ERR_OK) {
426        // Handle exceptions.
427    }
428    ```
429
43010. (Optional) Call **OH_AudioCodec_Reset()** to reset the decoder.
431
432    After **OH_AudioCodec_Reset()** is called, the decoder returns to the initialized state. To continue decoding, you must call **OH_AudioCodec_Configure()** and then **OH_AudioCodec_Start()**.
433
434    ```c++
435    // Reset the decoder.
436    OH_AVErrCode ret = OH_AudioCodec_Reset(audioDec_);
437    if (ret != AV_ERR_OK) {
438        // Handle exceptions.
439    }
440    // Reconfigure the decoder.
441    ret = OH_AudioCodec_Configure(audioDec_, format);
442    if (ret != AV_ERR_OK) {
443        // Handle exceptions.
444    }
445    ```
446
44711. Call **OH_AudioCodec_Stop()** to stop the decoder.
448
449    After the decoder is stopped, you can call **OH_AudioCodec_Start()** to start it again. The input and output buffers obtained before the decoder is stopped cannot be reused. You must obtain them again after the decoder is started.
450
451    ```c++
452    // Stop the decoder.
453    OH_AVErrCode ret = OH_AudioCodec_Stop(audioDec_);
454    if (ret != AV_ERR_OK) {
455        // Handle exceptions.
456    }
457    ```
458
45912. Call **OH_AudioCodec_Destroy()** to destroy the decoder instance and release resources.
460
461    > **NOTE**
462    >
463    > You only need to call this API once.
464
465    ```c++
466    // Call OH_AudioCodec_Destroy to destroy the decoder.
467    OH_AVErrCode ret = OH_AudioCodec_Destroy(audioDec_);
468    if (ret != AV_ERR_OK) {
469        // Handle exceptions.
470    } else {
471        audioDec_ = NULL; // The decoder cannot be destroyed repeatedly.
472    }
473    ```
474