• 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 "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         pluginEvent.param.SameTypeWith(typeid(Plugin::NetworkClientErrorCode))) {
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 #ifdef VIDEO_SUPPORT
638             ret = NewVideoPortFound(filter, parameter);
639 #endif
640             break;
641         case FilterCallbackType::PORT_REMOVE:
642             ret = RemoveFilterChains(filter, parameter);
643             break;
644         default:
645             break;
646     }
647     return ret;
648 }
649 
GetTrackCnt(size_t & cnt) const650 ErrorCode HiPlayerImpl::GetTrackCnt(size_t& cnt) const
651 {
652     cnt = streamMeta_.size();
653     return ErrorCode::SUCCESS;
654 }
655 
GetSourceMeta(shared_ptr<const Plugin::Meta> & meta) const656 ErrorCode HiPlayerImpl::GetSourceMeta(shared_ptr<const Plugin::Meta>& meta) const
657 {
658     meta = sourceMeta_.lock();
659     return meta ? ErrorCode::SUCCESS : ErrorCode::ERROR_AGAIN;
660 }
661 
GetTrackMeta(size_t id,shared_ptr<const Plugin::Meta> & meta) const662 ErrorCode HiPlayerImpl::GetTrackMeta(size_t id, shared_ptr<const Plugin::Meta>& meta) const
663 {
664     if (id > streamMeta_.size() || id < 0) {
665         return ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
666     }
667     meta = streamMeta_[id].lock();
668     if (meta == nullptr) {
669         return ErrorCode::ERROR_AGAIN;
670     }
671     return ErrorCode::SUCCESS;
672 }
673 
NewAudioPortFound(Filter * filter,const Plugin::Any & parameter)674 ErrorCode HiPlayerImpl::NewAudioPortFound(Filter* filter, const Plugin::Any& parameter)
675 {
676     if (!parameter.SameTypeWith(typeid(PortInfo))) {
677         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
678     }
679     ErrorCode rtv = ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
680     auto param = Plugin::AnyCast<PortInfo>(parameter);
681     if (filter == demuxer_.get() && param.type == PortType::OUT) {
682         MEDIA_LOG_I("new port found on demuxer " PUBLIC_LOG_ZU, param.ports.size());
683         for (const auto& portDesc : param.ports) {
684             if (portDesc.name.compare(0, 5, "audio") != 0) { // 5 is length of "audio"
685                 continue;
686             }
687             MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
688             auto fromPort = filter->GetOutPort(portDesc.name);
689             if (portDesc.isPcm) {
690                 pipeline_->AddFilters({audioSink_.get()});
691                 FAIL_LOG(pipeline_->LinkPorts(fromPort, audioSink_->GetInPort(PORT_NAME_DEFAULT)));
692                 ActiveFilters({audioSink_.get()});
693             } else {
694                 auto newAudioDecoder = CreateAudioDecoder(portDesc.name);
695                 pipeline_->AddFilters({newAudioDecoder.get(), audioSink_.get()});
696                 FAIL_LOG(pipeline_->LinkPorts(fromPort, newAudioDecoder->GetInPort(PORT_NAME_DEFAULT)));
697                 FAIL_LOG(pipeline_->LinkPorts(newAudioDecoder->GetOutPort(PORT_NAME_DEFAULT),
698                                               audioSink_->GetInPort(PORT_NAME_DEFAULT)));
699                 ActiveFilters({newAudioDecoder.get(), audioSink_.get()});
700             }
701             mediaStats_.Append(audioSink_->GetName());
702             rtv = ErrorCode::SUCCESS;
703             break;
704         }
705     }
706     return rtv;
707 }
708 
709 #ifdef VIDEO_SUPPORT
NewVideoPortFound(Filter * filter,const Plugin::Any & parameter)710 ErrorCode HiPlayerImpl::NewVideoPortFound(Filter* filter, const Plugin::Any& parameter)
711 {
712     if (!parameter.SameTypeWith(typeid(PortInfo))) {
713         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
714     }
715     auto param = Plugin::AnyCast<PortInfo>(parameter);
716     if (filter != demuxer_.get() || param.type != PortType::OUT) {
717         return ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
718     }
719     std::vector<Filter*> newFilters;
720     for (const auto& portDesc : param.ports) {
721         if (portDesc.name.compare(0, 5, "video") == 0) { // 5 is length of "video"
722             MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
723             videoDecoder = FilterFactory::Instance().CreateFilterWithType<VideoDecoderFilter>(
724                 "builtin.player.videodecoder", "videodecoder-" + portDesc.name);
725             if (pipeline_->AddFilters({videoDecoder.get()}) == ErrorCode::SUCCESS) {
726                 // link demuxer and video decoder
727                 auto fromPort = filter->GetOutPort(portDesc.name);
728                 auto toPort = videoDecoder->GetInPort(PORT_NAME_DEFAULT);
729                 FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports
730                 newFilters.emplace_back(videoDecoder.get());
731 
732                 // link video decoder and video sink
733                 if (pipeline_->AddFilters({videoSink.get()}) == ErrorCode::SUCCESS) {
734                     fromPort = videoDecoder->GetOutPort(PORT_NAME_DEFAULT);
735                     toPort = videoSink->GetInPort(PORT_NAME_DEFAULT);
736                     FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports
737                     newFilters.push_back(videoSink.get());
738                     mediaStats_.Append(videoSink->GetName());
739                 }
740             }
741             break;
742         }
743     }
744     if (!newFilters.empty()) {
745         ActiveFilters(newFilters);
746     }
747     return ErrorCode::SUCCESS;
748 }
749 #endif
750 
RemoveFilterChains(Filter * filter,const Plugin::Any & parameter)751 ErrorCode HiPlayerImpl::RemoveFilterChains(Filter* filter, const Plugin::Any& parameter)
752 {
753     ErrorCode ret = ErrorCode::SUCCESS;
754     auto param = Plugin::AnyCast<PortInfo>(parameter);
755     if (filter != demuxer_.get() || param.type != PortType::OUT) {
756         return ret;
757     }
758     for (const auto& portDesc : param.ports) {
759         MEDIA_LOG_I("remove filter chain for port: " PUBLIC_LOG_S, portDesc.name.c_str());
760         auto peerPort = filter->GetOutPort(portDesc.name)->GetPeerPort();
761         if (peerPort) {
762             auto nextFilter = const_cast<Filter*>(dynamic_cast<const Filter*>(peerPort->GetOwnerFilter()));
763             if (nextFilter) {
764                 pipeline_->RemoveFilterChain(nextFilter);
765             }
766         }
767     }
768     return ret;
769 }
770 
ActiveFilters(const std::vector<Filter * > & filters)771 void HiPlayerImpl::ActiveFilters(const std::vector<Filter*>& filters)
772 {
773     for (auto it = filters.rbegin(); it != filters.rend(); ++it) {
774         (*it)->Prepare();
775     }
776 }
777 
TransStateId2PlayerState(StateId state)778 PlayerStates HiPlayerImpl::TransStateId2PlayerState(StateId state)
779 {
780     PlayerStates playerState = PLAYER_STATE_ERROR;
781     switch (state) {
782         case StateId::IDLE:
783             playerState = PLAYER_IDLE;
784             break;
785         case StateId::INIT:
786             playerState = PLAYER_INITIALIZED;
787             break;
788         case StateId::PREPARING:
789             playerState = PLAYER_PREPARING;
790             break;
791         case StateId::READY:
792             playerState = PLAYER_PREPARED;
793             break;
794         case StateId::PAUSE:
795             playerState = PLAYER_PAUSED;
796             break;
797         case StateId::PLAYING:
798             playerState = PLAYER_STARTED;
799             break;
800         case StateId::STOPPED:
801             playerState = PLAYER_STOPPED;
802             break;
803         case StateId::EOS:
804             playerState = PLAYER_PLAYBACK_COMPLETE;
805             break;
806         default:
807             break;
808     }
809     return playerState;
810 }
811 
Transform2SeekMode(PlayerSeekMode mode)812 Plugin::SeekMode HiPlayerImpl::Transform2SeekMode(PlayerSeekMode mode)
813 {
814     switch (mode) {
815         case PlayerSeekMode::PLAYER_SEEK_NEXT_SYNC:
816             return Plugin::SeekMode::SEEK_NEXT_SYNC;
817         case PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC:
818             return Plugin::SeekMode::SEEK_PREVIOUS_SYNC;
819         case PlayerSeekMode::PLAYER_SEEK_CLOSEST_SYNC:
820             return Plugin::SeekMode::SEEK_CLOSEST_SYNC;
821         case PlayerSeekMode::PLAYER_SEEK_CLOSEST:
822             return Plugin::SeekMode::SEEK_CLOSEST;
823         default:
824             return Plugin::SeekMode::SEEK_CLOSEST;
825     }
826 }
827 
StringnessPlayerState(PlayerStates state)828 const std::string& HiPlayerImpl::StringnessPlayerState(PlayerStates state)
829 {
830     using StateString = std::pair<PlayerStates, std::string>;
831     const static std::array<StateString, 9> maps = { // array size
832         std::make_pair(PlayerStates::PLAYER_STATE_ERROR, "state error"),
833         std::make_pair(PlayerStates::PLAYER_IDLE, "idle"),
834         std::make_pair(PlayerStates::PLAYER_INITIALIZED, "init"),
835         std::make_pair(PlayerStates::PLAYER_PREPARING, "preparing"),
836         std::make_pair(PlayerStates::PLAYER_PREPARED, "prepared"),
837         std::make_pair(PlayerStates::PLAYER_STARTED, "started"),
838         std::make_pair(PlayerStates::PLAYER_PAUSED, "paused"),
839         std::make_pair(PlayerStates::PLAYER_STOPPED, "stopped"),
840         std::make_pair(PlayerStates::PLAYER_PLAYBACK_COMPLETE, "completed"),
841     };
842     const static std::string UNKNOWN = "unknown";
843     auto ite = std::find_if(maps.begin(), maps.end(), [&] (const StateString& item) -> bool {
844         return item.first == state;
845     });
846     if (ite == maps.end()) {
847         return UNKNOWN;
848     }
849     return ite->second;
850 }
851 } // namespace Media
852 } // namespace OHOS
853