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