• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 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 #define HST_LOG_TAG "HiPlayerImpl"
17 
18 #include "hiplayer_impl.h"
19 #include "foundation/log.h"
20 #include "hitrace_meter.h"
21 #include "pipeline/factory/filter_factory.h"
22 #include "scene/player/standard/media_utils.h"
23 #include "plugin/common/media_source.h"
24 #include "plugin/common/plugin_time.h"
25 #include "plugin/core/plugin_meta.h"
26 #include "utils/steady_clock.h"
27 #include "av_common.h"
28 #include "media_errors.h"
29 
30 namespace {
31 const float MAX_MEDIA_VOLUME = 1.0f; // standard interface volume is between 0 to 1.
32 }
33 
34 namespace OHOS {
35 namespace Media {
36 using namespace Pipeline;
37 constexpr double EPSINON = 0.0001;
38 constexpr double SPEED_0_75_X = 0.75;
39 constexpr double SPEED_1_00_X = 1.00;
40 constexpr double SPEED_1_25_X = 1.25;
41 constexpr double SPEED_1_75_X = 1.75;
42 constexpr double SPEED_2_00_X = 2.00;
43 
HiPlayerImpl(int32_t appUid,int32_t appPid)44 HiPlayerImpl::HiPlayerImpl(int32_t appUid, int32_t appPid)
45     : appUid_(appUid),
46       appPid_(appPid),
47       fsm_(*this),
48       curFsmState_(StateId::IDLE),
49       volume_(-1.0f), // default negative, if app not set, will not set it.
50       mediaStats_()
51 {
52     StartTrace(HITRACE_TAG_ZMEDIA, "Hst hiPlayerImpl ctor");
53     MEDIA_LOG_I("hiPlayerImpl ctor");
54     FilterFactory::Instance().Init();
55     syncManager_ = std::make_shared<MediaSyncManager>();
56 
57     audioSource_ =
58         FilterFactory::Instance().CreateFilterWithType<MediaSourceFilter>("builtin.player.mediasource", "mediaSource");
59 #ifdef UNIT_TEST
60     demuxer_ = FilterFactory::Instance().CreateFilterWithType<DemuxerFilter>("builtin.player.demuxer", "demuxer");
61     audioDecoder_ = FilterFactory::Instance().CreateFilterWithType<AudioDecoderFilter>("builtin.player.audiodecoder",
62                                                                                        "audiodecoder");
63     audioSink_ =
64         FilterFactory::Instance().CreateFilterWithType<AudioSinkFilter>("builtin.player.audiosink", "audiosink");
65 #else
66     demuxer_ = FilterFactory::Instance().CreateFilterWithType<DemuxerFilter>("builtin.player.demuxer", "demuxer");
67     audioSink_ =
68         FilterFactory::Instance().CreateFilterWithType<AudioSinkFilter>("builtin.player.audiosink", "audioSink");
69     audioSink_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_PID), appPid_);
70     audioSink_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_UID), appUid_);
71 #ifdef VIDEO_SUPPORT
72     videoSink_ =
73         FilterFactory::Instance().CreateFilterWithType<VideoSinkFilter>("builtin.player.videosink", "videoSink");
74     FALSE_RETURN(videoSink_ != nullptr);
75     videoSink_->SetSyncCenter(syncManager_);
76 #endif
77 #endif
78     FALSE_RETURN(audioSource_ != nullptr);
79     FALSE_RETURN(demuxer_ != nullptr);
80     FALSE_RETURN(audioSink_ != nullptr);
81     audioSink_->SetSyncCenter(syncManager_);
82     pipeline_ = std::make_shared<PipelineCore>();
83     callbackLooper_.SetPlayEngine(this);
84     FinishTrace(HITRACE_TAG_ZMEDIA);
85 }
86 
~HiPlayerImpl()87 HiPlayerImpl::~HiPlayerImpl()
88 {
89     MEDIA_LOG_I("dtor called.");
90     fsm_.SendEventAsync(Intent::STOP);
91     fsm_.Stop();
92     callbackLooper_.Stop();
93     audioSink_.reset();
94 #ifdef VIDEO_SUPPORT
95     videoSink_.reset();
96     if (surface_) {
97         surface_ = nullptr;
98     }
99 #endif
100     syncManager_.reset();
101 }
UpdateStateNoLock(PlayerStates newState,bool notifyUpward)102 void HiPlayerImpl::UpdateStateNoLock(PlayerStates newState, bool notifyUpward)
103 {
104     if (pipelineStates_ == newState) {
105         return;
106     }
107     pipelineStates_ = newState;
108     if (pipelineStates_ == PlayerStates::PLAYER_IDLE) {
109         MEDIA_LOG_W("do not report idle since audio player will report idle");
110         return;
111     }
112     if (notifyUpward) {
113         if (callbackLooper_.IsStarted()) {
114             Format format;
115             while (!pendingStates_.empty()) {
116                 auto pendingState = pendingStates_.front();
117                 pendingStates_.pop();
118                 MEDIA_LOG_I("sending pending state change: " PUBLIC_LOG_S, StringnessPlayerState(pendingState).c_str());
119                 callbackLooper_.OnInfo(INFO_TYPE_STATE_CHANGE, pendingState, format);
120             }
121             MEDIA_LOG_I("sending newest state change: " PUBLIC_LOG_S,
122                         StringnessPlayerState(pipelineStates_.load()).c_str());
123             callbackLooper_.OnInfo(INFO_TYPE_STATE_CHANGE, pipelineStates_, format);
124         } else {
125             pendingStates_.push(newState);
126         }
127     }
128 }
129 
Init()130 ErrorCode HiPlayerImpl::Init()
131 {
132     MEDIA_LOG_I("Init entered.");
133     mediaStats_.Reset();
134     if (initialized_.load()) {
135         return ErrorCode::SUCCESS;
136     }
137     pipeline_->Init(this, this);
138     ErrorCode ret = pipeline_->AddFilters({audioSource_.get(), demuxer_.get()});
139     if (ret == ErrorCode::SUCCESS) {
140         ret = pipeline_->LinkFilters({audioSource_.get(), demuxer_.get()});
141     }
142     if (ret == ErrorCode::SUCCESS) {
143         fsm_.SetStateCallback(this);
144         fsm_.Start();
145         initialized_ = true;
146     } else {
147         pipeline_->UnlinkPrevFilters();
148         pipeline_->RemoveFilterChain(audioSource_.get());
149         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
150     }
151     return ret;
152 }
153 
SetSource(const std::string & uri)154 int32_t HiPlayerImpl::SetSource(const std::string& uri)
155 {
156     StartTrace(HITRACE_TAG_ZMEDIA, "Hst player SetSource");
157     MEDIA_LOG_I("SetSource entered source uri: " PUBLIC_LOG_S, uri.c_str());
158     PROFILE_BEGIN("SetSource begin");
159     auto ret = Init();
160     if (ret == ErrorCode::SUCCESS) {
161         ret = fsm_.SendEvent(Intent::SET_SOURCE, std::make_shared<MediaSource>(uri));
162     }
163     if (ret != ErrorCode::SUCCESS) {
164         MEDIA_LOG_E("SetSource error: " PUBLIC_LOG_S, GetErrorName(ret));
165     }
166     PROFILE_END("SetSource end.");
167     FinishTrace(HITRACE_TAG_ZMEDIA);
168     return TransErrorCode(ret);
169 }
170 
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)171 int32_t HiPlayerImpl::SetSource(const std::shared_ptr<IMediaDataSource>& dataSrc)
172 {
173     MEDIA_LOG_I("SetSource entered source stream");
174     PROFILE_BEGIN("SetSource begin");
175     auto ret = Init();
176     if (ret == ErrorCode::SUCCESS) {
177         ret = fsm_.SendEvent(Intent::SET_SOURCE, std::make_shared<MediaSource>(dataSrc));
178     }
179     if (ret != ErrorCode::SUCCESS) {
180         MEDIA_LOG_E("SetSource error: " PUBLIC_LOG_S, GetErrorName(ret));
181     }
182     PROFILE_END("SetSource end.");
183     return TransErrorCode(ret);
184 }
185 
Prepare()186 int32_t HiPlayerImpl::Prepare()
187 {
188     StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Prepare");
189     MEDIA_LOG_I("Prepare entered, current fsm state: " PUBLIC_LOG_S ".", fsm_.GetCurrentState().c_str());
190     PROFILE_BEGIN();
191     auto ret = fsm_.SendEvent(Intent::PREPARE);
192     if (ret != ErrorCode::SUCCESS) {
193         PROFILE_END("Prepare failed,");
194         MEDIA_LOG_E("Prepare failed with error " PUBLIC_LOG_D32, ret);
195         return TransErrorCode(ret);
196     }
197     OSAL::ScopedLock lock(stateMutex_);
198     if (curFsmState_ == StateId::PREPARING) { // Wait state change to ready
199         cond_.Wait(lock, [this] { return curFsmState_ != StateId::PREPARING; });
200     }
201     MEDIA_LOG_D("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
202     PROFILE_END("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
203     if (curFsmState_ == StateId::READY) {
204         return TransErrorCode(ErrorCode::SUCCESS);
205     }
206     FinishTrace(HITRACE_TAG_ZMEDIA);
207     return TransErrorCode(ErrorCode::ERROR_UNKNOWN);
208 }
209 
PrepareAsync()210 int HiPlayerImpl::PrepareAsync()
211 {
212     StartAsyncTrace(HITRACE_TAG_ZMEDIA, "Hst player PrepareAsync", 1);
213     MEDIA_LOG_I("Prepare async entered, current fsm state: " PUBLIC_LOG_S, fsm_.GetCurrentState().c_str());
214     PROFILE_BEGIN();
215     auto ret = fsm_.SendEventAsync(Intent::PREPARE);
216     if (ret != ErrorCode::SUCCESS) {
217         PROFILE_END("Prepare async failed,");
218         MEDIA_LOG_E("Prepare async failed with error " PUBLIC_LOG_D32, ret);
219     } else {
220         PROFILE_END("Prepare async successfully,");
221     }
222     FinishAsyncTrace(HITRACE_TAG_ZMEDIA, "Hst player PrepareAsync", 1);
223     return TransErrorCode(ret);
224 }
225 
Play()226 int32_t HiPlayerImpl::Play()
227 {
228     StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Play");
229     MEDIA_LOG_I("Play entered.");
230     callbackLooper_.StartReportMediaProgress();
231     PROFILE_BEGIN();
232     seekInProgress_.store(false);
233     ErrorCode ret;
234     if (pipelineStates_ == PlayerStates::PLAYER_PAUSED) {
235         ret = fsm_.SendEvent(Intent::RESUME);
236     } else {
237         ret = fsm_.SendEvent(Intent::PLAY);
238     }
239     PROFILE_END("Play ret = " PUBLIC_LOG_D32, TransErrorCode(ret));
240     FinishTrace(HITRACE_TAG_ZMEDIA);
241     return TransErrorCode(ret);
242 }
243 
Pause()244 int32_t HiPlayerImpl::Pause()
245 {
246     StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Pause");
247     MEDIA_LOG_I("Pause entered.");
248     PROFILE_BEGIN();
249     auto ret = TransErrorCode(fsm_.SendEvent(Intent::PAUSE));
250     callbackLooper_.StopReportMediaProgress();
251     callbackLooper_.ManualReportMediaProgressOnce();
252     PROFILE_END("Pause ret = " PUBLIC_LOG_D32, ret);
253     FinishTrace(HITRACE_TAG_ZMEDIA);
254     return ret;
255 }
256 
Stop()257 int32_t HiPlayerImpl::Stop()
258 {
259     StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Stop");
260     MEDIA_LOG_I("Stop entered.");
261     PROFILE_BEGIN();
262     auto ret = TransErrorCode(fsm_.SendEvent(Intent::STOP));
263     callbackLooper_.StopReportMediaProgress();
264     callbackLooper_.ManualReportMediaProgressOnce();
265     PROFILE_END("Stop ret = " PUBLIC_LOG_D32, ret);
266     FinishTrace(HITRACE_TAG_ZMEDIA);
267     return ret;
268 }
269 
StopAsync()270 ErrorCode HiPlayerImpl::StopAsync()
271 {
272     MEDIA_LOG_I("StopAsync entered.");
273     return fsm_.SendEventAsync(Intent::STOP);
274 }
275 
Seek(int32_t mSeconds,PlayerSeekMode mode)276 int32_t HiPlayerImpl::Seek(int32_t mSeconds, PlayerSeekMode mode)
277 {
278     StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Seek");
279     MEDIA_LOG_I("Seek entered. mSeconds : " PUBLIC_LOG_D32 ", seekMode : " PUBLIC_LOG_D32,
280                 mSeconds, static_cast<int32_t>(mode));
281     int64_t hstTime = 0;
282     int32_t durationMs = 0;
283     NZERO_RETURN(GetDuration(durationMs));
284     MEDIA_LOG_D("Seek durationMs : " PUBLIC_LOG_D32, durationMs);
285     if (mSeconds >= durationMs) { // if exceeds change to duration
286         mSeconds = durationMs;
287     }
288     if (audioSource_->GetSeekable() != Plugin::Seekable::SEEKABLE) {
289         MEDIA_LOG_E("Seek, invalid operation, audio source is unseekable or invalid");
290         return MSERR_INVALID_OPERATION;
291     }
292     if (!Plugin::Ms2HstTime(mSeconds, hstTime)) {
293         return TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
294     }
295     auto smode = Transform2SeekMode(mode);
296     lastSeekPosition_.store(hstTime);
297     lastSeekMode_.store(smode);
298     if (!seekInProgress_.load()) {
299         seekInProgress_.store(true);
300         auto ret = fsm_.SendEvent(Intent::SEEK, SeekInfo{hstTime, smode});
301         if (ret != ErrorCode::SUCCESS) {
302             seekInProgress_.store(false);
303         }
304         FinishTrace(HITRACE_TAG_ZMEDIA);
305         return TransErrorCode(ret);
306     } else {
307         MEDIA_LOG_D("Seek in progress. Record the seek request [" PUBLIC_LOG_D64 "," PUBLIC_LOG_D32 "]",
308                     hstTime, static_cast<int32_t>(smode));
309         FinishTrace(HITRACE_TAG_ZMEDIA);
310         return MSERR_OK;
311     }
312 }
313 
SetVolume(float leftVolume,float rightVolume)314 int32_t HiPlayerImpl::SetVolume(float leftVolume, float rightVolume)
315 {
316     MEDIA_LOG_I("SetVolume entered.");
317     if (leftVolume < 0 || leftVolume > MAX_MEDIA_VOLUME || rightVolume < 0 || rightVolume > MAX_MEDIA_VOLUME) {
318         MEDIA_LOG_E("volume not valid, should be in range [0,100]");
319         return TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
320     }
321     float volume = 0.0f;
322     if (leftVolume < 1e-6 && rightVolume >= 1e-6) {  // 1e-6
323         volume = rightVolume;
324     } else if (rightVolume < 1e-6 && leftVolume >= 1e-6) {  // 1e-6
325         volume = leftVolume;
326     } else {
327         volume = (leftVolume + rightVolume) / 2;  // 2
328     }
329     volume /= MAX_MEDIA_VOLUME;  // normalize to 0~1
330     if (pipelineStates_ == PlayerStates::PLAYER_STOPPED) {
331         return TransErrorCode(ErrorCode::ERROR_INVALID_OPERATION);
332     }
333     volume_ = volume;
334     if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_INITIALIZED ||
335         pipelineStates_ == PlayerStates::PLAYER_PREPARING || audioSink_ == nullptr) {
336         MEDIA_LOG_W("cannot set volume, will do this onReady");
337         return TransErrorCode(ErrorCode::SUCCESS);
338     }
339     return TransErrorCode(SetVolumeToSink(volume));
340 }
341 
SetVideoSurface(sptr<Surface> surface)342 int32_t HiPlayerImpl::SetVideoSurface(sptr<Surface> surface)
343 {
344     MEDIA_LOG_D("SetVideoSurface entered.");
345 #ifdef VIDEO_SUPPORT
346     if (surface != nullptr) {
347         surface_ = surface;
348     }
349     return TransErrorCode(videoSink_->SetVideoSurface(surface_));
350 #else
351     return TransErrorCode(ErrorCode::SUCCESS);
352 #endif
353 }
354 
GetVideoTrackInfo(std::vector<Format> & videoTrack)355 int32_t HiPlayerImpl::GetVideoTrackInfo(std::vector<Format>& videoTrack)
356 {
357     MEDIA_LOG_I("GetVideoTrackInfo entered.");
358     std::string mime;
359     std::vector<std::shared_ptr<Plugin::Meta>> metaInfo = demuxer_->GetStreamMetaInfo();
360     for (const auto& trackInfo : metaInfo) {
361         if (trackInfo->GetString(Plugin::MetaID::MIME, mime)) {
362             if (IsVideoMime(mime)) {
363                 int64_t bitRate;
364                 uint32_t frameRate;
365                 uint32_t height;
366                 uint32_t width;
367                 uint32_t trackIndex;
368                 Format videoTrackInfo {};
369                 (void)videoTrackInfo.PutStringValue("codec_mime", mime);
370                 (void)videoTrackInfo.PutIntValue("track_type", MediaType::MEDIA_TYPE_VID);
371                 if (trackInfo->GetUint32(Plugin::MetaID::TRACK_ID, trackIndex)) {
372                     (void)videoTrackInfo.PutIntValue("track_index", static_cast<int32_t>(trackIndex));
373                 }
374                 if (trackInfo->GetInt64(Plugin::MetaID::MEDIA_BITRATE, bitRate)) {
375                     (void)videoTrackInfo.PutIntValue("bitrate", static_cast<int32_t>(bitRate));
376                 }
377                 if (trackInfo->GetUint32(Plugin::MetaID::VIDEO_FRAME_RATE, frameRate)) {
378                     (void)videoTrackInfo.PutIntValue("frame_rate", static_cast<int32_t>(frameRate));
379                 }
380                 if (trackInfo->GetUint32(Plugin::MetaID::VIDEO_HEIGHT, height)) {
381                     (void)videoTrackInfo.PutIntValue("height", static_cast<int32_t>(height));
382                 }
383                 if (trackInfo->GetUint32(Plugin::MetaID::VIDEO_WIDTH, width)) {
384                     (void)videoTrackInfo.PutIntValue("width", static_cast<int32_t>(width));
385                 }
386                 videoTrack.push_back(videoTrackInfo);
387             }
388         }
389     }
390     return TransErrorCode(ErrorCode::SUCCESS);
391 }
392 
GetAudioTrackInfo(std::vector<Format> & audioTrack)393 int32_t HiPlayerImpl::GetAudioTrackInfo(std::vector<Format>& audioTrack)
394 {
395     MEDIA_LOG_I("GetAudioTrackInfo entered.");
396     std::string mime;
397     std::vector<std::shared_ptr<Plugin::Meta>> metaInfo = demuxer_->GetStreamMetaInfo();
398     for (const auto& trackInfo : metaInfo) {
399         if (trackInfo->GetString(Plugin::MetaID::MIME, mime)) {
400             if (IsAudioMime(mime)) {
401                 int64_t bitRate;
402                 uint32_t audioChannels;
403                 uint32_t audioSampleRate;
404                 uint32_t trackIndex;
405                 Format audioTrackInfo {};
406                 (void)audioTrackInfo.PutStringValue("codec_mime", mime);
407                 (void)audioTrackInfo.PutIntValue("track_type", MediaType::MEDIA_TYPE_AUD);
408                 if (trackInfo->GetUint32(Plugin::MetaID::TRACK_ID, trackIndex)) {
409                     (void)audioTrackInfo.PutIntValue("track_index", static_cast<int32_t>(trackIndex));
410                 }
411                 if (trackInfo->GetInt64(Plugin::MetaID::MEDIA_BITRATE, bitRate)) {
412                     (void)audioTrackInfo.PutIntValue("bitrate", static_cast<int32_t>(bitRate));
413                 }
414                 if (trackInfo->GetUint32(Plugin::MetaID::AUDIO_CHANNELS, audioChannels)) {
415                     (void)audioTrackInfo.PutIntValue("channel_count", static_cast<int32_t>(audioChannels));
416                 }
417                 if (trackInfo->GetUint32(Plugin::MetaID::AUDIO_SAMPLE_RATE, audioSampleRate)) {
418                     (void)audioTrackInfo.PutIntValue("sample_rate", static_cast<int32_t>(audioSampleRate));
419                 }
420                 audioTrack.push_back(audioTrackInfo);
421             }
422         }
423     }
424     return TransErrorCode(ErrorCode::SUCCESS);
425 }
426 
GetVideoWidth()427 int32_t HiPlayerImpl::GetVideoWidth()
428 {
429     MEDIA_LOG_I("GetVideoWidth entered.");
430     if (surface_ != nullptr) {
431         return surface_->GetDefaultWidth();
432     }
433     return 0;
434 }
435 
GetVideoHeight()436 int32_t HiPlayerImpl::GetVideoHeight()
437 {
438     MEDIA_LOG_I("GetVideoHeight entered.");
439     if (surface_ != nullptr) {
440         return surface_->GetDefaultHeight();
441     }
442     return 0;
443 }
444 
HandlePluginErrorEvent(const Event & event)445 void HiPlayerImpl::HandlePluginErrorEvent(const Event& event)
446 {
447     Plugin::PluginEvent pluginEvent = Plugin::AnyCast<Plugin::PluginEvent>(event.param);
448     MEDIA_LOG_I("Receive PLUGIN_ERROR, type:  " PUBLIC_LOG_D32, CppExt::to_underlying(pluginEvent.type));
449     if (pluginEvent.type == Plugin::PluginEventType::CLIENT_ERROR &&
450         pluginEvent.param.SameTypeWith(typeid(Plugin::NetworkClientErrorCode))) {
451         auto netClientErrorCode = Plugin::AnyCast<Plugin::NetworkClientErrorCode>(pluginEvent.param);
452         auto errorType {PlayerErrorType::PLAYER_ERROR_UNKNOWN};
453         auto serviceErrCode { MSERR_UNKNOWN };
454         if (netClientErrorCode == Plugin::NetworkClientErrorCode::ERROR_TIME_OUT) {
455             errorType = PlayerErrorType::PLAYER_ERROR;
456             serviceErrCode = MSERR_NETWORK_TIMEOUT;
457         }
458         callbackLooper_.OnError(errorType, serviceErrCode);
459     }
460 }
461 
OnEvent(const Event & event)462 void HiPlayerImpl::OnEvent(const Event& event)
463 {
464     if (event.type != EventType::EVENT_AUDIO_PROGRESS) {
465         MEDIA_LOG_I("[HiStreamer] OnEvent (" PUBLIC_LOG_S ")", GetEventName(event.type));
466     }
467     switch (event.type) {
468         case EventType::EVENT_ERROR: {
469             fsm_.SendEventAsync(Intent::NOTIFY_ERROR, event.param);
470             break;
471         }
472         case EventType::EVENT_READY:
473             fsm_.SendEventAsync(Intent::NOTIFY_READY);
474             break;
475         case EventType::EVENT_COMPLETE:
476             mediaStats_.ReceiveEvent(event);
477             if (mediaStats_.IsEventCompleteAllReceived()) {
478                 fsm_.SendEventAsync(Intent::NOTIFY_COMPLETE);
479             }
480             break;
481         case EventType::EVENT_PLUGIN_ERROR: {
482             HandlePluginErrorEvent(event);
483             break;
484         }
485         case EventType::EVENT_PLUGIN_EVENT: {
486             auto pluginEvent = Plugin::AnyCast<Plugin::PluginEvent>(event.param);
487             switch (pluginEvent.type) {
488                 case Plugin::PluginEventType::INTERRUPT: {
489                     auto interruptEvent = Plugin::AnyCast<Plugin::AudioInterruptEvent>(pluginEvent.param);
490                     Format format;
491                     (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, interruptEvent.eventType);
492                     (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, interruptEvent.forceType);
493                     (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, interruptEvent.hintType);
494                     callbackLooper_.OnInfo(INFO_TYPE_INTERRUPT_EVENT, 0, format);
495                     MEDIA_LOG_I("Receive Audio INTERRUPT EVENT");
496                     break;
497                 }
498                 case Plugin::PluginEventType::BELOW_LOW_WATERLINE:
499                 case Plugin::PluginEventType::ABOVE_LOW_WATERLINE:
500                 default:
501                     MEDIA_LOG_I("Receive PLUGIN_EVENT, type:  " PUBLIC_LOG_D32,
502                                 CppExt::to_underlying(pluginEvent.type));
503                     break;
504             }
505             break;
506         }
507         default:
508             MEDIA_LOG_E("Unknown event(" PUBLIC_LOG_U32 ")", event.type);
509     }
510 }
511 
DoSetSource(const std::shared_ptr<MediaSource> & source)512 ErrorCode HiPlayerImpl::DoSetSource(const std::shared_ptr<MediaSource>& source)
513 {
514     auto ret = audioSource_->SetSource(source);
515     if (ret != ErrorCode::SUCCESS) {
516         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
517     }
518     return ret;
519 }
520 
PrepareFilters()521 ErrorCode HiPlayerImpl::PrepareFilters()
522 {
523     auto ret = pipeline_->Prepare();
524     if (ret != ErrorCode::SUCCESS) {
525         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
526     }
527     return ret;
528 }
529 
DoPlay()530 ErrorCode HiPlayerImpl::DoPlay()
531 {
532     syncManager_->Resume();
533     auto ret = pipeline_->Start();
534     if (ret != ErrorCode::SUCCESS) {
535         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
536     }
537     return ret;
538 }
539 
DoPause()540 ErrorCode HiPlayerImpl::DoPause()
541 {
542     auto ret = pipeline_->Pause();
543     syncManager_->Pause();
544     if (ret != ErrorCode::SUCCESS) {
545         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
546     }
547     return ret;
548 }
549 
DoResume()550 ErrorCode HiPlayerImpl::DoResume()
551 {
552     syncManager_->Resume();
553     auto ret = pipeline_->Resume();
554     if (ret != ErrorCode::SUCCESS) {
555         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
556     }
557     return ret;
558 }
559 
DoStop()560 ErrorCode HiPlayerImpl::DoStop()
561 {
562     mediaStats_.Reset();
563     auto ret = pipeline_->Stop();
564     syncManager_->Reset();
565     if (ret != ErrorCode::SUCCESS) {
566         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
567     }
568     return ret;
569 }
570 
DoReset()571 ErrorCode HiPlayerImpl::DoReset()
572 {
573     return DoStop();
574 }
575 
DoSeek(int64_t hstTime,Plugin::SeekMode mode,bool appTriggered)576 ErrorCode HiPlayerImpl::DoSeek(int64_t hstTime, Plugin::SeekMode mode, bool appTriggered)
577 {
578     if (appTriggered) {
579         fsm_.Notify(Intent::SEEK, ErrorCode::SUCCESS);
580     }
581     PROFILE_BEGIN();
582     int64_t seekPos = hstTime;
583     Plugin::SeekMode seekMode = mode;
584     if (appTriggered && (hstTime != lastSeekPosition_.load() || mode != lastSeekMode_.load())) { // Newer seek happened
585         seekPos = lastSeekPosition_.load();
586         seekMode = lastSeekMode_.load();
587     }
588     auto rtv = seekPos >= 0 ? ErrorCode::SUCCESS : ErrorCode::ERROR_INVALID_OPERATION;
589     if (rtv == ErrorCode::SUCCESS) {
590         pipeline_->FlushStart();
591         PROFILE_END("Flush start");
592         PROFILE_RESET();
593 
594         MEDIA_LOG_I("Do seek ...");
595         syncManager_->Seek(seekPos);
596         rtv = demuxer_->SeekTo(seekPos, seekMode);
597         PROFILE_END("SeekTo");
598 
599         pipeline_->FlushEnd();
600         PROFILE_END("Flush end");
601         PROFILE_RESET();
602     }
603     if (rtv != ErrorCode::SUCCESS) {
604         callbackLooper_.OnError(PLAYER_ERROR, MSERR_SEEK_FAILED);
605     } else {
606         Format format;
607         int64_t currentPos = Plugin::HstTime2Ms(seekPos);
608         MEDIA_LOG_I("Seek done, currentPos : " PUBLIC_LOG_D64 ", appTriggered: " PUBLIC_LOG_D32,
609                     currentPos, appTriggered);
610         callbackLooper_.OnInfo(INFO_TYPE_SEEKDONE, static_cast<int32_t>(currentPos), format);
611     }
612     if (appTriggered && seekInProgress_.load()) {
613         OSAL::SleepFor(10); // 10 wait seek real complete
614         seekInProgress_.store(false);
615     }
616     if (appTriggered) {
617         return ErrorCode::ERROR_NO_NOTIFY;
618     }
619     return rtv;
620 }
621 
DoOnReady()622 ErrorCode HiPlayerImpl::DoOnReady()
623 {
624     SetVolumeToSink(volume_, false); // do not report
625     auto tmpMeta = demuxer_->GetGlobalMetaInfo();
626     sourceMeta_ = tmpMeta;
627     int64_t duration = 0;
628     bool found = false;
629     if (tmpMeta->GetInt64(Media::Plugin::MetaID::MEDIA_DURATION, duration)) {
630         found = true;
631     }
632     streamMeta_.clear();
633     int64_t tmp = 0;
634     for (auto& streamMeta : demuxer_->GetStreamMetaInfo()) {
635         streamMeta_.push_back(streamMeta);
636         if (streamMeta->GetInt64(Media::Plugin::MetaID::MEDIA_DURATION, tmp)) {
637             duration = std::max(duration, tmp);
638             found = true;
639         }
640     }
641     if (found) {
642         duration_ = duration;
643     }
644     return ErrorCode::SUCCESS;
645 }
646 
DoOnComplete()647 ErrorCode HiPlayerImpl::DoOnComplete()
648 {
649     MEDIA_LOG_I("OnComplete looping: " PUBLIC_LOG_D32 ".", singleLoop_.load());
650     Format format;
651     callbackLooper_.OnInfo(INFO_TYPE_EOS, static_cast<int32_t>(singleLoop_.load()), format);
652     if (!singleLoop_.load()) {
653         callbackLooper_.StopReportMediaProgress();
654         callbackLooper_.ManualReportMediaProgressOnce();
655     }
656     return ErrorCode::SUCCESS;
657 }
658 
DoOnError(ErrorCode errorCode)659 ErrorCode HiPlayerImpl::DoOnError(ErrorCode errorCode)
660 {
661     UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
662     callbackLooper_.OnError(PLAYER_ERROR, TransErrorCode(errorCode));
663     return ErrorCode::SUCCESS;
664 }
665 
SetVolumeToSink(float volume,bool reportUpward)666 ErrorCode HiPlayerImpl::SetVolumeToSink(float volume, bool reportUpward)
667 {
668     MEDIA_LOG_I("SetVolumeToSink entered.");
669     ErrorCode ret = ErrorCode::SUCCESS;
670     if (volume_ > 0) {
671         MEDIA_LOG_I("set volume " PUBLIC_LOG_F, volume);
672         ret = audioSink_->SetVolume(volume);
673     }
674 
675     if (ret != ErrorCode::SUCCESS) {
676         MEDIA_LOG_E("SetVolume failed with error " PUBLIC_LOG_D32, static_cast<int>(ret));
677         callbackLooper_.OnError(PLAYER_ERROR, TransErrorCode(ret));
678     } else if (reportUpward) {
679         Format format;
680         callbackLooper_.OnInfo(INFO_TYPE_VOLUME_CHANGE, volume, format);
681     }
682     return ret;
683 }
684 
CreateAudioDecoder(const std::string & desc)685 PFilter HiPlayerImpl::CreateAudioDecoder(const std::string& desc)
686 {
687     if (!audioDecoderMap_[desc]) {
688         audioDecoderMap_[desc] = FilterFactory::Instance().CreateFilterWithType<AudioDecoderFilter>(
689             "builtin.player.audiodecoder", "audiodecoder-" + desc);
690         // set parameters to decoder.
691     }
692     return audioDecoderMap_[desc];
693 }
694 
SetLooping(bool loop)695 int32_t HiPlayerImpl::SetLooping(bool loop)
696 {
697     MEDIA_LOG_I("SetLooping entered, loop: " PUBLIC_LOG_D32, loop);
698     singleLoop_ = loop;
699     return TransErrorCode(ErrorCode::SUCCESS);
700 }
701 
IsSingleLoop()702 bool HiPlayerImpl::IsSingleLoop()
703 {
704     // note that we should also consider the live source, which cannot be singleLoop!
705     return singleLoop_;
706 }
707 
SetParameter(const Format & params)708 int32_t HiPlayerImpl::SetParameter(const Format& params)
709 {
710     MEDIA_LOG_I("SetParameter entered.");
711     if (params.ContainKey(PlayerKeys::VIDEO_SCALE_TYPE)) {
712         int32_t videoScaleType = 0;
713         params.GetIntValue(PlayerKeys::VIDEO_SCALE_TYPE, videoScaleType);
714         return SetVideoScaleType(VideoScaleType(videoScaleType));
715     }
716     if (params.ContainKey(PlayerKeys::CONTENT_TYPE) && params.ContainKey(PlayerKeys::STREAM_USAGE)) {
717         int32_t contentType;
718         int32_t streamUsage;
719         int32_t rendererFlag;
720         params.GetIntValue(PlayerKeys::CONTENT_TYPE, contentType);
721         params.GetIntValue(PlayerKeys::STREAM_USAGE, streamUsage);
722         params.GetIntValue(PlayerKeys::RENDERER_FLAG, rendererFlag);
723         return SetAudioRendererInfo(contentType, streamUsage, rendererFlag);
724     }
725     if (params.ContainKey(PlayerKeys::AUDIO_INTERRUPT_MODE)) {
726         int32_t interruptMode = 0;
727         params.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_MODE, interruptMode);
728         return SetAudioInterruptMode(interruptMode);
729     }
730     return TransErrorCode(ErrorCode::ERROR_UNIMPLEMENTED);
731 }
732 
SetObs(const std::weak_ptr<IPlayerEngineObs> & obs)733 int32_t HiPlayerImpl::SetObs(const std::weak_ptr<IPlayerEngineObs>& obs)
734 {
735     MEDIA_LOG_I("SetObs entered.");
736     callbackLooper_.StartWithPlayerEngineObs(obs);
737     return TransErrorCode(ErrorCode::SUCCESS);
738 }
739 
Reset()740 int32_t HiPlayerImpl::Reset()
741 {
742     MEDIA_LOG_I("Reset entered.");
743     singleLoop_ = false;
744     mediaStats_.Reset();
745     return TransErrorCode(fsm_.SendEvent(Intent::RESET));
746 }
747 
GetCurrentTime(int32_t & currentPositionMs)748 int32_t HiPlayerImpl::GetCurrentTime(int32_t& currentPositionMs)
749 {
750     currentPositionMs = Plugin::HstTime2Ms(syncManager_->GetMediaTimeNow());
751     return TransErrorCode(ErrorCode::SUCCESS);
752 }
753 
GetDuration(int32_t & durationMs)754 int32_t HiPlayerImpl::GetDuration(int32_t& durationMs)
755 {
756     durationMs = 0;
757     if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_PREPARING ||
758         audioSource_ == nullptr) {
759         MEDIA_LOG_E("GetDuration, invalid state or audioSource_ is null. state: " PUBLIC_LOG_S,
760                     StringnessPlayerState(pipelineStates_).c_str());
761         return MSERR_INVALID_STATE;
762     }
763     if (duration_ < 0) {
764         durationMs = -1;
765         MEDIA_LOG_W("no valid duration");
766         return MSERR_UNKNOWN;
767     }
768     durationMs = Plugin::HstTime2Ms(duration_);
769     MEDIA_LOG_DD("GetDuration returned " PUBLIC_LOG_D32, durationMs);
770     return MSERR_OK;
771 }
772 
SetPlaybackSpeed(PlaybackRateMode mode)773 int32_t HiPlayerImpl::SetPlaybackSpeed(PlaybackRateMode mode)
774 {
775     MEDIA_LOG_I("SetPlaybackSpeed entered.");
776     double playbackSpeed = ChangeModeToSpeed(mode);
777     demuxer_->SetParameter(static_cast<int32_t>(Plugin::Tag::MEDIA_PLAYBACK_SPEED), playbackSpeed);
778     return MSERR_OK;
779 }
GetPlaybackSpeed(PlaybackRateMode & mode)780 int32_t HiPlayerImpl::GetPlaybackSpeed(PlaybackRateMode& mode)
781 {
782     MEDIA_LOG_I("GetPlaybackSpeed entered.");
783     Plugin::Any any;
784     demuxer_->GetParameter(static_cast<int32_t>(Plugin::Tag::MEDIA_PLAYBACK_SPEED), any);
785     auto playbackSpeed = Plugin::AnyCast<double>(any);
786     mode = ChangeSpeedToMode(playbackSpeed);
787     return MSERR_OK;
788 }
789 
OnStateChanged(StateId state)790 void HiPlayerImpl::OnStateChanged(StateId state)
791 {
792     MEDIA_LOG_I("OnStateChanged from " PUBLIC_LOG_D32 " to " PUBLIC_LOG_D32, curFsmState_.load(), state);
793     UpdateStateNoLock(TransStateId2PlayerState(state));
794     {
795         OSAL::ScopedLock lock(stateMutex_);
796         curFsmState_ = state;
797         cond_.NotifyOne();
798     }
799 }
800 
OnCallback(const FilterCallbackType & type,Filter * filter,const Plugin::Any & parameter)801 ErrorCode HiPlayerImpl::OnCallback(const FilterCallbackType& type, Filter* filter, const Plugin::Any& parameter)
802 {
803     ErrorCode ret = ErrorCode::SUCCESS;
804     switch (type) {
805         case FilterCallbackType::PORT_ADDED:
806             ret = NewAudioPortFound(filter, parameter);
807 #ifdef VIDEO_SUPPORT
808             ret = NewVideoPortFound(filter, parameter);
809 #endif
810             break;
811         case FilterCallbackType::PORT_REMOVE:
812             ret = RemoveFilterChains(filter, parameter);
813             break;
814         default:
815             break;
816     }
817     return ret;
818 }
819 
NewAudioPortFound(Filter * filter,const Plugin::Any & parameter)820 ErrorCode HiPlayerImpl::NewAudioPortFound(Filter* filter, const Plugin::Any& parameter)
821 {
822     if (!parameter.SameTypeWith(typeid(PortInfo))) {
823         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
824     }
825     ErrorCode rtv = ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
826     auto param = Plugin::AnyCast<PortInfo>(parameter);
827     if (filter == demuxer_.get() && param.type == PortType::OUT) {
828         MEDIA_LOG_I("new port found on demuxer " PUBLIC_LOG_ZU, param.ports.size());
829         for (const auto& portDesc : param.ports) {
830             if (portDesc.name.compare(0, 5, "audio") != 0) { // 5 is length of "audio"
831                 continue;
832             }
833             MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
834             auto fromPort = filter->GetOutPort(portDesc.name);
835             if (portDesc.isPcm) {
836                 pipeline_->AddFilters({audioSink_.get()});
837                 FAIL_LOG(pipeline_->LinkPorts(fromPort, audioSink_->GetInPort(PORT_NAME_DEFAULT)));
838                 ActiveFilters({audioSink_.get()});
839             } else {
840                 auto newAudioDecoder = CreateAudioDecoder(portDesc.name);
841                 pipeline_->AddFilters({newAudioDecoder.get(), audioSink_.get()});
842                 FAIL_LOG(pipeline_->LinkPorts(fromPort, newAudioDecoder->GetInPort(PORT_NAME_DEFAULT)));
843                 FAIL_LOG(pipeline_->LinkPorts(newAudioDecoder->GetOutPort(PORT_NAME_DEFAULT),
844                                               audioSink_->GetInPort(PORT_NAME_DEFAULT)));
845                 ActiveFilters({newAudioDecoder.get(), audioSink_.get()});
846             }
847             mediaStats_.Append(audioSink_->GetName());
848             rtv = ErrorCode::SUCCESS;
849             break;
850         }
851     }
852     return rtv;
853 }
854 
855 #ifdef VIDEO_SUPPORT
NewVideoPortFound(Filter * filter,const Plugin::Any & parameter)856 ErrorCode HiPlayerImpl::NewVideoPortFound(Filter* filter, const Plugin::Any& parameter)
857 {
858     if (!parameter.SameTypeWith(typeid(PortInfo))) {
859         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
860     }
861     auto param = Plugin::AnyCast<PortInfo>(parameter);
862     if (filter != demuxer_.get() || param.type != PortType::OUT) {
863         return ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
864     }
865     std::vector<Filter*> newFilters;
866     for (const auto& portDesc : param.ports) {
867         if (portDesc.name.compare(0, 5, "video") == 0) { // 5 is length of "video"
868             MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
869             videoDecoder_ = FilterFactory::Instance().CreateFilterWithType<VideoDecoderFilter>(
870                 "builtin.player.videodecoder", "videodecoder-" + portDesc.name);
871             if (pipeline_->AddFilters({videoDecoder_.get()}) == ErrorCode::SUCCESS) {
872                 // link demuxer and video decoder
873                 auto fromPort = filter->GetOutPort(portDesc.name);
874                 auto toPort = videoDecoder_->GetInPort(PORT_NAME_DEFAULT);
875                 FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort));  // link ports
876                 newFilters.emplace_back(videoDecoder_.get());
877 
878                 // link video decoder and video sink
879                 if (pipeline_->AddFilters({videoSink_.get()}) == ErrorCode::SUCCESS) {
880                     fromPort = videoDecoder_->GetOutPort(PORT_NAME_DEFAULT);
881                     toPort = videoSink_->GetInPort(PORT_NAME_DEFAULT);
882                     FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort));  // link ports
883                     newFilters.push_back(videoSink_.get());
884                     mediaStats_.Append(videoSink_->GetName());
885                 }
886             }
887             break;
888         }
889     }
890     if (!newFilters.empty()) {
891         ActiveFilters(newFilters);
892     }
893     return ErrorCode::SUCCESS;
894 }
895 #endif
896 
RemoveFilterChains(Filter * filter,const Plugin::Any & parameter)897 ErrorCode HiPlayerImpl::RemoveFilterChains(Filter* filter, const Plugin::Any& parameter)
898 {
899     ErrorCode ret = ErrorCode::SUCCESS;
900     auto param = Plugin::AnyCast<PortInfo>(parameter);
901     if (filter != demuxer_.get() || param.type != PortType::OUT) {
902         return ret;
903     }
904     for (const auto& portDesc : param.ports) {
905         MEDIA_LOG_I("remove filter chain for port: " PUBLIC_LOG_S, portDesc.name.c_str());
906         auto peerPort = filter->GetOutPort(portDesc.name)->GetPeerPort();
907         if (peerPort) {
908             auto nextFilter = const_cast<Filter*>(dynamic_cast<const Filter*>(peerPort->GetOwnerFilter()));
909             if (nextFilter) {
910                 pipeline_->RemoveFilterChain(nextFilter);
911             }
912         }
913     }
914     return ret;
915 }
916 
ActiveFilters(const std::vector<Filter * > & filters)917 void HiPlayerImpl::ActiveFilters(const std::vector<Filter*>& filters)
918 {
919     for (auto it = filters.rbegin(); it != filters.rend(); ++it) {
920         (*it)->Prepare();
921     }
922 }
923 
ChangeModeToSpeed(const PlaybackRateMode & mode) const924 double HiPlayerImpl::ChangeModeToSpeed(const PlaybackRateMode& mode) const
925 {
926     switch (mode) {
927         case SPEED_FORWARD_0_75_X:
928             return SPEED_0_75_X;
929         case SPEED_FORWARD_1_00_X:
930             return SPEED_1_00_X;
931         case SPEED_FORWARD_1_25_X:
932             return SPEED_1_25_X;
933         case SPEED_FORWARD_1_75_X:
934             return SPEED_1_75_X;
935         case SPEED_FORWARD_2_00_X:
936             return SPEED_2_00_X;
937         default:
938             MEDIA_LOG_I("unknown mode:" PUBLIC_LOG_D32 ", return default speed(SPEED_1_00_X)", mode);
939     }
940     return SPEED_1_00_X;
941 }
942 
ChangeSpeedToMode(double rate) const943 PlaybackRateMode HiPlayerImpl::ChangeSpeedToMode(double rate) const
944 {
945     if (abs(rate - SPEED_0_75_X) < EPSINON) {
946         return SPEED_FORWARD_0_75_X;
947     }
948     if (abs(rate - SPEED_1_00_X) < EPSINON) {
949         return SPEED_FORWARD_1_00_X;
950     }
951     if (abs(rate - SPEED_1_25_X) < EPSINON) {
952         return SPEED_FORWARD_1_25_X;
953     }
954     if (abs(rate - SPEED_1_75_X) < EPSINON) {
955         return SPEED_FORWARD_1_75_X;
956     }
957     if (abs(rate - SPEED_2_00_X) < EPSINON) {
958         return SPEED_FORWARD_2_00_X;
959     }
960     MEDIA_LOG_I("unknown rate:" PUBLIC_LOG_F ", return default speed(SPEED_FORWARD_1_00_X)", rate);
961     return SPEED_FORWARD_1_00_X;
962 }
963 
SetVideoScaleType(VideoScaleType videoScaleType)964 int32_t HiPlayerImpl::SetVideoScaleType(VideoScaleType videoScaleType)
965 {
966     return TransErrorCode(ErrorCode::ERROR_UNIMPLEMENTED);
967 }
968 
SetAudioRendererInfo(const int32_t contentType,const int32_t streamUsage,const int32_t rendererFlag)969 int32_t HiPlayerImpl::SetAudioRendererInfo(const int32_t contentType, const int32_t streamUsage,
970                                            const int32_t rendererFlag)
971 {
972     MEDIA_LOG_I("SetAudioRendererInfo entered.");
973     Plugin::AudioRenderInfo audioRenderInfo {contentType, streamUsage, rendererFlag};
974     auto ret = audioSink_->SetParameter(static_cast<int32_t>(Tag::AUDIO_RENDER_INFO), audioRenderInfo);
975     return TransErrorCode(ret);
976 }
977 
SetAudioInterruptMode(const int32_t interruptMode)978 int32_t HiPlayerImpl::SetAudioInterruptMode(const int32_t interruptMode)
979 {
980     MEDIA_LOG_I("SetAudioInterruptMode entered.");
981     auto ret = audioSink_->SetParameter(static_cast<int32_t>(Tag::AUDIO_INTERRUPT_MODE), interruptMode);
982     return TransErrorCode(ret);
983 }
984 }  // namespace Media
985 }  // namespace OHOS
986