• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License"){}
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "audio_decoder.h"
17 
18 #include "audio_info.h"
19 #include "avsharedmemory.h"
20 #include "media_errors.h"
21 #include "securec.h"
22 
23 #include "audio_decoder_callback.h"
24 #include "daudio_errorcode.h"
25 #include "daudio_log.h"
26 #include "daudio_util.h"
27 
28 #undef DH_LOG_TAG
29 #define DH_LOG_TAG "AudioDecoder"
30 
31 namespace OHOS {
32 namespace DistributedHardware {
33 const std::string AudioDecoder::DECODE_MIME_AAC = "audio/mp4a-latm";
34 
~AudioDecoder()35 AudioDecoder::~AudioDecoder()
36 {
37     if (audioDecoder_ != nullptr) {
38         DHLOGI("Release audio codec.");
39         StopAudioCodec();
40         ReleaseAudioCodec();
41     }
42 }
43 
ConfigureAudioCodec(const AudioCommonParam & codecParam,const std::shared_ptr<IAudioCodecCallback> & codecCallback)44 int32_t AudioDecoder::ConfigureAudioCodec(const AudioCommonParam &codecParam,
45     const std::shared_ptr<IAudioCodecCallback> &codecCallback)
46 {
47     DHLOGI("Configure audio codec.");
48     if (!IsInDecodeRange(codecParam) || codecCallback == nullptr) {
49         DHLOGE("Codec param error or callback is null.");
50         return ERR_DH_AUDIO_BAD_VALUE;
51     }
52     codecParam_ = codecParam;
53     codecCallback_ = codecCallback;
54 
55     int32_t ret = InitAudioDecoder(codecParam);
56     if (ret != DH_SUCCESS) {
57         DHLOGE("Init audio decoder fail. Error code %d.", ret);
58         return ret;
59     }
60 
61     ret = SetDecoderFormat(codecParam);
62     if (ret != DH_SUCCESS) {
63         DHLOGE("Set decoder format fail. Error code %d.", ret);
64         return ret;
65     }
66     return DH_SUCCESS;
67 }
68 
IsInDecodeRange(const AudioCommonParam & codecParam)69 bool AudioDecoder::IsInDecodeRange(const AudioCommonParam &codecParam)
70 {
71     if (codecParam.channelMask >= CHANNEL_MASK_MIN && codecParam.channelMask <= CHANNEL_MASK_MAX &&
72         codecParam.sampleRate >= SAMPLE_RATE_MIN && codecParam.sampleRate <= SAMPLE_RATE_MAX &&
73         codecParam.bitFormat == SAMPLE_S16LE && codecParam.codecType == AUDIO_CODEC_AAC) {
74         return true;
75     }
76 
77     DHLOGE("Param error, codec type %d, channel count %d, sample rate %d, sample format %d.",
78         codecParam.codecType, codecParam.channelMask, codecParam.sampleRate, codecParam.bitFormat);
79     return false;
80 }
81 
InitAudioDecoder(const AudioCommonParam & codecParam)82 int32_t AudioDecoder::InitAudioDecoder(const AudioCommonParam &codecParam)
83 {
84     DHLOGI("Init audio decoder.");
85     audioDecoder_ = Media::AudioDecoderFactory::CreateByMime(DECODE_MIME_AAC);
86     if (audioDecoder_ == nullptr) {
87         DHLOGE("Create audio decoder fail.");
88         return ERR_DH_AUDIO_CODEC_CONFIG;
89     }
90 
91     decoderCallback_ = std::make_shared<AudioDecoderCallback>(shared_from_this());
92     int32_t ret = audioDecoder_->SetCallback(decoderCallback_);
93     if (ret != Media::MediaServiceErrCode::MSERR_OK) {
94         DHLOGE("Set decoder callback fail. Error code %d.", ret);
95         decoderCallback_ = nullptr;
96         return ERR_DH_AUDIO_CODEC_CONFIG;
97     }
98 
99     return DH_SUCCESS;
100 }
101 
SetDecoderFormat(const AudioCommonParam & codecParam)102 int32_t AudioDecoder::SetDecoderFormat(const AudioCommonParam &codecParam)
103 {
104     if (audioDecoder_ == nullptr) {
105         DHLOGE("Decoder is null.");
106         return ERR_DH_AUDIO_BAD_VALUE;
107     }
108 
109     DHLOGI("Set encoder format, codec type %d, channel count %d, sample rate %d, sample format %d.",
110         codecParam.codecType, codecParam.channelMask, codecParam.sampleRate, codecParam.bitFormat);
111     cfgFormat_.PutIntValue("channel_count", codecParam.channelMask);
112     cfgFormat_.PutIntValue("sample_rate", codecParam.sampleRate);
113     cfgFormat_.PutIntValue("audio_sample_format",
114         static_cast<AudioStandard::AudioSampleFormat>(codecParam.bitFormat));
115 
116     int32_t ret = audioDecoder_->Configure(cfgFormat_);
117     if (ret != Media::MSERR_OK) {
118         DHLOGE("Configure decoder format fail. Error code %d.", ret);
119         return ERR_DH_AUDIO_CODEC_CONFIG;
120     }
121 
122     ret = audioDecoder_->Prepare();
123     if (ret != Media::MediaServiceErrCode::MSERR_OK) {
124         DHLOGE("Decoder prepare fail. Error code %d.", ret);
125         return ERR_DH_AUDIO_CODEC_CONFIG;
126     }
127     return DH_SUCCESS;
128 }
129 
ReleaseAudioCodec()130 int32_t AudioDecoder::ReleaseAudioCodec()
131 {
132     DHLOGI("Release audio codec.");
133     if (audioDecoder_ == nullptr) {
134         DHLOGE("Decoder is null.");
135         return DH_SUCCESS;
136     }
137 
138     int32_t ret = audioDecoder_->Release();
139     if (ret != Media::MediaServiceErrCode::MSERR_OK) {
140         DHLOGE("Decoder release fail. Error code %d.", ret);
141         return ERR_DH_AUDIO_BAD_OPERATE;
142     }
143     decoderCallback_ = nullptr;
144     audioDecoder_ = nullptr;
145 
146     DHLOGI("Release audio codec end.");
147     return DH_SUCCESS;
148 }
149 
StartAudioCodec()150 int32_t AudioDecoder::StartAudioCodec()
151 {
152     DHLOGI("Start audio codec.");
153     if (audioDecoder_ == nullptr) {
154         DHLOGE("Decoder is null.");
155         return ERR_DH_AUDIO_BAD_VALUE;
156     }
157 
158     int32_t ret = audioDecoder_->Start();
159     if (ret != Media::MediaServiceErrCode::MSERR_OK) {
160         DHLOGE("Decoder start fail. Error code %d.", ret);
161         return ERR_DH_AUDIO_CODEC_START;
162     }
163     StartInputThread();
164     return DH_SUCCESS;
165 }
166 
StartInputThread()167 void AudioDecoder::StartInputThread()
168 {
169     DHLOGI("Start input thread.");
170     isDecoderRunning_.store(true);
171     decodeThread_ = std::thread(&AudioDecoder::InputDecodeAudioData, this);
172     if (pthread_setname_np(decodeThread_.native_handle(), DECODE_THREAD) != DH_SUCCESS) {
173         DHLOGE("Decode thread setname failed.");
174     }
175 }
176 
StopAudioCodec()177 int32_t AudioDecoder::StopAudioCodec()
178 {
179     DHLOGI("Stop audio codec.");
180     StopInputThread();
181     if (audioDecoder_ == nullptr) {
182         DHLOGE("Decoder is null.");
183         return DH_SUCCESS;
184     }
185 
186     bool isSuccess = true;
187     int32_t ret = audioDecoder_->Flush();
188     if (ret != Media::MediaServiceErrCode::MSERR_OK) {
189         DHLOGE("Decoder flush fail. Error type: %d.", ret);
190         isSuccess = false;
191     }
192     ret = audioDecoder_->Stop();
193     if (ret != Media::MediaServiceErrCode::MSERR_OK) {
194         DHLOGE("Decoder stop fail. Error type: %d.", ret);
195         isSuccess = false;
196     }
197     if (!isSuccess) {
198         return ERR_DH_AUDIO_CODEC_STOP;
199     }
200 
201     firstInputTimeUs_ = 0;
202     inputTimeStampUs_ = 0;
203     outputTimeStampUs_ = 0;
204     waitOutputCount_ = 0;
205     DHLOGI("Stop audio codec end.");
206     return DH_SUCCESS;
207 }
208 
StopInputThread()209 void AudioDecoder::StopInputThread()
210 {
211     isDecoderRunning_.store(false);
212     decodeCond_.notify_all();
213     if (decodeThread_.joinable()) {
214         decodeThread_.join();
215     }
216 
217     std::lock_guard<std::mutex> dataLock(mtxData_);
218     std::queue<uint32_t>().swap(bufIndexQueue_);
219     std::queue<std::shared_ptr<AudioData>>().swap(inputBufQueue_);
220     DHLOGI("Stop input thread success.");
221 }
222 
FeedAudioData(const std::shared_ptr<AudioData> & inputData)223 int32_t AudioDecoder::FeedAudioData(const std::shared_ptr<AudioData> &inputData)
224 {
225     DHLOGD("Feed audio data.");
226     if (!isDecoderRunning_.load()) {
227         DHLOGE("Decoder is stopped.");
228         return ERR_DH_AUDIO_CODEC_INPUT;
229     }
230     if (inputData == nullptr) {
231         DHLOGE("Input data is nullptr.");
232         return ERR_DH_AUDIO_BAD_VALUE;
233     }
234 
235     std::lock_guard<std::mutex> dataLock(mtxData_);
236     while (inputBufQueue_.size() > AUDIO_DECODER_QUEUE_MAX) {
237         DHLOGE("Input data queue overflow.");
238         inputBufQueue_.pop();
239     }
240     inputBufQueue_.push(inputData);
241     decodeCond_.notify_all();
242 
243     return DH_SUCCESS;
244 }
245 
InputDecodeAudioData()246 void AudioDecoder::InputDecodeAudioData()
247 {
248     DHLOGI("Input decode audio data thread start.");
249     while (isDecoderRunning_.load()) {
250         std::shared_ptr<AudioData> audioData;
251         int32_t bufferIndex = 0;
252         {
253             std::unique_lock<std::mutex> lock(mtxData_);
254             decodeCond_.wait_for(lock, std::chrono::milliseconds(DECODE_WAIT_MILLISECONDS),
255                 [this]() {
256                     return (!inputBufQueue_.empty() && !bufIndexQueue_.empty()) || !isDecoderRunning_.load();
257                 });
258 
259             if (inputBufQueue_.empty() || bufIndexQueue_.empty()) {
260                 continue;
261             }
262             bufferIndex = (int32_t)bufIndexQueue_.front();
263             bufIndexQueue_.pop();
264             audioData = inputBufQueue_.front();
265             inputBufQueue_.pop();
266         }
267 
268         int32_t ret = ProcessData(audioData, bufferIndex);
269         if (ret == ERR_DH_AUDIO_BAD_VALUE) {
270             DHLOGE("Decoder is stopped or null.");
271             return;
272         } else if (ret != DH_SUCCESS) {
273             DHLOGE("Process data fail. Error type: %d.", ret);
274             continue;
275         }
276     }
277 }
278 
ProcessData(const std::shared_ptr<AudioData> & audioData,const int32_t bufferIndex)279 int32_t AudioDecoder::ProcessData(const std::shared_ptr<AudioData> &audioData, const int32_t bufferIndex)
280 {
281     if (!isDecoderRunning_.load() || audioDecoder_ == nullptr) {
282         DHLOGE("Decoder is stopped or null, isRunning %d.", isDecoderRunning_.load());
283         return ERR_DH_AUDIO_BAD_VALUE;
284     }
285 
286     auto inMem = audioDecoder_->GetInputBuffer(bufferIndex);
287     if (inMem == nullptr) {
288         DHLOGE("Get input buffer fail.");
289         return ERR_DH_AUDIO_CODEC_INPUT;
290     }
291     if (inMem->GetSize() == INVALID_MEMORY_SIZE || static_cast<size_t>(inMem->GetSize()) < audioData->Size()) {
292         DHLOGE("Input buffer size error. Memory size %d, data size %zu.",
293             inMem->GetSize(), audioData->Size());
294         return ERR_DH_AUDIO_CODEC_INPUT;
295     }
296 
297     errno_t err = memcpy_s(inMem->GetBase(), inMem->GetSize(), audioData->Data(), audioData->Size());
298     if (err != EOK) {
299         DHLOGE("Copy input data fail. Error code %d. Memory size %d, data size %zu.",
300             err, inMem->GetSize(), audioData->Size());
301         return ERR_DH_AUDIO_BAD_OPERATE;
302     }
303 
304     inputTimeStampUs_ = GetDecoderTimeStamp();
305     Media::AVCodecBufferInfo bufferInfo = {inputTimeStampUs_, static_cast<int32_t>(audioData->Size()), 0};
306     auto bufferFlag =
307         bufferInfo.presentationTimeUs == 0 ? Media::AVCODEC_BUFFER_FLAG_CODEC_DATA : Media::AVCODEC_BUFFER_FLAG_NONE;
308     DHLOGD("Queue input buffer. AVCodec Info: input time stamp %lld, data size %zu.",
309         (long long)bufferInfo.presentationTimeUs, audioData->Size());
310     int32_t ret = audioDecoder_->QueueInputBuffer(bufferIndex, bufferInfo, bufferFlag);
311     if (ret != Media::MSERR_OK) {
312         DHLOGE("Queue input buffer fail. Error code %d", ret);
313         return ERR_DH_AUDIO_CODEC_INPUT;
314     }
315 
316     IncreaseWaitDecodeCnt();
317     return DH_SUCCESS;
318 }
319 
GetDecoderTimeStamp()320 int64_t AudioDecoder::GetDecoderTimeStamp()
321 {
322     int64_t TimeIntervalStampUs = 0;
323     int64_t nowTimeUs = GetNowTimeUs();
324     if (firstInputTimeUs_ == 0) {
325         firstInputTimeUs_ = nowTimeUs;
326         return TimeIntervalStampUs;
327     }
328 
329     TimeIntervalStampUs = nowTimeUs - firstInputTimeUs_;
330     return TimeIntervalStampUs;
331 }
332 
IncreaseWaitDecodeCnt()333 void AudioDecoder::IncreaseWaitDecodeCnt()
334 {
335     std::lock_guard<std::mutex> countLock(mtxCnt_);
336     waitOutputCount_++;
337     DHLOGD("Wait decoder output frames number is %d.", waitOutputCount_);
338 }
339 
ReduceWaitDecodeCnt()340 void AudioDecoder::ReduceWaitDecodeCnt()
341 {
342     std::lock_guard<std::mutex> countLock(mtxCnt_);
343     if (waitOutputCount_ <= 0) {
344         DHLOGE("Wait decoder output count %d.", waitOutputCount_);
345     }
346     waitOutputCount_--;
347     DHLOGD("Wait decoder output frames number is %d.", waitOutputCount_);
348 }
349 
OnInputBufferAvailable(uint32_t index)350 void AudioDecoder::OnInputBufferAvailable(uint32_t index)
351 {
352     std::lock_guard<std::mutex> countLock(mtxData_);
353     while (bufIndexQueue_.size() > AUDIO_DECODER_QUEUE_MAX) {
354         DHLOGE("Index queue overflow.");
355         bufIndexQueue_.pop();
356     }
357 
358     bufIndexQueue_.push(index);
359     decodeCond_.notify_all();
360 }
361 
OnOutputBufferAvailable(uint32_t index,Media::AVCodecBufferInfo info,Media::AVCodecBufferFlag flag)362 void AudioDecoder::OnOutputBufferAvailable(uint32_t index, Media::AVCodecBufferInfo info,
363     Media::AVCodecBufferFlag flag)
364 {
365     if (!isDecoderRunning_.load() || audioDecoder_ == nullptr) {
366         DHLOGE("Decoder is stopped or null, isRunning %d.", isDecoderRunning_.load());
367         return;
368     }
369 
370     auto outMem = audioDecoder_->GetOutputBuffer(index);
371     if (outMem == nullptr) {
372         DHLOGE("Get output buffer fail. index %u.", index);
373         return;
374     }
375     if (info.size <= 0 || info.size > outMem->GetSize()) {
376         DHLOGE("Codec output info error. AVCodec info: size %d, memory size %d.",
377             info.size, outMem->GetSize());
378         return;
379     }
380 
381     auto outBuf = std::make_shared<AudioData>(static_cast<size_t>(info.size));
382     errno_t err = memcpy_s(outBuf->Data(), outBuf->Size(), outMem->GetBase(), static_cast<size_t>(info.size));
383     if (err != EOK) {
384         DHLOGE("Copy output data fail. Error code %d. Buffer Size %zu, AVCodec info: size %d.",
385             err, outBuf->Size(), info.size);
386         return;
387     }
388     outBuf->SetInt64("timeUs", info.presentationTimeUs);
389     outputTimeStampUs_ = info.presentationTimeUs;
390     DHLOGD("Get output buffer. AVCodec info: output time stamp %lld, data size %zu.",
391         (long long)info.presentationTimeUs, outBuf->Size());
392 
393     ReduceWaitDecodeCnt();
394     err = DecodeDone(outBuf);
395     if (err != DH_SUCCESS) {
396         DHLOGE("Decode done fail. Error code: %d.", err);
397         return;
398     }
399 
400     err = audioDecoder_->ReleaseOutputBuffer(index);
401     if (err != Media::MediaServiceErrCode::MSERR_OK) {
402         DHLOGE("Release output buffer fail. Error code: %d, index %u.", err, index);
403     }
404 }
405 
OnOutputFormatChanged(const Media::Format & format)406 void AudioDecoder::OnOutputFormatChanged(const Media::Format &format)
407 {
408     if (format.GetFormatMap().empty()) {
409         DHLOGE("The first changed output frame format is null.");
410         return;
411     }
412     outputFormat_ = format;
413 }
414 
OnError(const AudioEvent & event)415 void AudioDecoder::OnError(const AudioEvent &event)
416 {
417     DHLOGE("Decoder error.");
418     std::shared_ptr<IAudioCodecCallback> cbObj = codecCallback_.lock();
419     if (cbObj == nullptr) {
420         DHLOGE("Codec callback is null.");
421         return;
422     }
423     cbObj->OnCodecStateNotify(event);
424 }
425 
DecodeDone(const std::shared_ptr<AudioData> & outputData)426 int32_t AudioDecoder::DecodeDone(const std::shared_ptr<AudioData> &outputData)
427 {
428     DHLOGD("Decode done.");
429     std::shared_ptr<IAudioCodecCallback> cbObj = codecCallback_.lock();
430     if (cbObj == nullptr) {
431         DHLOGE("Codec callback is null.");
432         return ERR_DH_AUDIO_BAD_VALUE;
433     }
434     cbObj->OnCodecDataDone(outputData);
435     return DH_SUCCESS;
436 }
437 } // namespace DistributedHardware
438 } // namespace OHOS