• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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