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