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