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