1 /*
2 * Copyright (C) 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 #include <fcntl.h>
16 #include <functional>
17 #include <cstdio>
18 #include "isoundpool.h"
19 #include "sound_parser.h"
20
21 namespace {
22 static constexpr int32_t MAX_SOUND_BUFFER_SIZE = 1 * 1024 * 1024;
23 static const std::string AUDIO_RAW_MIMETYPE_INFO = "audio/raw";
24 static const std::string AUDIO_MPEG_MIMETYPE_INFO = "audio/mpeg";
25 }
26
27 namespace OHOS {
28 namespace Media {
SoundParser(int32_t soundID,std::string url)29 SoundParser::SoundParser(int32_t soundID, std::string url)
30 {
31 std::shared_ptr<MediaAVCodec::AVSource> source = MediaAVCodec::AVSourceFactory::CreateWithURI(url);
32 CHECK_AND_RETURN_LOG(source != nullptr, "Create AVSource failed");
33 std::shared_ptr<MediaAVCodec::AVDemuxer> demuxer = MediaAVCodec::AVDemuxerFactory::CreateWithSource(source);
34 CHECK_AND_RETURN_LOG(demuxer != nullptr, "Create AVDemuxer failed");
35 soundID_ = soundID;
36 demuxer_ = demuxer;
37 source_ = source;
38 }
39
SoundParser(int32_t soundID,int32_t fd,int64_t offset,int64_t length)40 SoundParser::SoundParser(int32_t soundID, int32_t fd, int64_t offset, int64_t length)
41 {
42 fd = fcntl(fd, F_DUPFD_CLOEXEC, MIN_FD); // dup(fd) + close on exec to prevent leaks.
43 offset = offset >= INT64_MAX ? INT64_MAX : offset;
44 length = length >= INT64_MAX ? INT64_MAX : length;
45 std::shared_ptr<MediaAVCodec::AVSource> source = MediaAVCodec::AVSourceFactory::CreateWithFD(fd, offset, length);
46 CHECK_AND_RETURN_LOG(source != nullptr, "Create AVSource failed");
47 std::shared_ptr<MediaAVCodec::AVDemuxer> demuxer = MediaAVCodec::AVDemuxerFactory::CreateWithSource(source);
48 CHECK_AND_RETURN_LOG(demuxer != nullptr, "Create AVDemuxer failed");
49
50 soundID_ = soundID;
51 demuxer_ = demuxer;
52 source_ = source;
53 }
54
~SoundParser()55 SoundParser::~SoundParser()
56 {
57 MEDIA_INFO_LOG("SoundParser Destruction.");
58 Release();
59 }
60
DoParser()61 int32_t SoundParser::DoParser()
62 {
63 MEDIA_ERR_LOG("SoundParser do parser.");
64 std::unique_lock<std::mutex> lock(soundParserLock_);
65 DoDemuxer(&trackFormat_);
66 DoDecode(trackFormat_);
67 return MSERR_OK;
68 }
69
DoDemuxer(MediaAVCodec::Format * trackFormat)70 int32_t SoundParser::DoDemuxer(MediaAVCodec::Format *trackFormat)
71 {
72 MediaAVCodec::Format sourceFormat;
73 int32_t sourceTrackCountInfo = 0;
74 int64_t sourceDurationInfo = 0;
75 CHECK_AND_RETURN_RET_LOG(source_ != nullptr, MSERR_INVALID_VAL, "Failed to obtain av source");
76 CHECK_AND_RETURN_RET_LOG(demuxer_ != nullptr, MSERR_INVALID_VAL, "Failed to obtain demuxer");
77 CHECK_AND_RETURN_RET_LOG(trackFormat != nullptr, MSERR_INVALID_VAL, "Invalid trackFormat.");
78 int32_t ret = source_->GetSourceFormat(sourceFormat);
79 if (ret != 0) {
80 MEDIA_ERR_LOG("Get source format failed:%{public}d", ret);
81 }
82 sourceFormat.GetIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_TRACK_COUNT, sourceTrackCountInfo);
83 sourceFormat.GetLongValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_DURATION, sourceDurationInfo);
84
85 MEDIA_INFO_LOG("SoundParser sourceTrackCountInfo:%{public}d", sourceTrackCountInfo);
86 for (int32_t sourceTrackIndex = 0; sourceTrackIndex < sourceTrackCountInfo; sourceTrackIndex++) {
87 int32_t trackType = 0;
88 ret = source_->GetTrackFormat(*trackFormat, sourceTrackIndex);
89 if (ret != 0) {
90 MEDIA_ERR_LOG("Get track format failed:%{public}d", ret);
91 }
92 trackFormat->GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_TYPE, trackType);
93 MEDIA_INFO_LOG("SoundParser trackType:%{public}d", trackType);
94 if (trackType == MEDIA_TYPE_AUD) {
95 MEDIA_INFO_LOG("SoundParser trackType:%{public}d", trackType);
96 demuxer_->SelectTrackByID(sourceTrackIndex);
97 int32_t trackBitRateInfo;
98 std::string trackMimeTypeInfo;
99 trackFormat->GetIntValue(MediaDescriptionKey::MD_KEY_BITRATE, trackBitRateInfo);
100 trackFormat->PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, static_cast<int64_t>(trackBitRateInfo));
101 trackFormat->GetStringValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_MIME, trackMimeTypeInfo);
102 if (AUDIO_RAW_MIMETYPE_INFO.compare(trackMimeTypeInfo) != 0) {
103 // resample format
104 trackFormat->PutIntValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT,
105 MediaAVCodec::SAMPLE_S16LE);
106 } else {
107 isRawFile_ = true;
108 trackFormat->PutStringValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_MIME,
109 AUDIO_MPEG_MIMETYPE_INFO);
110 }
111 break;
112 }
113 }
114 return MSERR_OK;
115 }
116
DoDecode(MediaAVCodec::Format trackFormat)117 int32_t SoundParser::DoDecode(MediaAVCodec::Format trackFormat)
118 {
119 int32_t trackTypeInfo;
120 trackFormat.GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_TYPE, trackTypeInfo);
121 if (trackTypeInfo == MEDIA_TYPE_AUD) {
122 std::string trackMimeTypeInfo;
123 trackFormat.GetStringValue(MediaAVCodec::MediaDescriptionKey::MD_KEY_CODEC_MIME, trackMimeTypeInfo);
124 MEDIA_INFO_LOG("SoundParser mime type:%{public}s", trackMimeTypeInfo.c_str());
125 audioDec_ = MediaAVCodec::AudioDecoderFactory::CreateByMime(trackMimeTypeInfo);
126 CHECK_AND_RETURN_RET_LOG(audioDec_ != nullptr, MSERR_INVALID_VAL, "Failed to obtain audioDecorder.");
127 int32_t ret = audioDec_->Configure(trackFormat);
128 CHECK_AND_RETURN_RET_LOG(ret == 0, MSERR_INVALID_VAL, "Failed to configure audioDecorder.");
129 audioDecCb_ = std::make_shared<SoundDecoderCallback>(soundID_, audioDec_, demuxer_, isRawFile_);
130 CHECK_AND_RETURN_RET_LOG(audioDecCb_ != nullptr, MSERR_INVALID_VAL, "Failed to obtain decode callback.");
131 ret = audioDec_->SetCallback(audioDecCb_);
132 CHECK_AND_RETURN_RET_LOG(ret == 0, MSERR_INVALID_VAL, "Failed to setCallback audioDecorder");
133 soundParserListener_ = std::make_shared<SoundParserListener>(weak_from_this());
134 CHECK_AND_RETURN_RET_LOG(soundParserListener_ != nullptr, MSERR_INVALID_VAL, "Invalid sound parser listener");
135 audioDecCb_->SetDecodeCallback(soundParserListener_);
136 if (callback_ != nullptr) audioDecCb_->SetCallback(callback_);
137 ret = audioDec_->Start();
138 CHECK_AND_RETURN_RET_LOG(ret == 0, MSERR_INVALID_VAL, "Failed to Start audioDecorder.");
139 }
140 return MSERR_OK;
141 }
142
GetSoundData(std::deque<std::shared_ptr<AudioBufferEntry>> & soundData) const143 int32_t SoundParser::GetSoundData(std::deque<std::shared_ptr<AudioBufferEntry>> &soundData) const
144 {
145 CHECK_AND_RETURN_RET_LOG(soundParserListener_ != nullptr, MSERR_INVALID_VAL, "Invalid sound parser listener");
146 return soundParserListener_->GetSoundData(soundData);
147 }
148
GetSoundDataTotalSize() const149 size_t SoundParser::GetSoundDataTotalSize() const
150 {
151 CHECK_AND_RETURN_RET_LOG(soundParserListener_ != nullptr, MSERR_INVALID_VAL, "Invalid sound parser listener");
152 return soundParserListener_->GetSoundDataTotalSize();
153 }
154
IsSoundParserCompleted() const155 bool SoundParser::IsSoundParserCompleted() const
156 {
157 CHECK_AND_RETURN_RET_LOG(soundParserListener_ != nullptr, MSERR_INVALID_VAL, "Invalid sound parser listener");
158 return soundParserListener_->IsSoundParserCompleted();
159 }
160
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)161 int32_t SoundParser::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
162 {
163 callback_ = callback;
164 return MSERR_OK;
165 }
166
Release()167 int32_t SoundParser::Release()
168 {
169 MEDIA_INFO_LOG("SoundParser Release.");
170 int32_t ret = MSERR_OK;
171 if (soundParserListener_ != nullptr) soundParserListener_.reset();
172 if (audioDecCb_ != nullptr) {
173 ret = audioDecCb_->Release();
174 audioDecCb_.reset();
175 }
176 if (audioDec_ != nullptr) {
177 ret = audioDec_->Release();
178 audioDec_.reset();
179 }
180 if (demuxer_ != nullptr) demuxer_.reset();
181 if (source_ != nullptr) source_.reset();
182 if (callback_ != nullptr) callback_.reset();
183 return ret;
184 }
185
SoundDecoderCallback(const int32_t soundID,const std::shared_ptr<MediaAVCodec::AVCodecAudioDecoder> & audioDec,const std::shared_ptr<MediaAVCodec::AVDemuxer> & demuxer,const bool isRawFile)186 SoundDecoderCallback::SoundDecoderCallback(const int32_t soundID,
187 const std::shared_ptr<MediaAVCodec::AVCodecAudioDecoder> &audioDec,
188 const std::shared_ptr<MediaAVCodec::AVDemuxer> &demuxer,
189 const bool isRawFile) : soundID_(soundID), audioDec_(audioDec),
190 demuxer_(demuxer), isRawFile_(isRawFile), eosFlag_(false),
191 decodeShouldCompleted_(false), currentSoundBufferSize_(0)
192 {
193 MEDIA_INFO_LOG("Construction SoundDecoderCallback");
194 }
195
~SoundDecoderCallback()196 SoundDecoderCallback::~SoundDecoderCallback()
197 {
198 MEDIA_INFO_LOG("Destruction SoundDecoderCallback");
199 Release();
200 }
OnError(AVCodecErrorType errorType,int32_t errorCode)201 void SoundDecoderCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
202 {
203 if (isRawFile_) {
204 MEDIA_INFO_LOG("Recive error, errorType:%{public}d,errorCode:%{public}d", errorType, errorCode);
205 }
206 }
207
OnOutputFormatChanged(const Format & format)208 void SoundDecoderCallback::OnOutputFormatChanged(const Format &format)
209 {
210 (void)format;
211 }
212
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)213 void SoundDecoderCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
214 {
215 std::unique_lock<std::mutex> lock(amutex_);
216 MediaAVCodec::AVCodecBufferFlag bufferFlag = MediaAVCodec::AVCodecBufferFlag::AVCODEC_BUFFER_FLAG_NONE;
217 MediaAVCodec::AVCodecBufferInfo sampleInfo;
218 CHECK_AND_RETURN_LOG(demuxer_ != nullptr, "Failed to obtain demuxer");
219 CHECK_AND_RETURN_LOG(audioDec_ != nullptr, "Failed to obtain audio decode.");
220
221 if (isRawFile_ && !decodeShouldCompleted_) {
222 if (demuxer_->ReadSample(0, buffer, sampleInfo, bufferFlag) != AVCS_ERR_OK) {
223 MEDIA_ERR_LOG("SoundDecoderCallback demuxer error.");
224 return;
225 }
226 if (!decodeShouldCompleted_ && (currentSoundBufferSize_ > MAX_SOUND_BUFFER_SIZE ||
227 bufferFlag == AVCODEC_BUFFER_FLAG_EOS)) {
228 decodeShouldCompleted_ = true;
229 CHECK_AND_RETURN_LOG(listener_ != nullptr, "sound decode listener invalid.");
230 listener_->OnSoundDecodeCompleted(availableAudioBuffers_);
231 listener_->SetSoundBufferTotalSize(static_cast<size_t>(currentSoundBufferSize_));
232 CHECK_AND_RETURN_LOG(callback_ != nullptr, "sound decode:soundpool callback invalid.");
233 callback_->OnLoadCompleted(soundID_);
234 return;
235 }
236 int32_t size = sampleInfo.size;
237 uint8_t *buf = new(std::nothrow) uint8_t[size];
238 if (buf != nullptr) {
239 if (memcpy_s(buf, size, buffer->GetBase(), size) != EOK) {
240 MEDIA_INFO_LOG("audio buffer copy failed:%{public}s", strerror(errno));
241 } else {
242 availableAudioBuffers_.push_back(std::make_shared<AudioBufferEntry>(buf, size));
243 bufferCond_.notify_all();
244 }
245 }
246 currentSoundBufferSize_ += size;
247 audioDec_->QueueInputBuffer(index, sampleInfo, bufferFlag);
248 return;
249 }
250
251 if (!eosFlag_ && !decodeShouldCompleted_) {
252 if (demuxer_->ReadSample(0, buffer, sampleInfo, bufferFlag) != AVCS_ERR_OK) {
253 MEDIA_ERR_LOG("SoundDecoderCallback demuxer error.");
254 return;
255 }
256 if (bufferFlag == AVCODEC_BUFFER_FLAG_EOS) {
257 eosFlag_ = true;
258 }
259 audioDec_->QueueInputBuffer(index, sampleInfo, bufferFlag);
260 }
261 }
262
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)263 void SoundDecoderCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag,
264 std::shared_ptr<AVSharedMemory> buffer)
265 {
266 std::unique_lock<std::mutex> lock(amutex_);
267 if (isRawFile_) {
268 MEDIA_INFO_LOG("audio raw data, return.");
269 CHECK_AND_RETURN_LOG(audioDec_ != nullptr, "Failed to obtain audio decode.");
270 audioDec_->ReleaseOutputBuffer(index);
271 return;
272 }
273 if (buffer != nullptr && !decodeShouldCompleted_) {
274 if (currentSoundBufferSize_ > MAX_SOUND_BUFFER_SIZE || flag == AVCODEC_BUFFER_FLAG_EOS) {
275 decodeShouldCompleted_ = true;
276 CHECK_AND_RETURN_LOG(listener_ != nullptr, "sound decode listener invalid.");
277 listener_->OnSoundDecodeCompleted(availableAudioBuffers_);
278 listener_->SetSoundBufferTotalSize(static_cast<size_t>(currentSoundBufferSize_));
279 CHECK_AND_RETURN_LOG(callback_ != nullptr, "sound decode:soundpool callback invalid.");
280 callback_->OnLoadCompleted(soundID_);
281 return;
282 }
283 int32_t size = info.size;
284 uint8_t *buf = new(std::nothrow) uint8_t[size];
285 if (buf != nullptr) {
286 if (memcpy_s(buf, size, buffer->GetBase(), info.size) != EOK) {
287 MEDIA_INFO_LOG("audio buffer copy failed:%{public}s", strerror(errno));
288 } else {
289 availableAudioBuffers_.push_back(std::make_shared<AudioBufferEntry>(buf, size));
290 bufferCond_.notify_all();
291 }
292 }
293 currentSoundBufferSize_ += size;
294 }
295 CHECK_AND_RETURN_LOG(audioDec_ != nullptr, "Failed to obtain audio decode.");
296 audioDec_->ReleaseOutputBuffer(index);
297 }
298
SetCallback(const std::shared_ptr<ISoundPoolCallback> & callback)299 int32_t SoundDecoderCallback::SetCallback(const std::shared_ptr<ISoundPoolCallback> &callback)
300 {
301 MEDIA_INFO_LOG("SoundDecoderCallback::SetCallback");
302 callback_ = callback;
303 return MSERR_OK;
304 }
305
Release()306 int32_t SoundDecoderCallback::Release()
307 {
308 int32_t ret = MSERR_OK;
309 MEDIA_INFO_LOG("SoundDecoderCallback Release.");
310 if (audioDec_ != nullptr) {
311 ret = audioDec_->Release();
312 audioDec_.reset();
313 }
314 if (demuxer_ != nullptr) demuxer_.reset();
315 if (listener_ != nullptr) listener_.reset();
316 if (!availableAudioBuffers_.empty()) availableAudioBuffers_.clear();
317 if (callback_ != nullptr) callback_.reset();
318 return ret;
319 }
320 } // namespace Media
321 } // namespace OHOS
322