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 "foundation/utils/steady_clock.h"
21 #include "pipeline/factory/filter_factory.h"
22 #include "plugin/common/plugin_time.h"
23 namespace {
24 const float MAX_MEDIA_VOLUME = 100.0f;
25 }
26 
27 namespace OHOS {
28 namespace Media {
29 using namespace Pipeline;
30 
HiPlayerImpl()31 HiPlayerImpl::HiPlayerImpl()
32     : fsm_(*this),
33       curFsmState_(StateId::IDLE),
34       volume_(-1.0f),
35       mediaStats_()
36 {
37     MEDIA_LOG_I("hiPlayerImpl ctor");
38     FilterFactory::Instance().Init();
39     syncManager_ = std::make_shared<MediaSyncManager>();
40 
41     audioSource_ =
42         FilterFactory::Instance().CreateFilterWithType<MediaSourceFilter>("builtin.player.mediasource", "mediaSource");
43 
44 #ifdef UNIT_TEST
45     demuxer_ = FilterFactory::Instance().CreateFilterWithType<DemuxerFilter>("builtin.player.demuxer", "demuxer");
46     audioDecoder_ = FilterFactory::Instance().CreateFilterWithType<AudioDecoderFilter>("builtin.player.audiodecoder",
47                                                                                        "audiodecoder");
48     audioSink_ =
49         FilterFactory::Instance().CreateFilterWithType<AudioSinkFilter>("builtin.player.audiosink", "audiosink");
50 #else
51     demuxer_ = FilterFactory::Instance().CreateFilterWithType<DemuxerFilter>("builtin.player.demuxer", "demuxer");
52     audioSink_ =
53         FilterFactory::Instance().CreateFilterWithType<AudioSinkFilter>("builtin.player.audiosink", "audioSink");
54 #ifdef VIDEO_SUPPORT
55     videoSink =
56         FilterFactory::Instance().CreateFilterWithType<VideoSinkFilter>("builtin.player.videosink", "videoSink");
57     FALSE_RETURN(videoSink != nullptr);
58     videoSink->SetSyncCenter(syncManager_);
59 #endif
60 #endif
61     FALSE_RETURN(audioSource_ != nullptr);
62     FALSE_RETURN(demuxer_ != nullptr);
63     FALSE_RETURN(audioSink_ != nullptr);
64     audioSink_->SetSyncCenter(syncManager_);
65     pipeline_ = std::make_shared<PipelineCore>();
66 }
67 
UpdateStateNoLock(PlayerStates newState,bool notifyUpward)68 void HiPlayerImpl::UpdateStateNoLock(PlayerStates newState, bool notifyUpward)
69 {
70     if (pipelineStates_ == newState) {
71         return;
72     }
73     pipelineStates_ = newState;
74     if (pipelineStates_ == PlayerStates::PLAYER_IDLE) {
75         MEDIA_LOG_W("do not report idle since audio player will report idle");
76         return;
77     }
78     if (notifyUpward) {
79         auto ptr = callback_.lock();
80         if (ptr != nullptr) {
81             while (!pendingStates_.empty()) {
82                 auto pendingState = pendingStates_.front();
83                 pendingStates_.pop();
84                 MEDIA_LOG_I("sending pending state change: " PUBLIC_LOG_S, StringnessPlayerState(pendingState).c_str());
85             }
86             MEDIA_LOG_I("State change to : " PUBLIC_LOG_S, StringnessPlayerState(pipelineStates_.load()).c_str());
87         }
88     }
89 }
90 
~HiPlayerImpl()91 HiPlayerImpl::~HiPlayerImpl()
92 {
93     MEDIA_LOG_D("dtor called.");
94     fsm_.SendEventAsync(Intent::STOP);
95     fsm_.Stop();
96 #ifdef VIDEO_SUPPORT
97     videoSink.reset();
98 #endif
99     audioSink_.reset();
100     syncManager_.reset();
101 }
102 
CreateHiPlayerImpl()103 std::shared_ptr<HiPlayerImpl> HiPlayerImpl::CreateHiPlayerImpl()
104 {
105     return std::shared_ptr<HiPlayerImpl>(new (std::nothrow) HiPlayerImpl());
106 }
107 
Init()108 int32_t HiPlayerImpl::Init()
109 {
110     mediaStats_.Reset();
111     if (initialized_.load()) {
112         return CppExt::to_underlying(ErrorCode::SUCCESS);
113     }
114     pipeline_->Init(this, this);
115     ErrorCode ret = pipeline_->AddFilters({audioSource_.get(), demuxer_.get()});
116     if (ret == ErrorCode::SUCCESS) {
117         ret = pipeline_->LinkFilters({audioSource_.get(), demuxer_.get()});
118     }
119     if (ret == ErrorCode::SUCCESS) {
120         fsm_.SetStateCallback(this);
121         fsm_.Start();
122         initialized_ = true;
123     } else {
124         pipeline_->RemoveFilterChain(audioSource_.get());
125         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
126     }
127     return CppExt::to_underlying(ret);
128 }
SetSource(const Source & source)129 int32_t HiPlayerImpl::SetSource(const Source& source)
130 {
131     PROFILE_BEGIN("SetSource begin");
132     auto ret = Init();
133     if (ret == CppExt::to_underlying(ErrorCode::SUCCESS)) {
134         std::shared_ptr<MediaSource> mediaSource = std::make_shared<MediaSource>(source.GetSourceUri());
135         if (source.GetSourceType() == OHOS::Media::SourceType::SOURCE_TYPE_STREAM) {
136             mediaSource = std::make_shared<MediaSource>(source.GetDataConsumer());
137         }
138         ret = CppExt::to_underlying(fsm_.SendEvent(Intent::SET_SOURCE, mediaSource));
139     }
140     if (ret != CppExt::to_underlying(ErrorCode::SUCCESS)) {
141         MEDIA_LOG_E("SetSource error: " PUBLIC_LOG_D32, ret);
142     }
143     PROFILE_END("SetSource end.");
144     return ret;
145 }
146 
Prepare()147 int32_t HiPlayerImpl::Prepare()
148 {
149     MEDIA_LOG_I("Prepare entered, current fsm state: " PUBLIC_LOG_S ".", fsm_.GetCurrentState().c_str());
150     PROFILE_BEGIN();
151     auto ret = fsm_.SendEvent(Intent::PREPARE);
152     if (ret != ErrorCode::SUCCESS) {
153         PROFILE_END("Prepare failed,");
154         MEDIA_LOG_E("prepare failed with error " PUBLIC_LOG_D32, ret);
155         return CppExt::to_underlying(ret);
156     }
157     OSAL::ScopedLock lock(stateMutex_);
158     if (curFsmState_ == StateId::PREPARING) { // Wait state change to ready
159         cond_.Wait(lock, [this] { return curFsmState_ != StateId::PREPARING; });
160     }
161     MEDIA_LOG_D("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
162     PROFILE_END("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
163     if (curFsmState_ == StateId::READY) {
164         return CppExt::to_underlying(ErrorCode::SUCCESS);
165     }
166     return CppExt::to_underlying(ErrorCode::ERROR_UNKNOWN);
167 }
168 
CreateAudioDecoder(const std::string & desc)169 PFilter HiPlayerImpl::CreateAudioDecoder(const std::string& desc)
170 {
171     if (!audioDecoderMap_[desc]) {
172         audioDecoderMap_[desc] = FilterFactory::Instance().CreateFilterWithType<AudioDecoderFilter>(
173             "builtin.player.audiodecoder", "audiodecoder-" + desc);
174         // set parameters to decoder.
175     }
176     return audioDecoderMap_[desc];
177 }
178 
Play()179 int32_t HiPlayerImpl::Play()
180 {
181     PROFILE_BEGIN();
182     ErrorCode ret;
183     MEDIA_LOG_I("Play entered.");
184     if (pipelineStates_ == PlayerStates::PLAYER_PAUSED) {
185         ret = fsm_.SendEvent(Intent::RESUME);
186     } else {
187         ret = fsm_.SendEvent(Intent::PLAY);
188     }
189     PROFILE_END("Play ret = " PUBLIC_LOG_D32, CppExt::to_underlying(ret));
190     return CppExt::to_underlying(ret);
191 }
192 
IsPlaying()193 bool HiPlayerImpl::IsPlaying()
194 {
195     return pipelineStates_ == PlayerStates::PLAYER_STARTED;
196 }
197 
Pause()198 int32_t HiPlayerImpl::Pause()
199 {
200     PROFILE_BEGIN();
201     MEDIA_LOG_I("Pause entered.");
202     auto ret = CppExt::to_underlying(fsm_.SendEvent(Intent::PAUSE));
203     PROFILE_END("Pause ret = " PUBLIC_LOG_D32, ret);
204     return ret;
205 }
206 
Stop()207 int32_t HiPlayerImpl::Stop()
208 {
209     PROFILE_BEGIN();
210     MEDIA_LOG_I("Stop entered.");
211     auto ret = CppExt::to_underlying(fsm_.SendEvent(Intent::STOP));
212     PROFILE_END("Stop ret = " PUBLIC_LOG_D32, ret);
213     return ret;
214 }
215 
StopAsync()216 ErrorCode HiPlayerImpl::StopAsync()
217 {
218     MEDIA_LOG_I("StopAsync entered.");
219     return fsm_.SendEventAsync(Intent::STOP);
220 }
221 
Rewind(int64_t mSeconds,int32_t mode)222 int32_t HiPlayerImpl::Rewind(int64_t mSeconds, int32_t mode)
223 {
224     MEDIA_LOG_I("Rewind entered.");
225     int64_t hstTime = 0;
226     int64_t durationMs = 0;
227     NZERO_RETURN(GetDuration(durationMs));
228     MEDIA_LOG_D("Rewind durationMs : " PUBLIC_LOG_D64, durationMs);
229     if (mSeconds >= durationMs) { // if exceeds change to duration
230         mSeconds = durationMs;
231     }
232     if (audioSource_->GetSeekable() != Plugin::Seekable::SEEKABLE) {
233         MEDIA_LOG_E("Seek, invalid operation, audio source is unseekable or invalid");
234         return CppExt::to_underlying(ErrorCode::ERROR_INVALID_OPERATION);
235     }
236     if (!Plugin::Ms2HstTime(mSeconds, hstTime)) {
237         return CppExt::to_underlying(ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
238     }
239     auto smode = Transform2SeekMode(static_cast<PlayerSeekMode>(mode));
240     return CppExt::to_underlying(fsm_.SendEvent(Intent::SEEK, SeekInfo{hstTime, smode}));
241 }
242 
SetVolume(float leftVolume,float rightVolume)243 int32_t HiPlayerImpl::SetVolume(float leftVolume, float rightVolume)
244 {
245     if (leftVolume < 0 || leftVolume > MAX_MEDIA_VOLUME || rightVolume < 0 || rightVolume > MAX_MEDIA_VOLUME) {
246         MEDIA_LOG_E("volume not valid, should be in range [0,100]");
247         return CppExt::to_underlying(ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
248     }
249     float volume = 0.0f;
250     if (leftVolume < 1e-6 && rightVolume >= 1e-6) { // 1e-6
251         volume = rightVolume;
252     } else if (rightVolume < 1e-6 && leftVolume >= 1e-6) { // 1e-6
253         volume = leftVolume;
254     } else {
255         volume = (leftVolume + rightVolume) / 2; // 2
256     }
257     volume /= MAX_MEDIA_VOLUME; // normalize to 0~1
258     if (pipelineStates_ == PlayerStates::PLAYER_STOPPED) {
259         return CppExt::to_underlying(ErrorCode::ERROR_INVALID_OPERATION);
260     }
261     volume_ = volume;
262     if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_INITIALIZED ||
263         pipelineStates_ == PlayerStates::PLAYER_PREPARING || audioSink_ == nullptr) {
264         MEDIA_LOG_W("cannot set volume, will do this onReady");
265         return CppExt::to_underlying(ErrorCode::SUCCESS);
266     }
267     return CppExt::to_underlying(SetVolumeToSink(volume_));
268 }
269 
270 #ifndef SURFACE_DISABLED
SetSurface(Surface * surface)271 int32_t HiPlayerImpl::SetSurface(Surface* surface)
272 {
273     return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED);
274 }
275 #endif
SetBufferSize(size_t size)276 ErrorCode HiPlayerImpl::SetBufferSize(size_t size)
277 {
278     return audioSource_->SetBufferSize(size);
279 }
280 
OnEvent(const Event & event)281 void HiPlayerImpl::OnEvent(const Event& event)
282 {
283     if (event.type != EventType::EVENT_AUDIO_PROGRESS) {
284         MEDIA_LOG_I("[HiStreamer] OnEvent (" PUBLIC_LOG_S ")", GetEventName(event.type));
285     }
286     switch (event.type) {
287         case EventType::EVENT_ERROR: {
288             fsm_.SendEventAsync(Intent::NOTIFY_ERROR, event.param);
289             break;
290         }
291         case EventType::EVENT_READY:
292             fsm_.SendEventAsync(Intent::NOTIFY_READY);
293             break;
294         case EventType::EVENT_COMPLETE:
295             mediaStats_.ReceiveEvent(event);
296             if (mediaStats_.IsEventCompleteAllReceived()) {
297                 fsm_.SendEventAsync(Intent::NOTIFY_COMPLETE);
298             }
299             break;
300         case EventType::EVENT_PLUGIN_ERROR: {
301             HandlePluginErrorEvent(event);
302             break;
303         }
304         case EventType::EVENT_PLUGIN_EVENT: {
305             Plugin::PluginEvent pluginEvent = Plugin::AnyCast<Plugin::PluginEvent>(event.param);
306             if (pluginEvent.type == Plugin::PluginEventType::BELOW_LOW_WATERLINE ||
307                 pluginEvent.type == Plugin::PluginEventType::ABOVE_LOW_WATERLINE) {
308                 MEDIA_LOG_I("Receive PLUGIN_EVENT, type:  " PUBLIC_LOG_D32, CppExt::to_underlying(pluginEvent.type));
309             }
310             break;
311         }
312         default:
313             MEDIA_LOG_E("Unknown event(" PUBLIC_LOG_U32 ")", event.type);
314     }
315 }
316 
DoSetSource(const std::shared_ptr<MediaSource> & source)317 ErrorCode HiPlayerImpl::DoSetSource(const std::shared_ptr<MediaSource>& source)
318 {
319     auto ret = audioSource_->SetSource(source);
320     if (ret != ErrorCode::SUCCESS) {
321         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
322     }
323     return ret;
324 }
325 
PrepareFilters()326 ErrorCode HiPlayerImpl::PrepareFilters()
327 {
328     auto ret = pipeline_->Prepare();
329     if (ret != ErrorCode::SUCCESS) {
330         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
331     }
332     return ret;
333 }
334 
DoPlay()335 ErrorCode HiPlayerImpl::DoPlay()
336 {
337     syncManager_->Resume();
338     auto ret = pipeline_->Start();
339     if (ret != ErrorCode::SUCCESS) {
340         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
341     }
342     return ret;
343 }
344 
DoPause()345 ErrorCode HiPlayerImpl::DoPause()
346 {
347     auto ret = pipeline_->Pause();
348     syncManager_->Pause();
349     if (ret != ErrorCode::SUCCESS) {
350         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
351     }
352     return ret;
353 }
354 
DoResume()355 ErrorCode HiPlayerImpl::DoResume()
356 {
357     syncManager_->Resume();
358     auto ret = pipeline_->Resume();
359     if (ret != ErrorCode::SUCCESS) {
360         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
361     }
362     return ret;
363 }
364 
DoStop()365 ErrorCode HiPlayerImpl::DoStop()
366 {
367     MEDIA_LOG_I("HiPlayerImpl DoStop called, stop pipeline.");
368     mediaStats_.Reset();
369     // 先先关闭demuxer线程,防止元数据解析prepare过程中出现并发问题
370     if (demuxer_) {
371         demuxer_->StopTask(false);
372     }
373     auto ret = pipeline_->Stop();
374     syncManager_->Reset();
375     if (ret != ErrorCode::SUCCESS) {
376         UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
377     }
378     return ret;
379 }
380 
DoReset()381 ErrorCode HiPlayerImpl::DoReset()
382 {
383     return DoStop();
384 }
385 
DoSeek(int64_t hstTime,Plugin::SeekMode mode,bool appTriggered)386 ErrorCode HiPlayerImpl::DoSeek(int64_t hstTime, Plugin::SeekMode mode, bool appTriggered)
387 {
388     if (appTriggered) {
389         fsm_.Notify(Intent::SEEK, ErrorCode::SUCCESS);
390     }
391     PROFILE_BEGIN();
392     auto rtv = hstTime >= 0 ? ErrorCode::SUCCESS : ErrorCode::ERROR_INVALID_OPERATION;
393     if (rtv == ErrorCode::SUCCESS) {
394         pipeline_->FlushStart();
395         PROFILE_END("Flush start");
396         PROFILE_RESET();
397 
398         int64_t realSeekTime = hstTime;
399         rtv = demuxer_->SeekTo(hstTime, mode, realSeekTime);
400         if (rtv == ErrorCode::SUCCESS) {
401             syncManager_->Seek(realSeekTime);
402         }
403         PROFILE_END("SeekTo");
404 
405         pipeline_->FlushEnd();
406         PROFILE_END("Flush end");
407         PROFILE_RESET();
408     }
409     auto ptr = callback_.lock();
410     if (ptr != nullptr) {
411         if (rtv != ErrorCode::SUCCESS) {
412             ptr->OnError(CppExt::to_underlying(PlayerErrorTypeExt::SEEK_ERROR), CppExt::to_underlying(rtv));
413         } else {
414             ptr->OnRewindToComplete();
415         }
416     }
417     if (appTriggered) {
418         return ErrorCode::ERROR_NO_NOTIFY;
419     }
420     return rtv;
421 }
422 
DoOnReady()423 ErrorCode HiPlayerImpl::DoOnReady()
424 {
425     SetVolumeToSink(volume_, false); // do not report
426     auto tmpMeta = demuxer_->GetGlobalMetaInfo();
427     sourceMeta_ = tmpMeta;
428     int64_t duration = 0;
429     bool found = false;
430     if (tmpMeta->Get<Media::Plugin::Tag::MEDIA_DURATION>(duration)) {
431         found = true;
432     } else {
433         MEDIA_LOG_W("Get media duration failed.");
434     }
435     streamMeta_.clear();
436     int64_t tmp = 0;
437     for (auto& streamMeta : demuxer_->GetStreamMetaInfo()) {
438         streamMeta_.push_back(streamMeta);
439         if (streamMeta->Get<Media::Plugin::Tag::MEDIA_DURATION>(tmp)) {
440             duration = std::max(duration, tmp);
441             found = true;
442         } else {
443             MEDIA_LOG_W("Get media duration failed.");
444         }
445     }
446     if (found) {
447         duration_ = duration;
448     }
449     return ErrorCode::SUCCESS;
450 }
451 
DoOnComplete()452 ErrorCode HiPlayerImpl::DoOnComplete()
453 {
454     MEDIA_LOG_W("OnComplete looping: " PUBLIC_LOG_D32 ".", singleLoop_.load());
455     auto ptr = callback_.lock();
456     FALSE_RETURN_V_MSG(ptr != nullptr, ErrorCode::SUCCESS, "Player callback not exist.");
457     ptr->OnPlaybackComplete();
458     return ErrorCode::SUCCESS;
459 }
460 
DoOnError(ErrorCode errorCode)461 ErrorCode HiPlayerImpl::DoOnError(ErrorCode errorCode)
462 {
463     UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
464     auto ptr = callback_.lock();
465     FALSE_RETURN_V_MSG(ptr != nullptr, ErrorCode::SUCCESS, "Player callback not exist.");
466     ptr->OnError(PlayerCallback::PlayerCallback::PLAYER_ERROR_UNKNOWN, static_cast<int32_t>(errorCode));
467     return ErrorCode::SUCCESS;
468 }
469 
SetVolumeToSink(float volume,bool reportUpward)470 ErrorCode HiPlayerImpl::SetVolumeToSink(float volume, bool reportUpward)
471 {
472     MEDIA_LOG_I("SetVolumeToSink entered.");
473     ErrorCode ret = ErrorCode::SUCCESS;
474     if (volume_ > 0) {
475         MEDIA_LOG_I("set volume " PUBLIC_LOG_F, volume);
476         ret = audioSink_->SetVolume(volume);
477     }
478     auto ptr = callback_.lock();
479     if (ptr != nullptr) {
480         if (ret != ErrorCode::SUCCESS) {
481             MEDIA_LOG_E("SetVolume failed with error " PUBLIC_LOG_D32, static_cast<int>(ret));
482             ptr->OnError(PlayerCallback::PlayerCallback::PLAYER_ERROR_UNKNOWN, CppExt::to_underlying(ret));
483         }
484     }
485     return ret;
486 }
487 
IsSingleLooping()488 bool HiPlayerImpl::IsSingleLooping()
489 {
490     return singleLoop_.load();
491 }
492 
SetLoop(bool loop)493 int32_t HiPlayerImpl::SetLoop(bool loop)
494 {
495     MEDIA_LOG_I("SetLoop entered, loop: " PUBLIC_LOG_D32, loop);
496     singleLoop_ = loop;
497     return CppExt::to_underlying(ErrorCode::SUCCESS);
498 }
499 
IsSingleLoop()500 bool HiPlayerImpl::IsSingleLoop()
501 {
502     // note that we should also consider the live source, which cannot be singleLoop!
503     return singleLoop_;
504 }
505 
SetPlayerCallback(const std::shared_ptr<PlayerCallback> & cb)506 void HiPlayerImpl::SetPlayerCallback(const std::shared_ptr<PlayerCallback>& cb)
507 {
508     callback_ = cb;
509 }
510 
Reset()511 int32_t HiPlayerImpl::Reset()
512 {
513     MEDIA_LOG_I("Reset entered.");
514     singleLoop_ = false;
515     mediaStats_.Reset();
516     return CppExt::to_underlying(fsm_.SendEvent(Intent::RESET));
517 }
518 
Release()519 int32_t HiPlayerImpl::Release()
520 {
521     PROFILE_BEGIN();
522     auto ret = Reset();
523     fsm_.Stop();
524     pipeline_.reset();
525     audioSource_.reset();
526     demuxer_.reset();
527     audioDecoderMap_.clear();
528     audioSink_.reset();
529     PROFILE_END("Release ret = " PUBLIC_LOG_D32, ret);
530     return ret;
531 }
532 
DeInit()533 int32_t HiPlayerImpl::DeInit()
534 {
535     return Reset();
536 }
537 
GetPlayerState(int32_t & state)538 int32_t HiPlayerImpl::GetPlayerState(int32_t& state)
539 {
540     state = static_cast<int32_t>(pipelineStates_.load());
541     return CppExt::to_underlying(ErrorCode::SUCCESS);
542 }
543 
GetCurrentPosition(int64_t & currentPositionMs)544 int32_t HiPlayerImpl::GetCurrentPosition(int64_t& currentPositionMs)
545 {
546     currentPositionMs = Plugin::HstTime2Ms(syncManager_->GetMediaTimeNow());
547     return CppExt::to_underlying(ErrorCode::SUCCESS);
548 }
549 
GetDuration(int64_t & outDurationMs)550 int32_t HiPlayerImpl::GetDuration(int64_t& outDurationMs)
551 {
552     MEDIA_LOG_I("GetDuration entered.");
553     outDurationMs = 0;
554     if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_PREPARING
555         || audioSource_ == nullptr) {
556         return CppExt::to_underlying(ErrorCode::ERROR_INVALID_STATE);
557     }
558     if (duration_ < 0) {
559         outDurationMs = -1;
560         MEDIA_LOG_W("no valid duration");
561         return CppExt::to_underlying(ErrorCode::ERROR_UNKNOWN);
562     }
563     outDurationMs = Plugin::HstTime2Ms(duration_);
564     MEDIA_LOG_I("GetDuration returned " PUBLIC_LOG_D32, outDurationMs);
565     return CppExt::to_underlying(ErrorCode::SUCCESS);
566 }
567 
GetVideoWidth(int32_t & videoWidth)568 int32_t HiPlayerImpl::GetVideoWidth(int32_t& videoWidth)
569 {
570     return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED);
571 }
572 
GetVideoHeight(int32_t & videoHeight)573 int32_t HiPlayerImpl::GetVideoHeight(int32_t& videoHeight)
574 {
575     return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED);
576 }
577 
HandlePluginErrorEvent(const Event & event)578 void HiPlayerImpl::HandlePluginErrorEvent(const Event& event)
579 {
580     Plugin::PluginEvent pluginEvent = Plugin::AnyCast<Plugin::PluginEvent>(event.param);
581     MEDIA_LOG_I("Receive PLUGIN_ERROR, type:  " PUBLIC_LOG_D32, CppExt::to_underlying(pluginEvent.type));
582     if (pluginEvent.type == Plugin::PluginEventType::CLIENT_ERROR &&
583             Plugin::Any::IsSameTypeWith<Plugin::NetworkClientErrorCode>(pluginEvent.param)) {
584         auto netClientErrorCode = Plugin::AnyCast<Plugin::NetworkClientErrorCode>(pluginEvent.param);
585         auto errorCode {-1};
586         if (netClientErrorCode == Plugin::NetworkClientErrorCode::ERROR_TIME_OUT) {
587             errorCode = CppExt::to_underlying(Plugin::NetworkClientErrorCode::ERROR_TIME_OUT);
588         }
589         auto ptr = callback_.lock();
590         if (ptr != nullptr) {
591             ptr->OnError(PlayerCallback::PlayerErrorType::PLAYER_ERROR_UNKNOWN, errorCode);
592         }
593     }
594 }
SetPlaybackSpeed(float speed)595 int32_t HiPlayerImpl::SetPlaybackSpeed(float speed)
596 {
597     return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED);
598 }
599 
GetPlaybackSpeed(float & speed)600 int32_t HiPlayerImpl::GetPlaybackSpeed(float& speed)
601 {
602     return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED);
603 }
604 
SetAudioStreamType(int32_t type)605 int32_t HiPlayerImpl::SetAudioStreamType(int32_t type)
606 {
607     return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED);
608 }
609 
GetAudioStreamType(int32_t & type)610 void HiPlayerImpl::GetAudioStreamType(int32_t& type)
611 {
612     type = -1;
613 }
614 
SetParameter(const Format & params)615 int32_t HiPlayerImpl::SetParameter(const Format& params)
616 {
617     return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED);
618 }
619 
OnStateChanged(StateId state)620 void HiPlayerImpl::OnStateChanged(StateId state)
621 {
622     MEDIA_LOG_I("OnStateChanged from " PUBLIC_LOG_D32 " to " PUBLIC_LOG_D32, curFsmState_.load(), state);
623     UpdateStateNoLock(TransStateId2PlayerState(state));
624     {
625         OSAL::ScopedLock lock(stateMutex_);
626         curFsmState_ = state;
627         cond_.NotifyOne();
628     }
629 }
630 
OnCallback(const FilterCallbackType & type,Filter * filter,const Plugin::Any & parameter)631 ErrorCode HiPlayerImpl::OnCallback(const FilterCallbackType& type, Filter* filter, const Plugin::Any& parameter)
632 {
633     ErrorCode ret = ErrorCode::SUCCESS;
634     switch (type) {
635         case FilterCallbackType::PORT_ADDED:
636             ret = NewAudioPortFound(filter, parameter);
637             if (ret != ErrorCode::SUCCESS) {
638                 return ret;
639             }
640 #ifdef VIDEO_SUPPORT
641             ret = NewVideoPortFound(filter, parameter);
642 #endif
643             break;
644         case FilterCallbackType::PORT_REMOVE:
645             ret = RemoveFilterChains(filter, parameter);
646             break;
647         default:
648             break;
649     }
650     return ret;
651 }
652 
GetTrackCnt(size_t & cnt) const653 ErrorCode HiPlayerImpl::GetTrackCnt(size_t& cnt) const
654 {
655     cnt = streamMeta_.size();
656     return ErrorCode::SUCCESS;
657 }
658 
GetSourceMeta(shared_ptr<const Plugin::Meta> & meta) const659 ErrorCode HiPlayerImpl::GetSourceMeta(shared_ptr<const Plugin::Meta>& meta) const
660 {
661     meta = sourceMeta_.lock();
662     return meta ? ErrorCode::SUCCESS : ErrorCode::ERROR_AGAIN;
663 }
664 
GetTrackMeta(size_t id,shared_ptr<const Plugin::Meta> & meta) const665 ErrorCode HiPlayerImpl::GetTrackMeta(size_t id, shared_ptr<const Plugin::Meta>& meta) const
666 {
667     if (id > streamMeta_.size() || id < 0) {
668         return ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
669     }
670     meta = streamMeta_[id].lock();
671     if (meta == nullptr) {
672         return ErrorCode::ERROR_AGAIN;
673     }
674     return ErrorCode::SUCCESS;
675 }
676 
NewAudioPortFound(Filter * filter,const Plugin::Any & parameter)677 ErrorCode HiPlayerImpl::NewAudioPortFound(Filter* filter, const Plugin::Any& parameter)
678 {
679     if (!Plugin::Any::IsSameTypeWith<PortInfo>(parameter)) {
680         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
681     }
682     ErrorCode rtv = ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
683     auto param = Plugin::AnyCast<PortInfo>(parameter);
684     if (filter == demuxer_.get() && param.type == PortType::OUT) {
685         MEDIA_LOG_I("new port found on demuxer " PUBLIC_LOG_ZU, param.ports.size());
686         for (const auto& portDesc : param.ports) {
687             if (portDesc.name.compare(0, 5, "audio") != 0) { // 5 is length of "audio"
688                 continue;
689             }
690             MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
691             auto fromPort = filter->GetOutPort(portDesc.name);
692             if (portDesc.isPcm) {
693                 pipeline_->AddFilters({audioSink_.get()});
694                 FAIL_LOG(pipeline_->LinkPorts(fromPort, audioSink_->GetInPort(PORT_NAME_DEFAULT)));
695                 ActiveFilters({audioSink_.get()});
696             } else {
697                 auto newAudioDecoder = CreateAudioDecoder(portDesc.name);
698                 pipeline_->AddFilters({newAudioDecoder.get(), audioSink_.get()});
699                 FAIL_LOG(pipeline_->LinkPorts(fromPort, newAudioDecoder->GetInPort(PORT_NAME_DEFAULT)));
700                 FAIL_LOG(pipeline_->LinkPorts(newAudioDecoder->GetOutPort(PORT_NAME_DEFAULT),
701                                               audioSink_->GetInPort(PORT_NAME_DEFAULT)));
702                 ActiveFilters({newAudioDecoder.get(), audioSink_.get()});
703             }
704             mediaStats_.Append(audioSink_->GetName());
705             rtv = ErrorCode::SUCCESS;
706             break;
707         }
708     }
709     return rtv;
710 }
711 
712 #ifdef VIDEO_SUPPORT
NewVideoPortFound(Filter * filter,const Plugin::Any & parameter)713 ErrorCode HiPlayerImpl::NewVideoPortFound(Filter* filter, const Plugin::Any& parameter)
714 {
715     if (!Plugin::Any::IsSameTypeWith<PortInfo>(parameter)) {
716         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
717     }
718     auto param = Plugin::AnyCast<PortInfo>(parameter);
719     if (filter != demuxer_.get() || param.type != PortType::OUT) {
720         return ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
721     }
722     std::vector<Filter*> newFilters;
723     for (const auto& portDesc : param.ports) {
724         if (portDesc.name.compare(0, 5, "video") == 0) { // 5 is length of "video"
725             MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
726             videoDecoder = FilterFactory::Instance().CreateFilterWithType<VideoDecoderFilter>(
727                 "builtin.player.videodecoder", "videodecoder-" + portDesc.name);
728             if (pipeline_->AddFilters({videoDecoder.get()}) == ErrorCode::SUCCESS) {
729                 // link demuxer and video decoder
730                 auto fromPort = filter->GetOutPort(portDesc.name);
731                 auto toPort = videoDecoder->GetInPort(PORT_NAME_DEFAULT);
732                 FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports
733                 newFilters.emplace_back(videoDecoder.get());
734 
735                 // link video decoder and video sink
736                 if (pipeline_->AddFilters({videoSink.get()}) == ErrorCode::SUCCESS) {
737                     fromPort = videoDecoder->GetOutPort(PORT_NAME_DEFAULT);
738                     toPort = videoSink->GetInPort(PORT_NAME_DEFAULT);
739                     FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports
740                     newFilters.push_back(videoSink.get());
741                     mediaStats_.Append(videoSink->GetName());
742                 }
743             }
744             break;
745         }
746     }
747     if (!newFilters.empty()) {
748         ActiveFilters(newFilters);
749     }
750     return ErrorCode::SUCCESS;
751 }
752 #endif
753 
RemoveFilterChains(Filter * filter,const Plugin::Any & parameter)754 ErrorCode HiPlayerImpl::RemoveFilterChains(Filter* filter, const Plugin::Any& parameter)
755 {
756     ErrorCode ret = ErrorCode::SUCCESS;
757     auto param = Plugin::AnyCast<PortInfo>(parameter);
758     if (filter != demuxer_.get() || param.type != PortType::OUT) {
759         return ret;
760     }
761     for (const auto& portDesc : param.ports) {
762         MEDIA_LOG_I("remove filter chain for port: " PUBLIC_LOG_S, portDesc.name.c_str());
763         auto peerPort = filter->GetOutPort(portDesc.name)->GetPeerPort();
764         if (peerPort) {
765             auto nextFilter = const_cast<Filter*>(reinterpret_cast<const Filter*>(peerPort->GetOwnerFilter()));
766             if (nextFilter) {
767                 pipeline_->RemoveFilterChain(nextFilter);
768             }
769         }
770     }
771     return ret;
772 }
773 
ActiveFilters(const std::vector<Filter * > & filters)774 void HiPlayerImpl::ActiveFilters(const std::vector<Filter*>& filters)
775 {
776     for (auto it = filters.rbegin(); it != filters.rend(); ++it) {
777         (*it)->Prepare();
778     }
779 }
780 
TransStateId2PlayerState(StateId state)781 PlayerStates HiPlayerImpl::TransStateId2PlayerState(StateId state)
782 {
783     PlayerStates playerState = PLAYER_STATE_ERROR;
784     switch (state) {
785         case StateId::IDLE:
786             playerState = PLAYER_IDLE;
787             break;
788         case StateId::INIT:
789             playerState = PLAYER_INITIALIZED;
790             break;
791         case StateId::PREPARING:
792             playerState = PLAYER_PREPARING;
793             break;
794         case StateId::READY:
795             playerState = PLAYER_PREPARED;
796             break;
797         case StateId::PAUSE:
798             playerState = PLAYER_PAUSED;
799             break;
800         case StateId::PLAYING:
801             playerState = PLAYER_STARTED;
802             break;
803         case StateId::STOPPED:
804             playerState = PLAYER_STOPPED;
805             break;
806         case StateId::EOS:
807             playerState = PLAYER_PLAYBACK_COMPLETE;
808             break;
809         default:
810             break;
811     }
812     return playerState;
813 }
814 
Transform2SeekMode(PlayerSeekMode mode)815 Plugin::SeekMode HiPlayerImpl::Transform2SeekMode(PlayerSeekMode mode)
816 {
817     switch (mode) {
818         case PlayerSeekMode::PLAYER_SEEK_NEXT_SYNC:
819             return Plugin::SeekMode::SEEK_NEXT_SYNC;
820         case PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC:
821             return Plugin::SeekMode::SEEK_PREVIOUS_SYNC;
822         case PlayerSeekMode::PLAYER_SEEK_CLOSEST_SYNC:
823             return Plugin::SeekMode::SEEK_CLOSEST_SYNC;
824         case PlayerSeekMode::PLAYER_SEEK_CLOSEST:
825             return Plugin::SeekMode::SEEK_CLOSEST;
826         default:
827             return Plugin::SeekMode::SEEK_CLOSEST;
828     }
829 }
830 
StringnessPlayerState(PlayerStates state)831 const std::string& HiPlayerImpl::StringnessPlayerState(PlayerStates state)
832 {
833     using StateString = std::pair<PlayerStates, std::string>;
834     const static std::array<StateString, 9> maps = { // array size
835         std::make_pair(PlayerStates::PLAYER_STATE_ERROR, "state error"),
836         std::make_pair(PlayerStates::PLAYER_IDLE, "idle"),
837         std::make_pair(PlayerStates::PLAYER_INITIALIZED, "init"),
838         std::make_pair(PlayerStates::PLAYER_PREPARING, "preparing"),
839         std::make_pair(PlayerStates::PLAYER_PREPARED, "prepared"),
840         std::make_pair(PlayerStates::PLAYER_STARTED, "started"),
841         std::make_pair(PlayerStates::PLAYER_PAUSED, "paused"),
842         std::make_pair(PlayerStates::PLAYER_STOPPED, "stopped"),
843         std::make_pair(PlayerStates::PLAYER_PLAYBACK_COMPLETE, "completed"),
844     };
845     const static std::string UNKNOWN = "unknown";
846     auto ite = std::find_if(maps.begin(), maps.end(), [&] (const StateString& item) -> bool {
847         return item.first == state;
848     });
849     if (ite == maps.end()) {
850         return UNKNOWN;
851     }
852     return ite->second;
853 }
854 } // namespace Media
855 } // namespace OHOS
856