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