• 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 "audio_haptic_sound_normal_impl.h"
17 
18 #include <fcntl.h>
19 
20 #include "audio_haptic_log.h"
21 #include "media_errors.h"
22 #include "player.h"
23 
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "AudioHapticSoundNormalImpl"};
26 }
27 
28 namespace OHOS {
29 namespace Media {
30 const int32_t LOAD_WAIT_SECONDS = 2;
31 
AudioHapticSoundNormalImpl(const std::string & audioUri,const bool & muteAudio,const AudioStandard::StreamUsage & streamUsage)32 AudioHapticSoundNormalImpl::AudioHapticSoundNormalImpl(const std::string &audioUri, const bool &muteAudio,
33     const AudioStandard::StreamUsage &streamUsage)
34     : audioUri_(audioUri),
35       muteAudio_(muteAudio),
36       streamUsage_(streamUsage)
37 {
38 }
39 
~AudioHapticSoundNormalImpl()40 AudioHapticSoundNormalImpl::~AudioHapticSoundNormalImpl()
41 {
42     if (avPlayer_ != nullptr) {
43         ReleaseAVPlayer();
44     }
45 }
46 
LoadAVPlayer()47 int32_t AudioHapticSoundNormalImpl::LoadAVPlayer()
48 {
49     avPlayer_ = PlayerFactory::CreatePlayer();
50     CHECK_AND_RETURN_RET_LOG(avPlayer_ != nullptr, MSERR_INVALID_VAL, "Failed to create AvPlayer instance");
51 
52     avPlayerCallback_ = std::make_shared<AHSoundNormalCallback>(shared_from_this());
53     CHECK_AND_RETURN_RET_LOG(avPlayerCallback_ != nullptr, MSERR_INVALID_VAL, "Failed to create callback object");
54     avPlayer_->SetPlayerCallback(avPlayerCallback_);
55 
56     configuredAudioUri_ = "";
57     playerState_ = AudioHapticPlayerState::STATE_NEW;
58     return MSERR_OK;
59 }
60 
PrepareSound()61 int32_t AudioHapticSoundNormalImpl::PrepareSound()
62 {
63     MEDIA_LOGI("PrepareSound with AVPlayer");
64     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
65     int32_t result = LoadAVPlayer();
66     CHECK_AND_RETURN_RET_LOG(result == MSERR_OK && avPlayer_ != nullptr, MSERR_INVALID_VAL,
67         "Audio haptic player(avplayer) instance is null");
68     CHECK_AND_RETURN_RET_LOG(!audioUri_.empty(), MSERR_OPEN_FILE_FAILED, "The audio uri is empty");
69     if (audioUri_ != configuredAudioUri_) {
70         return ResetAVPlayer();
71     }
72     return MSERR_OK;
73 }
74 
ResetAVPlayer()75 int32_t AudioHapticSoundNormalImpl::ResetAVPlayer()
76 {
77     // Reset the player and reload it.
78     MEDIA_LOGI("ResetAVPlayer");
79     (void)avPlayer_->Reset();
80     MEDIA_LOGI("Set audio source to avplayer. audioUri [%{public}s]", audioUri_.c_str());
81     const std::string fdHead = "fd://";
82 
83     if (audioUri_.find(fdHead) != std::string::npos) {
84         fileDes_ = std::stoi(audioUri_.substr(fdHead.size()));
85         MEDIA_LOGI("fileDes_ == %{public}d", fileDes_);
86     } else {
87         char realPathRes[PATH_MAX + 1] = {'\0'};
88         CHECK_AND_RETURN_RET_LOG((strlen(audioUri_.c_str()) < PATH_MAX) &&
89             (realpath(audioUri_.c_str(), realPathRes) != nullptr), MSERR_UNSUPPORT_FILE, "Invalid file path length");
90         std::string realPathStr(realPathRes);
91         if (fileDes_ != -1) {
92             (void)close(fileDes_);
93             fileDes_ = -1;
94         }
95         fileDes_ = open(realPathStr.c_str(), O_RDONLY);
96         CHECK_AND_RETURN_RET_LOG(fileDes_ != -1, MSERR_OPEN_FILE_FAILED, "Prepare: Failed to open uri for avplayer.");
97     }
98     int32_t ret = avPlayer_->SetSource(fileDes_);
99     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_OPEN_FILE_FAILED, "Set source failed %{public}d", ret);
100 
101     Format format;
102     format.PutIntValue(PlayerKeys::CONTENT_TYPE, AudioStandard::CONTENT_TYPE_UNKNOWN);
103     format.PutIntValue(PlayerKeys::STREAM_USAGE, streamUsage_);
104     ret = avPlayer_->SetParameter(format);
105     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Set stream usage to AVPlayer failed %{public}d", ret);
106 
107     ret = avPlayer_->PrepareAsync();
108     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Prepare failed %{public}d", ret);
109 
110     std::unique_lock<std::mutex> lockPrepare(prepareMutex_);
111     prepareCond_.wait_for(lockPrepare, std::chrono::seconds(LOAD_WAIT_SECONDS),
112         [this]() { return isPrepared_ || isReleased_ || isUnsupportedFile_; });
113     CHECK_AND_RETURN_RET_LOG(!isReleased_, MSERR_INVALID_OPERATION, "The avplayer is released when it is preparing.");
114     CHECK_AND_RETURN_RET_LOG(!isUnsupportedFile_, MSERR_UNSUPPORT_FILE, "Unsupported file when preparing avplayer.");
115     CHECK_AND_RETURN_RET_LOG(isPrepared_, MSERR_OPEN_FILE_FAILED, "Failed to load audio uri: time out.");
116 
117     // The avplayer has been prepared.
118     float actualVolume = volume_ * (muteAudio_ ? 0 : 1);
119     MEDIA_LOGI("AVPlayer has been prepared. Set volume %{public}f and loop %{public}d.", actualVolume, loop_);
120     (void)avPlayer_->SetVolume(actualVolume, actualVolume);
121     (void)avPlayer_->SetLooping(loop_);
122 
123     configuredAudioUri_ = audioUri_;
124     playerState_ = AudioHapticPlayerState::STATE_PREPARED;
125     return MSERR_OK;
126 }
127 
128 
StartSound()129 int32_t AudioHapticSoundNormalImpl::StartSound()
130 {
131     MEDIA_LOGI("StartSound with AVPlayer");
132     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
133     CHECK_AND_RETURN_RET_LOG(avPlayer_ != nullptr && playerState_ != AudioHapticPlayerState::STATE_INVALID,
134         MSERR_INVALID_VAL, "StartAVPlayer: no available AVPlayer_");
135     CHECK_AND_RETURN_RET_LOG(!audioUri_.empty(), MSERR_OPEN_FILE_FAILED, "The audio uri is empty");
136 
137     if (playerState_ == AudioHapticPlayerState::STATE_RUNNING) {
138         MEDIA_LOGE("The avplayer has been running. Cannot start again");
139         return MSERR_START_FAILED;
140     }
141 
142     // Player doesn't support play in stopped state. Hence reinitialise player for making start<-->stop to work
143     if (playerState_ == AudioHapticPlayerState::STATE_STOPPED || audioUri_ != configuredAudioUri_) {
144         ResetAVPlayer();
145     }
146     auto ret = avPlayer_->Play();
147     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_START_FAILED, "Start failed %{public}d", ret);
148 
149     playerState_ = AudioHapticPlayerState::STATE_RUNNING;
150     return MSERR_OK;
151 }
152 
StopSound()153 int32_t AudioHapticSoundNormalImpl::StopSound()
154 {
155     MEDIA_LOGI("StopSound with AVPlayer");
156     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
157     CHECK_AND_RETURN_RET_LOG(avPlayer_ != nullptr && playerState_ != AudioHapticPlayerState::STATE_INVALID,
158         MSERR_INVALID_VAL, "StopAVPlayer: no available AVPlayer_");
159 
160     if (playerState_ != AudioHapticPlayerState::STATE_STOPPED) {
161         (void)avPlayer_->Stop();
162     }
163 
164     playerState_ = AudioHapticPlayerState::STATE_STOPPED;
165     return MSERR_OK;
166 }
167 
ReleaseSound()168 int32_t AudioHapticSoundNormalImpl::ReleaseSound()
169 {
170     MEDIA_LOGI("ReleaseSound with AVPlayer");
171     {
172         std::lock_guard<std::mutex> lockPrepare(prepareMutex_);
173         isReleased_ = true;
174         prepareCond_.notify_one();
175     }
176     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
177     CHECK_AND_RETURN_RET_LOG(playerState_ != AudioHapticPlayerState::STATE_RELEASED, MSERR_OK,
178         "The audio haptic player for normal mode has been released.");
179     ReleaseAVPlayer();
180     playerState_ = AudioHapticPlayerState::STATE_RELEASED;
181     return MSERR_OK;
182 }
183 
ReleaseAVPlayer()184 void AudioHapticSoundNormalImpl::ReleaseAVPlayer()
185 {
186     if (avPlayer_ != nullptr) {
187         (void)avPlayer_->Release();
188         avPlayer_ = nullptr;
189     }
190     avPlayerCallback_ = nullptr;
191     if (fileDes_ != -1) {
192         (void)close(fileDes_);
193         fileDes_ = -1;
194     }
195 }
196 
SetVolume(float volume)197 int32_t AudioHapticSoundNormalImpl::SetVolume(float volume)
198 {
199     MEDIA_LOGI("AudioHapticSoundNormalImpl::SetVolume %{public}f", volume);
200     if (volume < 0.0f || volume > 1.0f) {
201         MEDIA_LOGE("SetVolume: the volume value is invalid.");
202         return MSERR_INVALID_VAL;
203     }
204 
205     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
206     int32_t result = MSERR_OK;
207     volume_ = volume;
208 
209     if (playerState_ != AudioHapticPlayerState::STATE_PREPARED &&
210         playerState_ != AudioHapticPlayerState::STATE_RUNNING) {
211         MEDIA_LOGI("Audio haptic player is not prepared or running. No need to modify player");
212         return result;
213     }
214 
215     float actualVolume = volume_ * (muteAudio_ ? 0 : 1);
216     result = avPlayer_->SetVolume(actualVolume, actualVolume);
217     return result;
218 }
219 
SetLoop(bool loop)220 int32_t AudioHapticSoundNormalImpl::SetLoop(bool loop)
221 {
222     MEDIA_LOGI("AudioHapticSoundNormalImpl::SetLoop %{public}d", loop);
223     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
224     int32_t result = MSERR_OK;
225     loop_ = loop;
226 
227     if (playerState_ != AudioHapticPlayerState::STATE_PREPARED &&
228         playerState_ != AudioHapticPlayerState::STATE_RUNNING) {
229         MEDIA_LOGI("Audio haptic player is not prepared or running. No need to modify player");
230         return result;
231     }
232 
233     result = avPlayer_->SetLooping(loop_);
234     return result;
235 }
236 
GetAudioCurrentTime()237 int32_t AudioHapticSoundNormalImpl::GetAudioCurrentTime()
238 {
239     if (avPlayer_ == nullptr) {
240         MEDIA_LOGE("GetAudioCurrentTime: avPlayer_ is nullptr. This function is only usable for avPlayer.");
241         return -1;
242     }
243     int32_t currentTime = -1;
244     (void)avPlayer_->GetCurrentTime(currentTime);
245     return currentTime;
246 }
247 
SetAudioHapticSoundCallback(const std::shared_ptr<AudioHapticSoundCallback> & callback)248 int32_t AudioHapticSoundNormalImpl::SetAudioHapticSoundCallback(
249     const std::shared_ptr<AudioHapticSoundCallback> &callback)
250 {
251     if (callback == nullptr) {
252         MEDIA_LOGE("The audio haptic player callback is nullptr.");
253         return MSERR_INVALID_VAL;
254     }
255 
256     std::lock_guard<std::mutex> lock(audioHapticPlayerLock_);
257     audioHapticPlayerCallback_ = callback;
258     return MSERR_OK;
259 }
260 
SetAVPlayerState(AudioHapticPlayerState playerState)261 void AudioHapticSoundNormalImpl::SetAVPlayerState(AudioHapticPlayerState playerState)
262 {
263     MEDIA_LOGI("SetAVPlayerState, state %{public}d", playerState);
264     playerState_ = playerState;
265 }
266 
NotifyPreparedEvent()267 void AudioHapticSoundNormalImpl::NotifyPreparedEvent()
268 {
269     std::lock_guard<std::mutex> lockPrepare(prepareMutex_);
270     isPrepared_ = true;
271     prepareCond_.notify_one();
272 }
273 
NotifyErrorEvent(int32_t errorCode)274 void AudioHapticSoundNormalImpl::NotifyErrorEvent(int32_t errorCode)
275 {
276     MediaServiceErrCode mediaErr = static_cast<MediaServiceErrCode>(errorCode);
277     if (mediaErr == MSERR_UNSUPPORT_FILE) {
278         std::lock_guard<std::mutex> lockPrepare(prepareMutex_);
279         isUnsupportedFile_ = true;
280         prepareCond_.notify_one();
281     }
282 
283     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
284     if (cb != nullptr) {
285         MEDIA_LOGI("NotifyFirstFrameEvent for audio haptic player");
286         cb->OnError(errorCode);
287     } else {
288         MEDIA_LOGE("NotifyFirstFrameEvent: audioHapticPlayerCallback_ is nullptr");
289     }
290 }
291 
NotifyFirstFrameEvent(uint64_t latency)292 void AudioHapticSoundNormalImpl::NotifyFirstFrameEvent(uint64_t latency)
293 {
294     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
295     if (cb != nullptr) {
296         MEDIA_LOGI("NotifyFirstFrameEvent for audio haptic player");
297         cb->OnFirstFrameWriting(latency);
298     } else {
299         MEDIA_LOGE("NotifyFirstFrameEvent: audioHapticPlayerCallback_ is nullptr");
300     }
301 }
302 
NotifyInterruptEvent(AudioStandard::InterruptEvent & interruptEvent)303 void AudioHapticSoundNormalImpl::NotifyInterruptEvent(AudioStandard::InterruptEvent &interruptEvent)
304 {
305     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
306     if (cb != nullptr) {
307         MEDIA_LOGI("NotifyInterruptEvent for audio haptic player");
308         cb->OnInterrupt(interruptEvent);
309     } else {
310         MEDIA_LOGE("NotifyInterruptEvent: audioHapticPlayerCallback_ is nullptr");
311     }
312 }
313 
NotifyEndOfStreamEvent()314 void AudioHapticSoundNormalImpl::NotifyEndOfStreamEvent()
315 {
316     MEDIA_LOGI("NotifyEndOfStreamEvent");
317     playerState_ = AudioHapticPlayerState::STATE_STOPPED;
318     std::shared_ptr<AudioHapticSoundCallback> cb = audioHapticPlayerCallback_.lock();
319     if (cb != nullptr) {
320         MEDIA_LOGI("NotifyEndOfStreamEvent for audio haptic player");
321         cb->OnEndOfStream();
322     } else {
323         MEDIA_LOGE("NotifyEndOfStreamEvent: audioHapticPlayerCallback_ is nullptr");
324     }
325 }
326 
327 // Callback class symbols
AHSoundNormalCallback(std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl)328 AHSoundNormalCallback::AHSoundNormalCallback(std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl)
329     : soundNormalImpl_(soundNormalImpl) {}
330 
OnError(int32_t errorCode,const std::string & errorMsg)331 void AHSoundNormalCallback::OnError(int32_t errorCode, const std::string &errorMsg)
332 {
333     MEDIA_LOGE("OnError reported from AVPlayer: %{public}d", errorCode);
334     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
335     if (soundNormalImpl == nullptr) {
336         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
337         return;
338     }
339     soundNormalImpl->NotifyErrorEvent(errorCode);
340 }
341 
OnInfo(Media::PlayerOnInfoType type,int32_t extra,const Media::Format & infoBody)342 void AHSoundNormalCallback::OnInfo(Media::PlayerOnInfoType type, int32_t extra, const Media::Format &infoBody)
343 {
344     if (type == INFO_TYPE_STATE_CHANGE) {
345         MEDIA_LOGI("OnInfo: state change reported from AVPlayer.");
346         HandleStateChangeEvent(extra, infoBody);
347     } else if (type == INFO_TYPE_INTERRUPT_EVENT) {
348         MEDIA_LOGI("OnInfo: interrupt event reported from AVPlayer.");
349         HandleAudioInterruptEvent(extra, infoBody);
350     } else if (type == INFO_TYPE_AUDIO_FIRST_FRAME) {
351         MEDIA_LOGI("OnInfo: first frame event reported from AVPlayer.");
352         HandleAudioFirstFrameEvent(extra, infoBody);
353     } else {
354         return;
355     }
356 }
357 
HandleStateChangeEvent(int32_t extra,const Format & infoBody)358 void AHSoundNormalCallback::HandleStateChangeEvent(int32_t extra, const Format &infoBody)
359 {
360     MEDIA_LOGI("HandleStateChangeEvent from AVPlayer");
361     PlayerStates avPlayerState = static_cast<PlayerStates>(extra);
362     switch (avPlayerState) {
363         case PLAYER_STATE_ERROR:
364             playerState_ = AudioHapticPlayerState::STATE_INVALID;
365             break;
366         case PLAYER_IDLE:
367         case PLAYER_INITIALIZED:
368         case PLAYER_PREPARING:
369             playerState_ = AudioHapticPlayerState::STATE_NEW;
370             break;
371         case PLAYER_PREPARED:
372             playerState_ = AudioHapticPlayerState::STATE_PREPARED;
373             break;
374         case PLAYER_STARTED:
375             playerState_ = AudioHapticPlayerState::STATE_RUNNING;
376             break;
377         case PLAYER_PAUSED:
378             playerState_ = AudioHapticPlayerState::STATE_PAUSED;
379             break;
380         case PLAYER_STOPPED:
381         case PLAYER_PLAYBACK_COMPLETE:
382             playerState_ = AudioHapticPlayerState::STATE_STOPPED;
383             break;
384         default:
385             break;
386     }
387     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
388     if (soundNormalImpl == nullptr) {
389         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
390         return;
391     }
392     soundNormalImpl->SetAVPlayerState(playerState_);
393 
394     if (avPlayerState == PLAYER_PREPARED) {
395         soundNormalImpl->NotifyPreparedEvent();
396     } else if (avPlayerState == PLAYER_PLAYBACK_COMPLETE) {
397         soundNormalImpl->NotifyEndOfStreamEvent();
398     }
399 }
400 
HandleAudioInterruptEvent(int32_t extra,const Format & infoBody)401 void AHSoundNormalCallback::HandleAudioInterruptEvent(int32_t extra, const Format &infoBody)
402 {
403     MEDIA_LOGI("HandleAudioInterruptEvent from AVPlayer");
404     AudioStandard::InterruptEvent interruptEvent;
405     int32_t eventTypeValue = 0;
406     int32_t forceTypeValue = 0;
407     int32_t hintTypeValue = 0;
408     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventTypeValue);
409     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceTypeValue);
410     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintTypeValue);
411     interruptEvent.eventType = static_cast<AudioStandard::InterruptType>(eventTypeValue);
412     interruptEvent.forceType = static_cast<AudioStandard::InterruptForceType>(forceTypeValue);
413     interruptEvent.hintType = static_cast<AudioStandard::InterruptHint>(hintTypeValue);
414 
415     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
416     if (soundNormalImpl == nullptr) {
417         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
418         return;
419     }
420     soundNormalImpl->NotifyInterruptEvent(interruptEvent);
421 }
422 
HandleAudioFirstFrameEvent(int32_t extra,const Format & infoBody)423 void AHSoundNormalCallback::HandleAudioFirstFrameEvent(int32_t extra, const Format &infoBody)
424 {
425     int64_t value = 0;
426     (void)infoBody.GetLongValue(PlayerKeys::AUDIO_FIRST_FRAME, value);
427     uint64_t latency = static_cast<uint64_t>(value);
428     MEDIA_LOGI("HandleAudioFirstFrameEvent from AVPlayer. Latency %{public}" PRIu64 "", latency);
429     std::shared_ptr<AudioHapticSoundNormalImpl> soundNormalImpl = soundNormalImpl_.lock();
430     if (soundNormalImpl == nullptr) {
431         MEDIA_LOGE("The audio haptic player for normal mode has been released.");
432         return;
433     }
434     soundNormalImpl->NotifyFirstFrameEvent(latency);
435 }
436 } // namesapce AudioStandard
437 } // namespace OHOS