/* * Copyright (c) 2025-2025 Shenzhen Kaihong Digital Industry Development Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "audio_avcodec_decoder.h" #include "avcodec_codec_name.h" #include "avcodec_errors.h" #include "common/common_macro.h" #include "common/media_log.h" #include "const_def.h" #include "sharing_sink_hisysevent.h" namespace OHOS { namespace Sharing { AudioAvCodecDecoder::AudioAvCodecDecoder() { SHARING_LOGD("trace"); } AudioAvCodecDecoder::~AudioAvCodecDecoder() { Release(); } int32_t AudioAvCodecDecoder::Init(const AudioTrack &audioTrack) { SHARING_LOGD("trace."); if (!InitDecoder() || !SetAudioCallback() || !SetDecoderFormat(audioTrack)) { return ERROR_DECODER_INIT; } return 0; } bool AudioAvCodecDecoder::InitDecoder() { SHARING_LOGD("trace."); if (audioDecoder_ != nullptr) { SHARING_LOGE("audio decoder already init."); return true; } audioDecoder_ = MediaAVCodec::AudioDecoderFactory::CreateByName( (MediaAVCodec::AVCodecCodecName::AUDIO_DECODER_AAC_NAME).data()); if (audioDecoder_ == nullptr) { SHARING_LOGE("create audio decoder failed."); WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::AUDIO_DECODE, SinkErrorCode::WIFI_DISPLAY_AUDIO_DECODE_FAILED); return false; } SHARING_LOGI("init audio decoder success."); return true; } bool AudioAvCodecDecoder::SetAudioCallback() { SHARING_LOGD("trace."); RETURN_FALSE_IF_NULL(audioDecoder_); auto ret = audioDecoder_->SetCallback(std::static_pointer_cast(shared_from_this())); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("set audio decoder callback failed!"); return false; } SHARING_LOGD("set audio decoder callback success"); return true; } bool AudioAvCodecDecoder::Start() { SHARING_LOGD("trace."); if (isRunning_) { SHARING_LOGW(" decoder is running."); return true; } auto audioDecoder = GetDecoder(); RETURN_FALSE_IF_NULL(audioDecoder); auto ret = audioDecoder->Start(); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("start decoder failed"); WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::AUDIO_DECODE, SinkErrorCode::WIFI_DISPLAY_AUDIO_DECODE_FAILED); return false; } isRunning_ = true; StartRender(); return true; } void AudioAvCodecDecoder::Stop() { SHARING_LOGD("trace."); if (!isRunning_) { SHARING_LOGE("decoder is not running"); return; } if (StopDecoder()) { isRunning_ = false; } } void AudioAvCodecDecoder::Release() { SHARING_LOGD("trace."); if (audioDecoder_ != nullptr) { audioDecoder_->Release(); audioDecoder_->Reset(); } } bool AudioAvCodecDecoder::StopDecoder() { SHARING_LOGD("trace."); auto audioDecoder = GetDecoder(); RETURN_FALSE_IF_NULL(audioDecoder); StopRender(); auto ret = audioDecoder->Flush(); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("Flush audioDecoder failed"); return false; } ret = audioDecoder->Stop(); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("Stop audioDecoder failed"); return false; } ret = audioDecoder->Reset(); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("Reset audioDecoder failed"); return false; } SHARING_LOGD("StopDecoder Success."); return true; } bool AudioAvCodecDecoder::SetDecoderFormat(const AudioTrack &audioTrack) { SHARING_LOGI("trace."); auto audioDecoder = GetDecoder(); RETURN_FALSE_IF_NULL(audioDecoder); int32_t sampleRate = audioTrack.sampleRate == 0 ? AUDIO_DECODE_DEFAULT_SAMPLERATE : static_cast(audioTrack.sampleRate); int32_t channelCount = audioTrack.channels == 0 ? AUDIO_DECODE_DEFAULT_CHANNEL_COUNT : static_cast(audioTrack.channels); MediaAVCodec::Format format; format.PutIntValue("sample_rate", sampleRate); format.PutIntValue("channel_count", channelCount); format.PutIntValue("audio_sample_format", static_cast(MediaAVCodec::AudioSampleFormat::SAMPLE_S16LE)); int32_t ret = audioDecoder->Configure(format); if (ret != MediaAVCodec::AVCS_ERR_OK) { WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::AUDIO_DECODE, SinkErrorCode::WIFI_DISPLAY_AUDIO_DECODE_FAILED); SHARING_LOGE("Configure decoder format failed, Error code %{public}d.", ret); return false; } ret = audioDecoder->Prepare(); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("Configure decoder prepare failed, Error code %{public}d.", ret); return false; } return true; } void AudioAvCodecDecoder::OnFrame(const Frame::Ptr &frame) { SHARING_LOGD("trace."); auto audioDecoder = GetDecoder(); RETURN_IF_NULL(audioDecoder); int32_t bufferIndex = 0; std::shared_ptr inputBuffer; { std::unique_lock lock(inputBufferMutex_); if (inBufferQueue_.empty()) { inCond_.wait_for(lock, std::chrono::milliseconds(AUDIO_DECODE_WAIT_MILLISECONDS), [this]() { return (!inBufferQueue_.empty()); }); } if (inBufferQueue_.empty()) { SHARING_LOGW("Index queue is empty."); WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::AUDIO_DECODE, SinkErrorCode::WIFI_DISPLAY_AUDIO_DECODE_TIMEOUT); return; } auto pair_data = inBufferQueue_.front(); bufferIndex = pair_data.first; inputBuffer = pair_data.second; inBufferQueue_.pop(); } if ((inputBuffer == nullptr) || frame == nullptr || (frame->Data() == nullptr)) { SHARING_LOGW("GetInputBuffer or GetFrameBuffer failed."); return; } if (inputBuffer->GetSize() < frame->Size()) { SHARING_LOGW("GetInputBuffer size invalid."); return; } if (memcpy_s(inputBuffer->GetBase(), inputBuffer->GetSize(), frame->Data(), frame->Size()) != EOK) { SHARING_LOGW("Copy data failed."); return; } MediaAVCodec::AVCodecBufferInfo bufferInfo = { .presentationTimeUs = frame->Pts(), .size = static_cast(frame->Size()), .offset = 0, }; auto bufferFlag = MediaAVCodec::AVCODEC_BUFFER_FLAG_CODEC_DATA; WfdSinkHiSysEvent::GetInstance().RecordMediaDecodeStartTime(MediaReportType::AUDIO, bufferInfo.presentationTimeUs); int32_t ret = audioDecoder->QueueInputBuffer(bufferIndex, bufferInfo, bufferFlag); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("Queue input buffer fail. Error code %{public}d.", ret); } } void AudioAvCodecDecoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode) { SHARING_LOGE("onError, errorCode = %{public}d", errorCode); WfdSinkHiSysEvent::GetInstance().ReportError(__func__, "", SinkStage::AUDIO_DECODE, SinkErrorCode::WIFI_DISPLAY_AUDIO_DECODE_FAILED); } void AudioAvCodecDecoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr buffer) { SHARING_LOGD("trace."); { std::lock_guard lock(inputBufferMutex_); if (buffer == nullptr) { return; } inBufferQueue_.push({index, buffer}); } inCond_.notify_all(); } void AudioAvCodecDecoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info, MediaAVCodec::AVCodecBufferFlag flag, std::shared_ptr buffer) { SHARING_LOGD("trace."); auto audioDecoder = GetDecoder(); RETURN_IF_NULL(audioDecoder); if (flag & MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS) { SHARING_LOGE("flag is eos."); return; } if (!buffer) { SHARING_LOGE("buffer is null"); return; } if (info.size <= 0 || info.size > buffer->GetSize()) { SHARING_LOGE("Codec output info error, AVCodec info: size %{public}d, memory size %{public}d.", info.size, buffer->GetSize()); return; } WfdSinkHiSysEvent::GetInstance().MediaDecodeTimProc(MediaReportType::AUDIO, info.presentationTimeUs); std::chrono::microseconds nowUs = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); int64_t nowTimeUs = nowUs.count(); if (firstTimestampUs_ == 0) { firstTimestampUs_ = info.presentationTimeUs; } auto frameBuffer = FrameImpl::Create(); frameBuffer->SetSize(static_cast(info.size)); frameBuffer->codecId_ = CODEC_AAC; frameBuffer->pts_ = static_cast(info.presentationTimeUs); frameBuffer->Assign((char *)buffer->GetBase(), info.size); frameBuffer->index = index; frameBuffer->isNeedDrop = IsNeedDropFrame(nowTimeUs); Render(frameBuffer); } bool AudioAvCodecDecoder::ReleaseOutputBuffer(uint32_t index) { std::lock_guard lock(decoderMutex_); if (audioDecoder_ == nullptr) { return false; } int32_t ret = audioDecoder_->ReleaseOutputBuffer(index); if (ret != MediaAVCodec::AVCS_ERR_OK) { SHARING_LOGE("ReleaseOutputBuffer fail. Error code %{public}d.", ret); } return ret == MediaAVCodec::AVCS_ERR_OK; } void AudioAvCodecDecoder::RenderOutBuffer() { while (isRenderReady_.load()) { std::shared_ptr frameBuffer; { std::unique_lock lock(renderBufferMutex_); if (renderBuffer_.empty()) { renderCond_.wait_for(lock, std::chrono::milliseconds(NEXT_FRAME_WAIT_TIME)); continue; } frameBuffer = renderBuffer_.front(); renderBuffer_.pop(); } if (frameBuffer->isNeedDrop) { SHARING_LOGE("Audio RenderBuffer is droped."); ReleaseOutputBuffer(frameBuffer->index); lastPlayPts_ = static_cast(frameBuffer->pts_); continue; } DeliverFrame(frameBuffer); ReleaseOutputBuffer(frameBuffer->index); lastPlayPts_ = static_cast(frameBuffer->pts_); } } void AudioAvCodecDecoder::Render(std::shared_ptr frameBuffer) { std::lock_guard lock(renderBufferMutex_); if (!frameBuffer) { SHARING_LOGE("frameBuffer is null"); return; } if (!isRenderReady_.load()) { SHARING_LOGE("Failed to send data."); ReleaseOutputBuffer(frameBuffer->index); return; } if (renderBuffer_.size() > MAX_BUFFER_SIZE) { ClearRenderBufferQueue(); } renderBuffer_.push(frameBuffer); renderCond_.notify_all(); } bool AudioAvCodecDecoder::StopRender() { SHARING_LOGD("Stop Render"); isRenderReady_ = false; renderCond_.notify_all(); if (renderThread_.joinable()) { renderThread_.join(); } std::lock_guard lock(renderBufferMutex_); ClearRenderBufferQueue(); return true; } void AudioAvCodecDecoder::ClearRenderBufferQueue() { while (!renderBuffer_.empty()) { auto frameBuffer = renderBuffer_.front(); ReleaseOutputBuffer(frameBuffer->index); renderBuffer_.pop(); } } bool AudioAvCodecDecoder::StartRender() { isRenderReady_ = true; renderThread_ = std::thread([this] { this->RenderOutBuffer(); }); std::string name = "AudioSpeakerRun"; pthread_setname_np(renderThread_.native_handle(), name.c_str()); return true; } int64_t AudioAvCodecDecoder::GetDecoderTimestamp() { int64_t timestamp = 0; if (firstTimestampUs_ == 0) { return timestamp; } timestamp = lastPlayPts_ - audioLatency_.load(); return timestamp; } bool AudioAvCodecDecoder::IsNeedDropFrame(int64_t nowTimeUs) { std::lock_guard lock(decoderMutex_); if (isForceDrop_.load() && (nowTimeUs - lastDropTimeUs_ > AUDIO_DECODE_DROP_INTERVAL)) { isForceDrop_ = false; lastDropTimeUs_ = nowTimeUs; return true; } return false; } void AudioAvCodecDecoder::DropOneFrame() { std::lock_guard lock(decoderMutex_); isForceDrop_ = true; } void AudioAvCodecDecoder::OnOutputFormatChanged(const MediaAVCodec::Format &format) { SHARING_LOGD("trace."); } std::shared_ptr AudioAvCodecDecoder::GetDecoder() { std::lock_guard lock(decoderMutex_); return audioDecoder_; } } // namespace Sharing } // namespace OHOS