1# Audio Decoding 2 3You can call the native APIs provided by the AudioCodec module to decode audio, that is, to decode media data into PCM streams. 4 5For details about the supported decoding capabilities, see [AVCodec Supported Formats](avcodec-support-formats.md#audio-decoding). 6 7**Usage Scenario** 8 9- Audio playback 10 11 Decode audio and transmit the data to the speaker for playing. 12- Audio rendering 13 14 Decode audio and transmit the data to the audio processing module for audio rendering. 15- Audio editing 16 17 Decode audio and transmit the data for audio editing (for example, adjusting the playback speed of a channel). Audio editing is performed based on PCM streams. 18> **NOTE** 19> 20> Streams generated in the MP3 audio encoding process cannot be directly decoded through the MP3 audio decoding process. The following process is recommended: PCM stream -> MP3 audio encoding -> muxing -> demuxing -> MP3 audio decoding. 21 22## How to Develop 23 24Read [AudioCodec](../../reference/apis-avcodec-kit/_audio_codec.md) for the API reference. 25 26Refer to the code snippet below to complete the entire audio decoding process, including creating a decoder, setting decoding parameters (such as the sampling rate, bit rate, and number of audio channels), and starting, refreshing, resetting, and destroying the decoder. 27 28During application development, you must call the APIs in the defined sequence. Otherwise, an exception or undefined behavior may occur. 29 30The figure below shows the call relationship of audio decoding. 31 32- The dotted line indicates an optional operation. 33 34- The solid line indicates a mandatory operation. 35 36 37 38### Linking the Dynamic Libraries in the CMake Script 39 40```cmake 41target_link_libraries(sample PUBLIC libnative_media_codecbase.so) 42target_link_libraries(sample PUBLIC libnative_media_core.so) 43target_link_libraries(sample PUBLIC libnative_media_acodec.so) 44``` 45 46### How to Develop 47 481. Add the header files. 49 50 ```cpp 51 #include <multimedia/player_framework/native_avcodec_audiocodec.h> 52 #include <multimedia/native_audio_channel_layout.h> 53 #include <multimedia/player_framework/native_avcapability.h> 54 #include <multimedia/player_framework/native_avcodec_base.h> 55 #include <multimedia/player_framework/native_avformat.h> 56 #include <multimedia/player_framework/native_avbuffer.h> 57 ``` 58 592. Create a decoder instance. In the code snippet below, **OH_AVCodec *** is the pointer to the decoder instance created. 60 61 ```cpp 62 // Namespace of the C++ standard library. 63 using namespace std; 64 // Create a decoder by codec name. 65 OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_AUDIO_MPEG, false); 66 const char *name = OH_AVCapability_GetName(capability); 67 OH_AVCodec *audioDec_ = OH_AudioCodec_CreateByName(name); 68 ``` 69 70 ```cpp 71 // Specify whether encoding is used. The value false means decoding. 72 bool isEncoder = false; 73 // Create a decoder by MIME type. 74 OH_AVCodec *audioDec_ = OH_AudioCodec_CreateByMime(OH_AVCODEC_MIMETYPE_AUDIO_MPEG, isEncoder); 75 ``` 76 77 ```cpp 78 // Initialize the queues. 79 class ADecBufferSignal { 80 public: 81 std::mutex inMutex_; 82 std::mutex outMutex_; 83 std::mutex startMutex_; 84 std::condition_variable inCond_; 85 std::condition_variable outCond_; 86 std::condition_variable startCond_; 87 std::queue<uint32_t> inQueue_; 88 std::queue<uint32_t> outQueue_; 89 std::queue<OH_AVBuffer *> inBufferQueue_; 90 std::queue<OH_AVBuffer *> outBufferQueue_; 91 }; 92 ADecBufferSignal *signal_; 93 ``` 94 953. Call **OH_AudioCodec_RegisterCallback()** to register callback functions. 96 97 Register the **OH_AVCodecCallback** struct that defines the following callback function pointers: 98 99 - **OH_AVCodecOnError**, a callback used to report a codec operation error 100 - **OH_AVCodecOnStreamChanged**, a callback used to report stream information changes, including changes in the sampling rate, number of audio channels, and audio sampling format. The decoding formats that can detect these changes include <!--RP5--><!--RP5End-->AAC, FLAC, MP3, and VORBIS. (This callback is supported since API version 15.) 101 - **OH_AVCodecOnNeedInputBuffer**, a callback used to report input data required, which means that the decoder is ready for receiving data 102 - **OH_AVCodecOnNewOutputBuffer**, a callback used to report output data generated, which means that decoding is complete 103 104 You need to process the callback functions to ensure that the decoder runs properly. 105 106 > **NOTE** 107 > 108 > You are not advised to perform time-consuming operations in the callback. 109 110 ```cpp 111 // Implement the OH_AVCodecOnError callback function. 112 static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData) 113 { 114 (void)codec; 115 (void)errorCode; 116 (void)userData; 117 } 118 // Implement the OH_AVCodecOnStreamChanged callback function. 119 static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData) 120 { 121 (void)codec; 122 (void)userData; 123 // Callback processing after the decoding output parameters are changed. The application performs processing as required. 124 int32_t sampleRate; 125 int32_t channelCount; 126 int32_t sampleFormat; 127 if (OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, &sampleRate)) { 128 // Check whether the sampling rate changes and perform processing as required. 129 } 130 if (OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, &channelCount)) { 131 // Check whether the number of audio channels changes and perform processing as required. 132 } 133 if (OH_AVFormat_GetIntValue(format, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, &sampleFormat)) { 134 // Check whether the audio sampling format changes and perform processing as required. 135 } 136 } 137 // Implement the OH_AVCodecOnNeedInputBuffer callback function. 138 static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData) 139 { 140 (void)codec; 141 ADecBufferSignal *signal = static_cast<ADecBufferSignal *>(userData); 142 unique_lock<mutex> lock(signal->inMutex_); 143 signal->inQueue_.push(index); 144 signal->inBufferQueue_.push(data); 145 signal->inCond_.notify_all(); 146 // The input stream is sent to inBufferQueue_. 147 } 148 // Implement the OH_AVCodecOnNewOutputBuffer callback function. 149 static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData) 150 { 151 (void)codec; 152 ADecBufferSignal *signal = static_cast<ADecBufferSignal *>(userData); 153 unique_lock<mutex> lock(signal->outMutex_); 154 signal->outQueue_.push(index); 155 signal->outBufferQueue_.push(data); 156 signal->outCond_.notify_all(); 157 // The index of the output buffer is sent to outQueue_. 158 // The decoded data is sent to outBufferQueue_. 159 } 160 signal_ = new ADecBufferSignal(); 161 OH_AVCodecCallback cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable}; 162 int32_t ret = OH_AudioCodec_RegisterCallback(audioDec_, cb_, signal_); 163 if (ret != AVCS_ERR_OK) { 164 // Handle exceptions. 165 } 166 ``` 167 1684. (Optional) Call **OH_AudioCodec_SetDecryptionConfig** to set the decryption configuration. 169 170 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 Demuxing](audio-video-demuxer.md). 171 172 For details about DRM APIs, see [DRM](../../reference/apis-drm-kit/_drm.md). 173 174 Add the header files. 175 176 ```c++ 177#include <multimedia/drm_framework/native_mediakeysystem.h> 178 #include <multimedia/drm_framework/native_mediakeysession.h> 179 #include <multimedia/drm_framework/native_drm_err.h> 180 #include <multimedia/drm_framework/native_drm_common.h> 181 ``` 182 Link the dynamic library in the CMake script. 183 184 ``` cmake 185target_link_libraries(sample PUBLIC libnative_drm.so) 186 ``` 187 188 The following is the sample code: 189```c++ 190 // Create a media key system based on the media key system information. The following uses com.clearplay.drm as an example. 191 MediaKeySystem *system = nullptr; 192 int32_t ret = OH_MediaKeySystem_Create("com.clearplay.drm", &system); 193 if (system == nullptr) { 194 printf("create media key system failed"); 195 return; 196 } 197 198 // Create a media key session. 199MediaKeySession *session = nullptr; 200 DRM_ContentProtectionLevel contentProtectionLevel = CONTENT_PROTECTION_LEVEL_SW_CRYPTO; 201 ret = OH_MediaKeySystem_CreateMediaKeySession(system, &contentProtectionLevel, &session); 202 if (ret != DRM_OK) { 203 // If the creation fails, refer to the DRM interface document and check logs. 204 printf("create media key session failed."); 205 return; 206 } 207 if (session == nullptr) { 208 printf("media key session is nullptr."); 209 return; 210 } 211 // Generate a media key request and set the response to the media key request. 212 // Set the decryption configuration, that is, set the decryption session and secure channel flag to the decoder. (Currently, the secure channel is not supported for audio decryption and therefore the secure channel flag should be set to false.) 213 bool secureAudio = false; 214 ret = OH_AudioCodec_SetDecryptionConfig(audioDec_, session, secureAudio); 215 ``` 216 2175. Call **OH_AudioCodec_Configure()** to configure the decoder. 218 219 Key values of configuration options are described as follows: 220 221 | key | Description | AAC | FLAC| Vorbis | MPEG | G711mu | AMR (AMR-NB and AMR-WB) | APE | 222 | ---------------------------- | :--------------: | :--------------------------------: | :--: | :--------------------------------: | :--: | :-----------------: | :-------------------------------: | :--: | 223 | OH_MD_KEY_AUD_SAMPLE_RATE | Sampling rate | Mandatory | Mandatory| Mandatory | Mandatory| Mandatory | Mandatory | Mandatory| 224 | OH_MD_KEY_AUD_CHANNEL_COUNT | Number of audio channels | Mandatory | Mandatory| Mandatory | Mandatory| Mandatory | Mandatory | Mandatory| 225 | OH_MD_KEY_MAX_INPUT_SIZE | Maximum input size | Optional | Optional| Optional | Optional| Optional | Optional | Optional| 226 | OH_MD_KEY_AAC_IS_ADTS | ADTS or not | Optional (defaults to **1**) | - | - | - | - | - | - | 227 | 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| 228 | OH_MD_KEY_BITRATE | Bit rate | Optional | Optional| Optional | Optional| Optional | Optional | Optional| 229 | OH_MD_KEY_IDENTIFICATION_HEADER | ID Header | - | - | Mandatory (Either this parameter or **MD_KEY_CODEC_CONFIG** must be set.) | - | - | - | - | 230 | OH_MD_KEY_SETUP_HEADER | Setup Header | - | - | Mandatory (Either this parameter or **MD_KEY_CODEC_CONFIG** must be set.) | - | - | - | - | 231 | 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| 232 233 The sample below lists the value range of each audio decoding type. 234 235 | Audio Decoding Type| Sampling Rate (Hz) | Audio Channel Count| 236 | ----------- | ---------------------------------------------------------------------------------------------- | :----: | 237 | AAC | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 | 1–8 | 238 | FLAC | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 | 1–8 | 239 | Vorbis | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000| 1–8 | 240 | MPEG (MP3) | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 | 1–2 | 241 | G711mu | 8000 | 1 | 242 | AMR (amrnb) | 8000 | 1 | 243 | AMR (amrwb) | 16000 | 1 | 244 | APE | 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000| 1–2 | 245 <!--RP4--> 246 <!--RP4End--> 247 248 ```cpp 249 // Set the decoding resolution. 250 int32_t ret; 251 // (Mandatory) Configure the audio sampling rate. 252 constexpr uint32_t DEFAULT_SAMPLERATE = 44100; 253 // (Optional) Configure the audio bit rate. 254 constexpr uint32_t DEFAULT_BITRATE = 32000; 255 // (Mandatory) Configure the number of audio channels. 256 constexpr uint32_t DEFAULT_CHANNEL_COUNT = 2; 257 // (Optional) Configure the maximum input length. 258 constexpr uint32_t DEFAULT_MAX_INPUT_SIZE = 1152; 259 // Configure whether to use ADTS decoding (optional for AAC decoding). 260 constexpr uint32_t DEFAULT_AAC_TYPE = 1; 261 OH_AVFormat *format = OH_AVFormat_Create(); 262 // Set the format. 263 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_SAMPLE_RATE, DEFAULT_SAMPLERATE); 264 OH_AVFormat_SetIntValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE); 265 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AUD_CHANNEL_COUNT, DEFAULT_CHANNEL_COUNT); 266 OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, DEFAULT_MAX_INPUT_SIZE); 267 OH_AVFormat_SetIntValue(format, OH_MD_KEY_AAC_IS_ADTS, DEFAULT_AAC_TYPE); 268 // Configure the decoder. 269 ret = OH_AudioCodec_Configure(audioDec_, format); 270 if (ret != AV_ERR_OK) { 271 // Handle exceptions. 272 } 273 ``` 274 2756. Call **OH_AudioCodec_Prepare()** to prepare internal resources for the decoder. 276 277 ```cpp 278 ret = OH_AudioCodec_Prepare(audioDec_); 279 if (ret != AV_ERR_OK) { 280 // Handle exceptions. 281 } 282 ``` 283 2847. Call **OH_AudioCodec_Start()** to start the decoder. 285 286 ```c++ 287 unique_ptr<ifstream> inputFile_ = make_unique<ifstream>(); 288 unique_ptr<ofstream> outFile_ = make_unique<ofstream>(); 289 // Open the path of the binary file to be decoded. 290 inputFile_->open(inputFilePath.data(), ios::in | ios::binary); 291 // Configure the path of the output file. 292 outFile_->open(outputFilePath.data(), ios::out | ios::binary); 293 // Start decoding. 294 ret = OH_AudioCodec_Start(audioDec_); 295 if (ret != AV_ERR_OK) { 296 // Handle exceptions. 297 } 298 ``` 299 3008. (Optional) Call **OH_AVCencInfo_SetAVBuffer()** to set the Common Encryption Scheme (CENC) information. 301 302 If the content being played is DRM encrypted and [demuxing](audio-video-demuxer.md#media-data-demuxing) is performed by the upper-layer application, call **OH_AVCencInfo_SetAVBuffer()** to set the CENC information to the AVBuffer so that the media data can be decrypted in the AVBuffer. 303 304 Add the header file. 305 306 ```c++ 307 #include <multimedia/player_framework/native_cencinfo.h> 308 ``` 309 Link the dynamic library in the CMake script. 310 311 ``` cmake 312 target_link_libraries(sample PUBLIC libnative_media_avcencinfo.so) 313 ``` 314 315 The following is the sample code: 316 ```c++ 317 auto buffer = signal_->inBufferQueue_.front(); 318 uint32_t keyIdLen = DRM_KEY_ID_SIZE; 319 uint8_t keyId[] = { 320 0xd4, 0xb2, 0x01, 0xe4, 0x61, 0xc8, 0x98, 0x96, 321 0xcf, 0x05, 0x22, 0x39, 0x8d, 0x09, 0xe6, 0x28}; 322 uint32_t ivLen = DRM_KEY_IV_SIZE; 323 uint8_t iv[] = { 324 0xbf, 0x77, 0xed, 0x51, 0x81, 0xde, 0x36, 0x3e, 325 0x52, 0xf7, 0x20, 0x4f, 0x72, 0x14, 0xa3, 0x95}; 326 uint32_t encryptedBlockCount = 0; 327 uint32_t skippedBlockCount = 0; 328 uint32_t firstEncryptedOffset = 0; 329 uint32_t subsampleCount = 1; 330 DrmSubsample subsamples[1] = { {0x10, 0x16} }; 331 // Create a CencInfo instance. 332 OH_AVCencInfo *cencInfo = OH_AVCencInfo_Create(); 333 if (cencInfo == nullptr) { 334 // Handle exceptions. 335 } 336 // Set the decryption algorithm. 337 OH_AVErrCode errNo = OH_AVCencInfo_SetAlgorithm(cencInfo, DRM_ALG_CENC_AES_CTR); 338 if (errNo != AV_ERR_OK) { 339 // Handle exceptions. 340 } 341 // Set KeyId and Iv. 342 errNo = OH_AVCencInfo_SetKeyIdAndIv(cencInfo, keyId, keyIdLen, iv, ivLen); 343 if (errNo != AV_ERR_OK) { 344 // Handle exceptions. 345 } 346 // Set the sample information. 347 errNo = OH_AVCencInfo_SetSubsampleInfo(cencInfo, encryptedBlockCount, skippedBlockCount, firstEncryptedOffset, 348 subsampleCount, subsamples); 349 if (errNo != AV_ERR_OK) { 350 // Handle exceptions. 351 } 352 // Set the mode. KeyId, Iv, and SubSamples have been set. 353 errNo = OH_AVCencInfo_SetMode(cencInfo, DRM_CENC_INFO_KEY_IV_SUBSAMPLES_SET); 354 if (errNo != AV_ERR_OK) { 355 // Handle exceptions. 356 } 357 // Set CencInfo to the AVBuffer. 358 errNo = OH_AVCencInfo_SetAVBuffer(cencInfo, buffer); 359 if (errNo != AV_ERR_OK) { 360 // Handle exceptions. 361 } 362 // Destroy the CencInfo instance. 363 errNo = OH_AVCencInfo_Destroy(cencInfo); 364 if (errNo != AV_ERR_OK) { 365 // Handle exceptions. 366 } 367 ``` 368 3699. Call **OH_AudioCodec_PushInputBuffer()** to write the data to decode. 370 371 You should fill in complete input data before calling this API. 372 373 To indicate the End of Stream (EOS), pass in the **AVCODEC_BUFFER_FLAGS_EOS** flag. 374 375 ```c++ 376 uint32_t index = signal_->inQueue_.front(); 377 auto buffer = signal_->inBufferQueue_.front(); 378 int64_t size; 379 int64_t pts; 380 // 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. 381 // The values of size and pts are obtained from an audio and video resource file or data stream to decode. 382 // In the case of an audio and video resource file, the values are obtained from the buffer in the decapsulated OH_AVDemuxer_ReadSampleBuffer. 383 // In the case of a data stream, the values are obtained from the data stream provider. 384 // In this example, the values of size and pts are obtained from the test file. 385 inputFile_.read(reinterpret_cast<char *>(&size), sizeof(size)); 386 inputFile_.read(reinterpret_cast<char *>(&pts), sizeof(pts)); 387 inputFile_.read((char *)OH_AVBuffer_GetAddr(buffer), size); 388 OH_AVCodecBufferAttr attr = {0}; 389 if (inputFile_->eof()) { 390 attr.size = 0; 391 attr.flags = AVCODEC_BUFFER_FLAGS_EOS; 392 } else { 393 attr.size = size; 394 attr.flags = AVCODEC_BUFFER_FLAGS_NONE; 395 } 396 attr.pts = pts; 397 OH_AVBuffer_SetBufferAttr(buffer, &attr); 398 int32_t ret = OH_AudioCodec_PushInputBuffer(audioDec_, index); 399 if (ret != AV_ERR_OK) { 400 // Handle exceptions. 401 } 402 ``` 403 40410. Call **OH_AudioCodec_FreeOutputBuffer()** to release the decoded data. 405 406 Once you have retrieved the decoded PCM stream, call **OH_AudioCodec_FreeOutputBuffer()** to free up the data. 407 408 <!--RP3--> 409 ```c++ 410 uint32_t index = signal_->outQueue_.front(); 411 OH_AVBuffer *data = signal_->outBufferQueue_.front(); 412 // Obtain the buffer attributes. 413 OH_AVCodecBufferAttr attr = {0}; 414 ret = OH_AVBuffer_GetBufferAttr(data, &attr); 415 if (ret != AV_ERR_OK) { 416 // Handle exceptions. 417 } 418 // Write the decoded data (specified by data) to the output file. 419 pcmOutputFile_.write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)), attr.size); 420 ret = OH_AudioCodec_FreeOutputBuffer(audioDec_, index); 421 if (ret != AV_ERR_OK) { 422 // Handle exceptions. 423 } 424 if (attr.flags == AVCODEC_BUFFER_FLAGS_EOS) { 425 // End. 426 } 427 ``` 428 <!--RP3End--> 429 43011. (Optional) Call **OH_AudioCodec_Flush()** to refresh the decoder. 431 432 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. To continue decoding, you must call **OH_AudioCodec_Start()** again. 433 434 You need to call **OH_AudioCodec_Start()** in the following cases: 435 436 * The EOS of the file is reached. 437 * An error with **OH_AudioCodec_IsValid** set to **true** (indicating that the execution can continue) occurs. 438 439 ```c++ 440 // Refresh the decoder. 441 ret = OH_AudioCodec_Flush(audioDec_); 442 if (ret != AV_ERR_OK) { 443 // Handle exceptions. 444 } 445 // Start decoding again. 446 ret = OH_AudioCodec_Start(audioDec_); 447 if (ret != AV_ERR_OK) { 448 // Handle exceptions. 449 } 450 ``` 451 45212. (Optional) Call **OH_AudioCodec_Reset()** to reset the decoder. 453 454 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()**. 455 456 ```c++ 457 // Reset the decoder. 458 ret = OH_AudioCodec_Reset(audioDec_); 459 if (ret != AV_ERR_OK) { 460 // Handle exceptions. 461 } 462 // Reconfigure the decoder. 463 ret = OH_AudioCodec_Configure(audioDec_, format); 464 if (ret != AV_ERR_OK) { 465 // Handle exceptions. 466 } 467 ``` 468 46913. Call **OH_AudioCodec_Stop()** to stop the decoder. 470 471 After the codec is stopped, you can call **OH_AudioCodec_Start()** to start it again. If you have passed specific data in the previous **OH_AudioCodec_Start()** for the codec, you must pass it again. 472 473 ```c++ 474 // Stop the decoder. 475 ret = OH_AudioCodec_Stop(audioDec_); 476 if (ret != AV_ERR_OK) { 477 // Handle exceptions. 478 } 479 ``` 480 48114. Call **OH_AudioCodec_Destroy()** to destroy the decoder instance and release resources. 482 483 > **NOTE** 484 > 485 > You only need to call this API once. 486 487 ```c++ 488 // Call OH_AudioCodec_Destroy to destroy the decoder. 489 ret = OH_AudioCodec_Destroy(audioDec_); 490 if (ret != AV_ERR_OK) { 491 // Handle exceptions. 492 } else { 493 audioDec_ = NULL; // The decoder cannot be destroyed repeatedly. 494 } 495 ``` 496 497