1 /*
2 * Copyright (C) 2024 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 <native_avcodec_audiodecoder.h>
17 #include "audio_decoder.h"
18 #include "media_log.h"
19 #include "codec/util/codec_util.h"
20 #include <string>
21 #include "securec.h"
22
23 namespace OHOS {
24 namespace Media {
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_VIDEOEDITOR, "ADec"};
27 }
28
AudioDecoder(uint64_t id,const CodecOnInData & packetReadFunc,const CodecOnDecodeFrame & onDecodeFrameCallback,const CodecOnDecodeResult & onDecodeResultCallback)29 AudioDecoder::AudioDecoder(uint64_t id, const CodecOnInData& packetReadFunc,
30 const CodecOnDecodeFrame& onDecodeFrameCallback, const CodecOnDecodeResult& onDecodeResultCallback)
31 : CodecDecoder(id, "audio-decoder"), packetReadFunc_(packetReadFunc), onDecodeFrameCallback_(onDecodeFrameCallback),
32 onDecodeResultCallback_(onDecodeResultCallback)
33 {
34 }
35
~AudioDecoder()36 AudioDecoder::~AudioDecoder()
37 {
38 MEDIA_LOGD("[%{public}s] destruct.", logTag_.c_str());
39 if (decoder_) {
40 OH_AudioDecoder_Destroy(decoder_);
41 decoder_ = nullptr;
42 }
43 }
44
Init(OH_AVFormat * format)45 VEFError AudioDecoder::Init(OH_AVFormat* format)
46 {
47 MEDIA_LOGI("[%{public}s] init.", logTag_.c_str());
48 if (format == nullptr) {
49 MEDIA_LOGE("[%{public}s] init failed, parameter format is nullptr.", logTag_.c_str());
50 return VEFError::ERR_INTERNAL_ERROR;
51 }
52 if (!packetReadFunc_ || !onDecodeFrameCallback_ || !onDecodeResultCallback_) {
53 MEDIA_LOGE("[%{public}s] init failed, invalid callback.", logTag_.c_str());
54 return VEFError::ERR_INTERNAL_ERROR;
55 }
56 std::string dumpInfo = OH_AVFormat_DumpInfo(format);
57 MEDIA_LOGI("[%{public}s] initializing decoder, format: %{public}s.", logTag_.c_str(), dumpInfo.c_str());
58
59 const char* mime = nullptr;
60 if (!OH_AVFormat_GetStringValue(format, OH_MD_KEY_CODEC_MIME, &mime)) {
61 MEDIA_LOGE("[%{public}s] get [%{public}s] from format failed.", logTag_.c_str(), OH_MD_KEY_CODEC_MIME);
62 return VEFError::ERR_INTERNAL_ERROR;
63 }
64 codecMime_ = mime;
65 MEDIA_LOGI("[%{public}s] initializing decoder, mime = %{public}s.", logTag_.c_str(), mime);
66
67 VEFError err = CreateDecoder();
68 if (err != VEFError::ERR_OK) {
69 MEDIA_LOGE("[%{public}s] init failed, create decoder failed with error: %{public}d.", logTag_.c_str(), err);
70 return err;
71 }
72
73 err = ConfigureDecoder(format);
74 if (err != VEFError::ERR_OK) {
75 MEDIA_LOGE("[%{public}s] init failed, configure decoder failed with error: %{public}d.", logTag_.c_str(), err);
76 return err;
77 }
78 MEDIA_LOGI("[%{public}s] init success.", logTag_.c_str());
79 return VEFError::ERR_OK;
80 }
81
SetPcmOutputBufferQueue(std::shared_ptr<PcmBufferQueue> & queue)82 void AudioDecoder::SetPcmOutputBufferQueue(std::shared_ptr<PcmBufferQueue>& queue)
83 {
84 pcmInputBufferQueue_ = queue;
85 }
86
Start()87 VEFError AudioDecoder::Start()
88 {
89 MEDIA_LOGI("[%{public}s] start.", logTag_.c_str());
90 auto ret = OH_AudioDecoder_Prepare(decoder_);
91 if (ret != AV_ERR_OK) {
92 MEDIA_LOGE("[%{public}s] start failed, OH_AudioDecoder_Prepare return %{public}d(%{public}s).", logTag_.c_str(),
93 ret, CodecUtil::GetCodecErrorStr(ret));
94 return VEFError::ERR_INTERNAL_ERROR;
95 }
96 // OH_AudioDecoder_Start结果判断
97 ret = OH_AudioDecoder_Start(decoder_);
98 if (ret != AV_ERR_OK) {
99 MEDIA_LOGE("[%{public}s] start failed, OH_AudioDecoder_Start return %{public}d(%{public}s).", logTag_.c_str(),
100 ret, CodecUtil::GetCodecErrorStr(ret));
101 return VEFError::ERR_INTERNAL_ERROR;
102 }
103 state_ = CodecState::RUNNING;
104 MEDIA_LOGI("[%{public}s] start success.", logTag_.c_str());
105 return VEFError::ERR_OK;
106 }
107
Stop()108 VEFError AudioDecoder::Stop()
109 {
110 MEDIA_LOGI("[%{public}s] stop.", logTag_.c_str());
111 pcmInputBufferQueue_->CancelEnqueue();
112 auto ret = OH_AudioDecoder_Stop(decoder_);
113 if (ret != AV_ERR_OK) {
114 MEDIA_LOGE("[%{public}s] stop failed, OH_AudioDecoder_Stop return %{public}d(%{public}s).", logTag_.c_str(),
115 ret, CodecUtil::GetCodecErrorStr(ret));
116 return VEFError::ERR_INTERNAL_ERROR;
117 }
118 state_ = CodecState::CANCEL;
119 MEDIA_LOGI("[%{public}s] stop success.", logTag_.c_str());
120 return VEFError::ERR_OK;
121 }
122
CreateDecoder()123 VEFError AudioDecoder::CreateDecoder()
124 {
125 decoder_ = OH_AudioDecoder_CreateByMime(codecMime_.c_str());
126 if (decoder_ == nullptr) {
127 MEDIA_LOGE("[%{public}s] create decoder failed, OH_AudioDecoder_CreateByMime failed, mime = %{public}s!",
128 logTag_.c_str(), codecMime_.c_str());
129 return VEFError::ERR_INTERNAL_ERROR;
130 }
131
132 auto ret = OH_AudioDecoder_SetCallback(decoder_, GetAVCodecAsyncCallback(), (CodecDecoder*)this);
133 if (ret != AV_ERR_OK) {
134 MEDIA_LOGE("[%{public}s] set callback for decoder error, return %{public}d(%{public}s).", logTag_.c_str(), ret,
135 CodecUtil::GetCodecErrorStr(ret));
136 return VEFError::ERR_INTERNAL_ERROR;
137 }
138 return VEFError::ERR_OK;
139 }
140
ConfigureDecoder(OH_AVFormat * format)141 VEFError AudioDecoder::ConfigureDecoder(OH_AVFormat* format)
142 {
143 OH_AVErrCode err = OH_AudioDecoder_Configure(decoder_, format);
144 if (err != AV_ERR_OK) {
145 MEDIA_LOGE("[%{public}s] configure decoder failed, OH_AudioDecoder_Configure return: %{public}d(%{public}s).",
146 logTag_.c_str(), err, CodecUtil::GetCodecErrorStr(err));
147 return VEFError::ERR_INTERNAL_ERROR;
148 }
149 return VEFError::ERR_OK;
150 }
151
CodecOnErrorInner(OH_AVCodec * codec,int32_t errorCode)152 void AudioDecoder::CodecOnErrorInner(OH_AVCodec* codec, int32_t errorCode)
153 {
154 if (codec == nullptr) {
155 MEDIA_LOGE("[%{public}s] CodecOnErrorInner invalid parameter, codec is nullptr.", logTag_.c_str());
156 return;
157 }
158 MEDIA_LOGI("[%{public}s] CodecOnError: %{public}d(%{public}s).", logTag_.c_str(), errorCode,
159 CodecUtil::GetCodecErrorStr((OH_AVErrCode)errorCode));
160 onDecodeResultCallback_(CodecResult::FAILED);
161 }
162
CodecOnStreamChangedInner(OH_AVFormat * format)163 void AudioDecoder::CodecOnStreamChangedInner(OH_AVFormat *format)
164 {
165 if (format == nullptr) {
166 MEDIA_LOGE("[%{public}s] invalid parameter, format is nullptr.", logTag_.c_str());
167 return;
168 }
169 MEDIA_LOGI("[%{public}s] CodecOnStreamChanged %{public}s.", logTag_.c_str(), OH_AVFormat_DumpInfo(format));
170 }
171
CodecOnNeedInputDataInner(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data)172 void AudioDecoder::CodecOnNeedInputDataInner(OH_AVCodec *codec, uint32_t index, OH_AVMemory* data)
173 {
174 if (codec == nullptr || data == nullptr) {
175 MEDIA_LOGE("[%{public}s] invalid parameter, codec or data is nullptr.", logTag_.c_str());
176 return;
177 }
178 MEDIA_LOGD("[%{public}s] CodecOnNeedInputDataInner index %{public}u.", logTag_.c_str(), index);
179
180 OH_AVCodecBufferAttr attr;
181 VEFError error = packetReadFunc_(codec, data, &attr);
182 if (error != VEFError::ERR_OK) {
183 MEDIA_LOGE("[%{public}s] read packet failed with error: %{public}d.", logTag_.c_str(), error);
184 return;
185 }
186 auto errCode = OH_AudioDecoder_PushInputData(decoder_, index, attr);
187 if (errCode != AV_ERR_OK) {
188 MEDIA_LOGE("[%{public}s] push inputData index %{public}u pts %{public}" PRIu64 " size %{public}d"
189 "flags %{public}u ret %{public}s", logTag_.c_str(), index, attr.pts, attr.size, attr.flags,
190 CodecUtil::GetCodecErrorStr(errCode));
191 onDecodeResultCallback_(CodecResult::FAILED);
192 return;
193 }
194 }
195
CodecOnNewOutputDataInner(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr)196 void AudioDecoder::CodecOnNewOutputDataInner(OH_AVCodec *codec, uint32_t index, OH_AVMemory* data,
197 OH_AVCodecBufferAttr* attr)
198 {
199 if (codec == nullptr || data == nullptr || attr == nullptr) {
200 MEDIA_LOGE("[%{public}s] invalid parameter, codec or data or attr is nullptr.", logTag_.c_str());
201 return;
202 }
203 MEDIA_LOGD("[%{public}s] CodecOnNewOutputDataInner index %{public}u.", logTag_.c_str(), index);
204
205 std::shared_ptr<PcmData> pcmData = std::make_shared<PcmData>();
206 pcmData->flags = attr->flags;
207 pcmData->pts = attr->pts;
208 if ((attr->flags & AVCODEC_BUFFER_FLAGS_EOS) == AVCODEC_BUFFER_FLAGS_EOS) {
209 pcmData->dataSize = 0;
210 pcmData->data = nullptr;
211 } else {
212 pcmData->dataSize = attr->size;
213 uint8_t* pcm = new (std::nothrow) uint8_t[pcmData->dataSize];
214 pcmData->data = std::shared_ptr<uint8_t>(pcm, std::default_delete<uint8_t[]>());
215 if (pcmData->data == nullptr) {
216 MEDIA_LOGE("[%{public}s] malloc memory for pcmData failed.", logTag_.c_str());
217 OH_AudioDecoder_FreeOutputData(codec, index);
218 onDecodeResultCallback_(CodecResult::FAILED);
219 return;
220 }
221 uint8_t* rawData = OH_AVMemory_GetAddr(data) + attr->offset;
222 int32_t error = memcpy_s(pcmData->data.get(), pcmData->dataSize, rawData, attr->size);
223 if (error != EOK) {
224 MEDIA_LOGE("[%{public}s] copy data failed, err = %{public}d.", logTag_.c_str(), error);
225 OH_AudioDecoder_FreeOutputData(codec, index);
226 onDecodeResultCallback_(CodecResult::FAILED);
227 return;
228 }
229 }
230
231 OH_AudioDecoder_FreeOutputData(codec, index);
232 pcmInputBufferQueue_->Enqueue(pcmData);
233
234 if ((attr->flags & AVCODEC_BUFFER_FLAGS_EOS) == AVCODEC_BUFFER_FLAGS_EOS) {
235 MEDIA_LOGI("[%{public}s] audio decode output EOS.", logTag_.c_str());
236 onDecodeResultCallback_(CodecResult::SUCCESS);
237 } else {
238 onDecodeFrameCallback_(attr->pts);
239 }
240 }
241 } // namespace Media
242 } // namespace OHOS