• 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_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