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