1 /*
2 * Copyright (c) 2025-2025 Shenzhen Kaihong Digital Industry Development 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_avcodec_decoder.h"
17 #include "avcodec_codec_name.h"
18 #include "avcodec_errors.h"
19 #include "common/common_macro.h"
20 #include "common/media_log.h"
21 #include "const_def.h"
22
23 namespace OHOS {
24 namespace Sharing {
AudioAvCodecDecoder()25 AudioAvCodecDecoder::AudioAvCodecDecoder()
26 {
27 SHARING_LOGD("tracs");
28 }
29
~AudioAvCodecDecoder()30 AudioAvCodecDecoder::~AudioAvCodecDecoder()
31 {
32 Release();
33 }
34
Init(const AudioTrack & audioTrack)35 int32_t AudioAvCodecDecoder::Init(const AudioTrack &audioTrack)
36 {
37 SHARING_LOGD("trace.");
38 if (!InitDecoder() || !SetAudioCallback() || !SetDecoderFormat(audioTrack)) {
39 return ERROR_DECODER_INIT;
40 }
41 return 0;
42 }
43
InitDecoder()44 bool AudioAvCodecDecoder::InitDecoder()
45 {
46 SHARING_LOGD("trace.");
47 if (audioDecoder_ != nullptr) {
48 SHARING_LOGE("audio decoder already init.");
49 return true;
50 }
51 audioDecoder_ = MediaAVCodec::AudioDecoderFactory::CreateByName(
52 (MediaAVCodec::AVCodecCodecName::AUDIO_DECODER_AAC_NAME).data());
53 if (audioDecoder_ == nullptr) {
54 SHARING_LOGE("create audio decoder failed.");
55 return false;
56 }
57 SHARING_LOGI("init audio decoder success.");
58 return true;
59 }
60
SetAudioCallback()61 bool AudioAvCodecDecoder::SetAudioCallback()
62 {
63 SHARING_LOGD("trace.");
64 RETURN_FALSE_IF_NULL(audioDecoder_);
65 auto ret = audioDecoder_->SetCallback(std::static_pointer_cast<AudioAvCodecDecoder>(shared_from_this()));
66 if (ret != MediaAVCodec::AVCS_ERR_OK) {
67 SHARING_LOGE("set audio decoder callback failed!");
68 return false;
69 }
70 SHARING_LOGD("set audio decoder callback success");
71 return true;
72 }
73
Start()74 bool AudioAvCodecDecoder::Start()
75 {
76 SHARING_LOGD("trace.");
77 if (isRunning_) {
78 SHARING_LOGW(" decoder is running.");
79 return true;
80 }
81
82 auto audioDecoder = GetDecoder();
83 RETURN_FALSE_IF_NULL(audioDecoder);
84 auto ret = audioDecoder->Start();
85 if (ret != MediaAVCodec::AVCS_ERR_OK) {
86 SHARING_LOGE("start decoder failed");
87 return false;
88 }
89 isRunning_ = true;
90 return true;
91 }
92
Stop()93 void AudioAvCodecDecoder::Stop()
94 {
95 SHARING_LOGD("trace.");
96 if (!isRunning_) {
97 SHARING_LOGE("decoder is not running");
98 return;
99 }
100 if (StopDecoder()) {
101 isRunning_ = false;
102 isFirstFrame_ = false;
103 }
104 }
105
Release()106 void AudioAvCodecDecoder::Release()
107 {
108 SHARING_LOGD("trace.");
109 if (audioDecoder_ != nullptr) {
110 audioDecoder_->Release();
111 audioDecoder_->Reset();
112 }
113 }
114
StopDecoder()115 bool AudioAvCodecDecoder::StopDecoder()
116 {
117 SHARING_LOGD("trace.");
118 auto audioDecoder = GetDecoder();
119 RETURN_FALSE_IF_NULL(audioDecoder);
120
121 auto ret = audioDecoder->Flush();
122 if (ret != MediaAVCodec::AVCS_ERR_OK) {
123 SHARING_LOGE("Flush audioDecoder failed");
124 return false;
125 }
126 ret = audioDecoder->Stop();
127 if (ret != MediaAVCodec::AVCS_ERR_OK) {
128 SHARING_LOGE("Stop audioDecoder failed");
129 return false;
130 }
131 ret = audioDecoder->Reset();
132 if (ret != MediaAVCodec::AVCS_ERR_OK) {
133 SHARING_LOGE("Reset audioDecoder failed");
134 return false;
135 }
136 SHARING_LOGD("StopDecoder Success.");
137 return true;
138 }
139
SetDecoderFormat(const AudioTrack & audioTrack)140 bool AudioAvCodecDecoder::SetDecoderFormat(const AudioTrack &audioTrack)
141 {
142 SHARING_LOGI("trace.");
143 auto audioDecoder = GetDecoder();
144 RETURN_FALSE_IF_NULL(audioDecoder);
145
146 int32_t sampleRate =
147 audioTrack.sampleRate == 0 ? AUDIO_DECODE_DEFAULT_SAMPLERRATE : static_cast<int32_t>(audioTrack.sampleRate);
148 int32_t channelCount =
149 audioTrack.channels == 0 ? AUDIO_DECODE_DEFAULT_CHANNEL_COUNT : static_cast<int32_t>(audioTrack.channels);
150
151 MediaAVCodec::Format format;
152 format.PutIntValue("sample_rate", sampleRate);
153 format.PutIntValue("channel_count", channelCount);
154 format.PutIntValue("audio_sample_format", static_cast<int32_t>(MediaAVCodec::AudioSampleFormat::SAMPLE_S16LE));
155 int32_t ret = audioDecoder->Configure(format);
156 if (ret != MediaAVCodec::AVCS_ERR_OK) {
157 SHARING_LOGE("Configure decoder format failed, Error code %{public}d.", ret);
158 return false;
159 }
160 ret = audioDecoder->Prepare();
161 if (ret != MediaAVCodec::AVCS_ERR_OK) {
162 SHARING_LOGE("Configure decoder prepare failed, Error code %{public}d.", ret);
163 return false;
164 }
165 return true;
166 }
167
OnFrame(const Frame::Ptr & frame)168 void AudioAvCodecDecoder::OnFrame(const Frame::Ptr &frame)
169 {
170 SHARING_LOGD("trace.");
171 auto audioDecoder = GetDecoder();
172 RETURN_IF_NULL(audioDecoder);
173 int32_t bufferIndex = 0;
174 std::shared_ptr<MediaAVCodec::AVSharedMemory> inputBuffer;
175 {
176 std::unique_lock<std::mutex> lock(inputBufferMutex_);
177 if (inBufferQueue_.empty()) {
178 inCond_.wait_for(lock, std::chrono::milliseconds(AUDIO_DECODE_WAIT_MILLISECONDS),
179 [this]() { return (!inBufferQueue_.empty()); });
180 }
181 if (inBufferQueue_.empty()) {
182 SHARING_LOGW("Index queue is empty.");
183 return;
184 }
185 auto pair_data = inBufferQueue_.front();
186 bufferIndex = pair_data.first;
187 inputBuffer = pair_data.second;
188 inBufferQueue_.pop();
189 }
190
191 if ((inputBuffer == nullptr) || frame == nullptr || (frame->Data() == nullptr)) {
192 SHARING_LOGW("GetInputBuffer or GetFrameBuffer failed.");
193 return;
194 }
195 if (memcpy_s(inputBuffer->GetBase(), inputBuffer->GetSize(), frame->Data(), frame->Size()) != EOK) {
196 SHARING_LOGW("Copy data failed.");
197 return;
198 }
199 MediaAVCodec::AVCodecBufferInfo bufferInfo = {
200 .presentationTimeUs = frame->Pts(),
201 .size = static_cast<int32_t>(frame->Size()),
202 .offset = 0,
203 };
204 auto bufferFlag = MediaAVCodec::AVCODEC_BUFFER_FLAG_CODEC_DATA;
205 if (isFirstFrame_) {
206 bufferFlag = MediaAVCodec::AVCODEC_BUFFER_FLAG_CODEC_DATA;
207 isFirstFrame_ = false;
208 } else {
209 bufferFlag = MediaAVCodec::AVCODEC_BUFFER_FLAG_CODEC_DATA;
210 }
211 int32_t ret = audioDecoder->QueueInputBuffer(bufferIndex, bufferInfo, bufferFlag);
212 if (ret != MediaAVCodec::AVCS_ERR_OK) {
213 SHARING_LOGE("Queue input buffer fail. Error code %{public}d.", ret);
214 }
215 }
216
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)217 void AudioAvCodecDecoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
218 {
219 SHARING_LOGE("onError, errorCode = %{public}d", errorCode);
220 }
221
OnInputBufferAvailable(uint32_t index,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)222 void AudioAvCodecDecoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
223 {
224 SHARING_LOGD("trace.");
225 {
226 std::lock_guard<std::mutex> lock(inputBufferMutex_);
227 inBufferQueue_.push({index, buffer});
228 }
229 inCond_.notify_all();
230 }
231
OnOutputBufferAvailable(uint32_t index,MediaAVCodec::AVCodecBufferInfo info,MediaAVCodec::AVCodecBufferFlag flag,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)232 void AudioAvCodecDecoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info,
233 MediaAVCodec::AVCodecBufferFlag flag,
234 std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
235 {
236 SHARING_LOGD("trace.");
237 auto audioDecoder = GetDecoder();
238 RETURN_IF_NULL(audioDecoder);
239 if (flag & MediaAVCodec::AVCODEC_BUFFER_FLAG_EOS) {
240 SHARING_LOGE("flag is eos.");
241 return;
242 }
243 if (!buffer) {
244 SHARING_LOGE("buffer is null");
245 return;
246 }
247 if (info.size <= 0 || info.size > buffer->GetSize()) {
248 SHARING_LOGE("Codec output info error, AVCodec info: size %{public}d, memory size %{public}d.", info.size,
249 buffer->GetSize());
250 return;
251 }
252 auto frameBuffer = FrameImpl::Create();
253 frameBuffer->SetSize(static_cast<uint32_t>(info.size));
254 frameBuffer->codecId_ = CODEC_AAC;
255 frameBuffer->pts_ = static_cast<uint32_t>(info.presentationTimeUs);
256 frameBuffer->Assign((char *)buffer->GetBase(), info.size);
257 DeliverFrame(frameBuffer);
258 int32_t ret = audioDecoder->ReleaseOutputBuffer(index);
259 if (ret != MediaAVCodec::AVCS_ERR_OK) {
260 SHARING_LOGE("ReleaseOutputBuffer fail. Error code %{public}d.", ret);
261 }
262 }
263
OnOutputFormatChanged(const MediaAVCodec::Format & format)264 void AudioAvCodecDecoder::OnOutputFormatChanged(const MediaAVCodec::Format &format)
265 {
266 SHARING_LOGD("trace.");
267 }
268
GetDecoder()269 std::shared_ptr<MediaAVCodec::AVCodecAudioDecoder> AudioAvCodecDecoder::GetDecoder()
270 {
271 std::lock_guard<std::mutex> lock(decoderMutex_);
272 return audioDecoder_;
273 }
274 } // namespace Sharing
275 } // namespace OHOS