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