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