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 "hitrace_meter.h"
21 #include "pipeline/factory/filter_factory.h"
22 #include "scene/player/standard/media_utils.h"
23 #include "plugin/common/media_source.h"
24 #include "plugin/common/plugin_time.h"
25 #include "plugin/core/plugin_meta.h"
26 #include "utils/steady_clock.h"
27 #include "av_common.h"
28 #include "media_errors.h"
29
30 namespace {
31 const float MAX_MEDIA_VOLUME = 1.0f; // standard interface volume is between 0 to 1.
32 }
33
34 namespace OHOS {
35 namespace Media {
36 using namespace Pipeline;
37 constexpr double EPSINON = 0.0001;
38 constexpr double SPEED_0_75_X = 0.75;
39 constexpr double SPEED_1_00_X = 1.00;
40 constexpr double SPEED_1_25_X = 1.25;
41 constexpr double SPEED_1_75_X = 1.75;
42 constexpr double SPEED_2_00_X = 2.00;
43
HiPlayerImpl(int32_t appUid,int32_t appPid)44 HiPlayerImpl::HiPlayerImpl(int32_t appUid, int32_t appPid)
45 : appUid_(appUid),
46 appPid_(appPid),
47 fsm_(*this),
48 curFsmState_(StateId::IDLE),
49 volume_(-1.0f), // default negative, if app not set, will not set it.
50 mediaStats_()
51 {
52 StartTrace(HITRACE_TAG_ZMEDIA, "Hst hiPlayerImpl ctor");
53 MEDIA_LOG_I("hiPlayerImpl ctor");
54 FilterFactory::Instance().Init();
55 syncManager_ = std::make_shared<MediaSyncManager>();
56
57 audioSource_ =
58 FilterFactory::Instance().CreateFilterWithType<MediaSourceFilter>("builtin.player.mediasource", "mediaSource");
59 #ifdef UNIT_TEST
60 demuxer_ = FilterFactory::Instance().CreateFilterWithType<DemuxerFilter>("builtin.player.demuxer", "demuxer");
61 audioDecoder_ = FilterFactory::Instance().CreateFilterWithType<AudioDecoderFilter>("builtin.player.audiodecoder",
62 "audiodecoder");
63 audioSink_ =
64 FilterFactory::Instance().CreateFilterWithType<AudioSinkFilter>("builtin.player.audiosink", "audiosink");
65 #else
66 demuxer_ = FilterFactory::Instance().CreateFilterWithType<DemuxerFilter>("builtin.player.demuxer", "demuxer");
67 audioSink_ =
68 FilterFactory::Instance().CreateFilterWithType<AudioSinkFilter>("builtin.player.audiosink", "audioSink");
69 audioSink_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_PID), appPid_);
70 audioSink_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_UID), appUid_);
71 #ifdef VIDEO_SUPPORT
72 videoSink_ =
73 FilterFactory::Instance().CreateFilterWithType<VideoSinkFilter>("builtin.player.videosink", "videoSink");
74 FALSE_RETURN(videoSink_ != nullptr);
75 videoSink_->SetSyncCenter(syncManager_);
76 #endif
77 #endif
78 FALSE_RETURN(audioSource_ != nullptr);
79 FALSE_RETURN(demuxer_ != nullptr);
80 FALSE_RETURN(audioSink_ != nullptr);
81 audioSink_->SetSyncCenter(syncManager_);
82 pipeline_ = std::make_shared<PipelineCore>();
83 callbackLooper_.SetPlayEngine(this);
84 FinishTrace(HITRACE_TAG_ZMEDIA);
85 }
86
~HiPlayerImpl()87 HiPlayerImpl::~HiPlayerImpl()
88 {
89 MEDIA_LOG_I("dtor called.");
90 fsm_.SendEventAsync(Intent::STOP);
91 fsm_.Stop();
92 callbackLooper_.Stop();
93 audioSink_.reset();
94 #ifdef VIDEO_SUPPORT
95 videoSink_.reset();
96 if (surface_) {
97 surface_ = nullptr;
98 }
99 #endif
100 syncManager_.reset();
101 }
UpdateStateNoLock(PlayerStates newState,bool notifyUpward)102 void HiPlayerImpl::UpdateStateNoLock(PlayerStates newState, bool notifyUpward)
103 {
104 if (pipelineStates_ == newState) {
105 return;
106 }
107 pipelineStates_ = newState;
108 if (pipelineStates_ == PlayerStates::PLAYER_IDLE) {
109 MEDIA_LOG_W("do not report idle since audio player will report idle");
110 return;
111 }
112 if (notifyUpward) {
113 if (callbackLooper_.IsStarted()) {
114 Format format;
115 while (!pendingStates_.empty()) {
116 auto pendingState = pendingStates_.front();
117 pendingStates_.pop();
118 MEDIA_LOG_I("sending pending state change: " PUBLIC_LOG_S, StringnessPlayerState(pendingState).c_str());
119 callbackLooper_.OnInfo(INFO_TYPE_STATE_CHANGE, pendingState, format);
120 }
121 MEDIA_LOG_I("sending newest state change: " PUBLIC_LOG_S,
122 StringnessPlayerState(pipelineStates_.load()).c_str());
123 callbackLooper_.OnInfo(INFO_TYPE_STATE_CHANGE, pipelineStates_, format);
124 } else {
125 pendingStates_.push(newState);
126 }
127 }
128 }
129
Init()130 ErrorCode HiPlayerImpl::Init()
131 {
132 MEDIA_LOG_I("Init entered.");
133 mediaStats_.Reset();
134 if (initialized_.load()) {
135 return ErrorCode::SUCCESS;
136 }
137 pipeline_->Init(this, this);
138 ErrorCode ret = pipeline_->AddFilters({audioSource_.get(), demuxer_.get()});
139 if (ret == ErrorCode::SUCCESS) {
140 ret = pipeline_->LinkFilters({audioSource_.get(), demuxer_.get()});
141 }
142 if (ret == ErrorCode::SUCCESS) {
143 fsm_.SetStateCallback(this);
144 fsm_.Start();
145 initialized_ = true;
146 } else {
147 pipeline_->UnlinkPrevFilters();
148 pipeline_->RemoveFilterChain(audioSource_.get());
149 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
150 }
151 return ret;
152 }
153
SetSource(const std::string & uri)154 int32_t HiPlayerImpl::SetSource(const std::string& uri)
155 {
156 StartTrace(HITRACE_TAG_ZMEDIA, "Hst player SetSource");
157 MEDIA_LOG_I("SetSource entered source uri: " PUBLIC_LOG_S, uri.c_str());
158 PROFILE_BEGIN("SetSource begin");
159 auto ret = Init();
160 if (ret == ErrorCode::SUCCESS) {
161 ret = fsm_.SendEvent(Intent::SET_SOURCE, std::make_shared<MediaSource>(uri));
162 }
163 if (ret != ErrorCode::SUCCESS) {
164 MEDIA_LOG_E("SetSource error: " PUBLIC_LOG_S, GetErrorName(ret));
165 }
166 PROFILE_END("SetSource end.");
167 FinishTrace(HITRACE_TAG_ZMEDIA);
168 return TransErrorCode(ret);
169 }
170
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)171 int32_t HiPlayerImpl::SetSource(const std::shared_ptr<IMediaDataSource>& dataSrc)
172 {
173 MEDIA_LOG_I("SetSource entered source stream");
174 PROFILE_BEGIN("SetSource begin");
175 auto ret = Init();
176 if (ret == ErrorCode::SUCCESS) {
177 ret = fsm_.SendEvent(Intent::SET_SOURCE, std::make_shared<MediaSource>(dataSrc));
178 }
179 if (ret != ErrorCode::SUCCESS) {
180 MEDIA_LOG_E("SetSource error: " PUBLIC_LOG_S, GetErrorName(ret));
181 }
182 PROFILE_END("SetSource end.");
183 return TransErrorCode(ret);
184 }
185
Prepare()186 int32_t HiPlayerImpl::Prepare()
187 {
188 StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Prepare");
189 MEDIA_LOG_I("Prepare entered, current fsm state: " PUBLIC_LOG_S ".", fsm_.GetCurrentState().c_str());
190 PROFILE_BEGIN();
191 auto ret = fsm_.SendEvent(Intent::PREPARE);
192 if (ret != ErrorCode::SUCCESS) {
193 PROFILE_END("Prepare failed,");
194 MEDIA_LOG_E("Prepare failed with error " PUBLIC_LOG_D32, ret);
195 return TransErrorCode(ret);
196 }
197 OSAL::ScopedLock lock(stateMutex_);
198 if (curFsmState_ == StateId::PREPARING) { // Wait state change to ready
199 cond_.Wait(lock, [this] { return curFsmState_ != StateId::PREPARING; });
200 }
201 MEDIA_LOG_D("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
202 PROFILE_END("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
203 if (curFsmState_ == StateId::READY) {
204 return TransErrorCode(ErrorCode::SUCCESS);
205 }
206 FinishTrace(HITRACE_TAG_ZMEDIA);
207 return TransErrorCode(ErrorCode::ERROR_UNKNOWN);
208 }
209
PrepareAsync()210 int HiPlayerImpl::PrepareAsync()
211 {
212 StartAsyncTrace(HITRACE_TAG_ZMEDIA, "Hst player PrepareAsync", 1);
213 MEDIA_LOG_I("Prepare async entered, current fsm state: " PUBLIC_LOG_S, fsm_.GetCurrentState().c_str());
214 PROFILE_BEGIN();
215 auto ret = fsm_.SendEventAsync(Intent::PREPARE);
216 if (ret != ErrorCode::SUCCESS) {
217 PROFILE_END("Prepare async failed,");
218 MEDIA_LOG_E("Prepare async failed with error " PUBLIC_LOG_D32, ret);
219 } else {
220 PROFILE_END("Prepare async successfully,");
221 }
222 FinishAsyncTrace(HITRACE_TAG_ZMEDIA, "Hst player PrepareAsync", 1);
223 return TransErrorCode(ret);
224 }
225
Play()226 int32_t HiPlayerImpl::Play()
227 {
228 StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Play");
229 MEDIA_LOG_I("Play entered.");
230 callbackLooper_.StartReportMediaProgress();
231 PROFILE_BEGIN();
232 seekInProgress_.store(false);
233 ErrorCode ret;
234 if (pipelineStates_ == PlayerStates::PLAYER_PAUSED) {
235 ret = fsm_.SendEvent(Intent::RESUME);
236 } else {
237 ret = fsm_.SendEvent(Intent::PLAY);
238 }
239 PROFILE_END("Play ret = " PUBLIC_LOG_D32, TransErrorCode(ret));
240 FinishTrace(HITRACE_TAG_ZMEDIA);
241 return TransErrorCode(ret);
242 }
243
Pause()244 int32_t HiPlayerImpl::Pause()
245 {
246 StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Pause");
247 MEDIA_LOG_I("Pause entered.");
248 PROFILE_BEGIN();
249 auto ret = TransErrorCode(fsm_.SendEvent(Intent::PAUSE));
250 callbackLooper_.StopReportMediaProgress();
251 callbackLooper_.ManualReportMediaProgressOnce();
252 PROFILE_END("Pause ret = " PUBLIC_LOG_D32, ret);
253 FinishTrace(HITRACE_TAG_ZMEDIA);
254 return ret;
255 }
256
Stop()257 int32_t HiPlayerImpl::Stop()
258 {
259 StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Stop");
260 MEDIA_LOG_I("Stop entered.");
261 PROFILE_BEGIN();
262 auto ret = TransErrorCode(fsm_.SendEvent(Intent::STOP));
263 callbackLooper_.StopReportMediaProgress();
264 callbackLooper_.ManualReportMediaProgressOnce();
265 PROFILE_END("Stop ret = " PUBLIC_LOG_D32, ret);
266 FinishTrace(HITRACE_TAG_ZMEDIA);
267 return ret;
268 }
269
StopAsync()270 ErrorCode HiPlayerImpl::StopAsync()
271 {
272 MEDIA_LOG_I("StopAsync entered.");
273 return fsm_.SendEventAsync(Intent::STOP);
274 }
275
Seek(int32_t mSeconds,PlayerSeekMode mode)276 int32_t HiPlayerImpl::Seek(int32_t mSeconds, PlayerSeekMode mode)
277 {
278 StartTrace(HITRACE_TAG_ZMEDIA, "Hst player Seek");
279 MEDIA_LOG_I("Seek entered. mSeconds : " PUBLIC_LOG_D32 ", seekMode : " PUBLIC_LOG_D32,
280 mSeconds, static_cast<int32_t>(mode));
281 int64_t hstTime = 0;
282 int32_t durationMs = 0;
283 NZERO_RETURN(GetDuration(durationMs));
284 MEDIA_LOG_D("Seek durationMs : " PUBLIC_LOG_D32, durationMs);
285 if (mSeconds >= durationMs) { // if exceeds change to duration
286 mSeconds = durationMs;
287 }
288 if (audioSource_->GetSeekable() != Plugin::Seekable::SEEKABLE) {
289 MEDIA_LOG_E("Seek, invalid operation, audio source is unseekable or invalid");
290 return MSERR_INVALID_OPERATION;
291 }
292 if (!Plugin::Ms2HstTime(mSeconds, hstTime)) {
293 return TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
294 }
295 auto smode = Transform2SeekMode(mode);
296 lastSeekPosition_.store(hstTime);
297 lastSeekMode_.store(smode);
298 if (!seekInProgress_.load()) {
299 seekInProgress_.store(true);
300 auto ret = fsm_.SendEvent(Intent::SEEK, SeekInfo{hstTime, smode});
301 if (ret != ErrorCode::SUCCESS) {
302 seekInProgress_.store(false);
303 }
304 FinishTrace(HITRACE_TAG_ZMEDIA);
305 return TransErrorCode(ret);
306 } else {
307 MEDIA_LOG_D("Seek in progress. Record the seek request [" PUBLIC_LOG_D64 "," PUBLIC_LOG_D32 "]",
308 hstTime, static_cast<int32_t>(smode));
309 FinishTrace(HITRACE_TAG_ZMEDIA);
310 return MSERR_OK;
311 }
312 }
313
SetVolume(float leftVolume,float rightVolume)314 int32_t HiPlayerImpl::SetVolume(float leftVolume, float rightVolume)
315 {
316 MEDIA_LOG_I("SetVolume entered.");
317 if (leftVolume < 0 || leftVolume > MAX_MEDIA_VOLUME || rightVolume < 0 || rightVolume > MAX_MEDIA_VOLUME) {
318 MEDIA_LOG_E("volume not valid, should be in range [0,100]");
319 return TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
320 }
321 float volume = 0.0f;
322 if (leftVolume < 1e-6 && rightVolume >= 1e-6) { // 1e-6
323 volume = rightVolume;
324 } else if (rightVolume < 1e-6 && leftVolume >= 1e-6) { // 1e-6
325 volume = leftVolume;
326 } else {
327 volume = (leftVolume + rightVolume) / 2; // 2
328 }
329 volume /= MAX_MEDIA_VOLUME; // normalize to 0~1
330 if (pipelineStates_ == PlayerStates::PLAYER_STOPPED) {
331 return TransErrorCode(ErrorCode::ERROR_INVALID_OPERATION);
332 }
333 volume_ = volume;
334 if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_INITIALIZED ||
335 pipelineStates_ == PlayerStates::PLAYER_PREPARING || audioSink_ == nullptr) {
336 MEDIA_LOG_W("cannot set volume, will do this onReady");
337 return TransErrorCode(ErrorCode::SUCCESS);
338 }
339 return TransErrorCode(SetVolumeToSink(volume));
340 }
341
SetVideoSurface(sptr<Surface> surface)342 int32_t HiPlayerImpl::SetVideoSurface(sptr<Surface> surface)
343 {
344 MEDIA_LOG_D("SetVideoSurface entered.");
345 #ifdef VIDEO_SUPPORT
346 if (surface != nullptr) {
347 surface_ = surface;
348 }
349 return TransErrorCode(videoSink_->SetVideoSurface(surface_));
350 #else
351 return TransErrorCode(ErrorCode::SUCCESS);
352 #endif
353 }
354
GetVideoTrackInfo(std::vector<Format> & videoTrack)355 int32_t HiPlayerImpl::GetVideoTrackInfo(std::vector<Format>& videoTrack)
356 {
357 MEDIA_LOG_I("GetVideoTrackInfo entered.");
358 std::string mime;
359 std::vector<std::shared_ptr<Plugin::Meta>> metaInfo = demuxer_->GetStreamMetaInfo();
360 for (const auto& trackInfo : metaInfo) {
361 if (trackInfo->GetString(Plugin::MetaID::MIME, mime)) {
362 if (IsVideoMime(mime)) {
363 int64_t bitRate;
364 uint32_t frameRate;
365 uint32_t height;
366 uint32_t width;
367 uint32_t trackIndex;
368 Format videoTrackInfo {};
369 (void)videoTrackInfo.PutStringValue("codec_mime", mime);
370 (void)videoTrackInfo.PutIntValue("track_type", MediaType::MEDIA_TYPE_VID);
371 if (trackInfo->GetUint32(Plugin::MetaID::TRACK_ID, trackIndex)) {
372 (void)videoTrackInfo.PutIntValue("track_index", static_cast<int32_t>(trackIndex));
373 }
374 if (trackInfo->GetInt64(Plugin::MetaID::MEDIA_BITRATE, bitRate)) {
375 (void)videoTrackInfo.PutIntValue("bitrate", static_cast<int32_t>(bitRate));
376 }
377 if (trackInfo->GetUint32(Plugin::MetaID::VIDEO_FRAME_RATE, frameRate)) {
378 (void)videoTrackInfo.PutIntValue("frame_rate", static_cast<int32_t>(frameRate));
379 }
380 if (trackInfo->GetUint32(Plugin::MetaID::VIDEO_HEIGHT, height)) {
381 (void)videoTrackInfo.PutIntValue("height", static_cast<int32_t>(height));
382 }
383 if (trackInfo->GetUint32(Plugin::MetaID::VIDEO_WIDTH, width)) {
384 (void)videoTrackInfo.PutIntValue("width", static_cast<int32_t>(width));
385 }
386 videoTrack.push_back(videoTrackInfo);
387 }
388 }
389 }
390 return TransErrorCode(ErrorCode::SUCCESS);
391 }
392
GetAudioTrackInfo(std::vector<Format> & audioTrack)393 int32_t HiPlayerImpl::GetAudioTrackInfo(std::vector<Format>& audioTrack)
394 {
395 MEDIA_LOG_I("GetAudioTrackInfo entered.");
396 std::string mime;
397 std::vector<std::shared_ptr<Plugin::Meta>> metaInfo = demuxer_->GetStreamMetaInfo();
398 for (const auto& trackInfo : metaInfo) {
399 if (trackInfo->GetString(Plugin::MetaID::MIME, mime)) {
400 if (IsAudioMime(mime)) {
401 int64_t bitRate;
402 uint32_t audioChannels;
403 uint32_t audioSampleRate;
404 uint32_t trackIndex;
405 Format audioTrackInfo {};
406 (void)audioTrackInfo.PutStringValue("codec_mime", mime);
407 (void)audioTrackInfo.PutIntValue("track_type", MediaType::MEDIA_TYPE_AUD);
408 if (trackInfo->GetUint32(Plugin::MetaID::TRACK_ID, trackIndex)) {
409 (void)audioTrackInfo.PutIntValue("track_index", static_cast<int32_t>(trackIndex));
410 }
411 if (trackInfo->GetInt64(Plugin::MetaID::MEDIA_BITRATE, bitRate)) {
412 (void)audioTrackInfo.PutIntValue("bitrate", static_cast<int32_t>(bitRate));
413 }
414 if (trackInfo->GetUint32(Plugin::MetaID::AUDIO_CHANNELS, audioChannels)) {
415 (void)audioTrackInfo.PutIntValue("channel_count", static_cast<int32_t>(audioChannels));
416 }
417 if (trackInfo->GetUint32(Plugin::MetaID::AUDIO_SAMPLE_RATE, audioSampleRate)) {
418 (void)audioTrackInfo.PutIntValue("sample_rate", static_cast<int32_t>(audioSampleRate));
419 }
420 audioTrack.push_back(audioTrackInfo);
421 }
422 }
423 }
424 return TransErrorCode(ErrorCode::SUCCESS);
425 }
426
GetVideoWidth()427 int32_t HiPlayerImpl::GetVideoWidth()
428 {
429 MEDIA_LOG_I("GetVideoWidth entered.");
430 if (surface_ != nullptr) {
431 return surface_->GetDefaultWidth();
432 }
433 return 0;
434 }
435
GetVideoHeight()436 int32_t HiPlayerImpl::GetVideoHeight()
437 {
438 MEDIA_LOG_I("GetVideoHeight entered.");
439 if (surface_ != nullptr) {
440 return surface_->GetDefaultHeight();
441 }
442 return 0;
443 }
444
HandlePluginErrorEvent(const Event & event)445 void HiPlayerImpl::HandlePluginErrorEvent(const Event& event)
446 {
447 Plugin::PluginEvent pluginEvent = Plugin::AnyCast<Plugin::PluginEvent>(event.param);
448 MEDIA_LOG_I("Receive PLUGIN_ERROR, type: " PUBLIC_LOG_D32, CppExt::to_underlying(pluginEvent.type));
449 if (pluginEvent.type == Plugin::PluginEventType::CLIENT_ERROR &&
450 pluginEvent.param.SameTypeWith(typeid(Plugin::NetworkClientErrorCode))) {
451 auto netClientErrorCode = Plugin::AnyCast<Plugin::NetworkClientErrorCode>(pluginEvent.param);
452 auto errorType {PlayerErrorType::PLAYER_ERROR_UNKNOWN};
453 auto serviceErrCode { MSERR_UNKNOWN };
454 if (netClientErrorCode == Plugin::NetworkClientErrorCode::ERROR_TIME_OUT) {
455 errorType = PlayerErrorType::PLAYER_ERROR;
456 serviceErrCode = MSERR_NETWORK_TIMEOUT;
457 }
458 callbackLooper_.OnError(errorType, serviceErrCode);
459 }
460 }
461
OnEvent(const Event & event)462 void HiPlayerImpl::OnEvent(const Event& event)
463 {
464 if (event.type != EventType::EVENT_AUDIO_PROGRESS) {
465 MEDIA_LOG_I("[HiStreamer] OnEvent (" PUBLIC_LOG_S ")", GetEventName(event.type));
466 }
467 switch (event.type) {
468 case EventType::EVENT_ERROR: {
469 fsm_.SendEventAsync(Intent::NOTIFY_ERROR, event.param);
470 break;
471 }
472 case EventType::EVENT_READY:
473 fsm_.SendEventAsync(Intent::NOTIFY_READY);
474 break;
475 case EventType::EVENT_COMPLETE:
476 mediaStats_.ReceiveEvent(event);
477 if (mediaStats_.IsEventCompleteAllReceived()) {
478 fsm_.SendEventAsync(Intent::NOTIFY_COMPLETE);
479 }
480 break;
481 case EventType::EVENT_PLUGIN_ERROR: {
482 HandlePluginErrorEvent(event);
483 break;
484 }
485 case EventType::EVENT_PLUGIN_EVENT: {
486 auto pluginEvent = Plugin::AnyCast<Plugin::PluginEvent>(event.param);
487 switch (pluginEvent.type) {
488 case Plugin::PluginEventType::INTERRUPT: {
489 auto interruptEvent = Plugin::AnyCast<Plugin::AudioInterruptEvent>(pluginEvent.param);
490 Format format;
491 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, interruptEvent.eventType);
492 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, interruptEvent.forceType);
493 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, interruptEvent.hintType);
494 callbackLooper_.OnInfo(INFO_TYPE_INTERRUPT_EVENT, 0, format);
495 MEDIA_LOG_I("Receive Audio INTERRUPT EVENT");
496 break;
497 }
498 case Plugin::PluginEventType::BELOW_LOW_WATERLINE:
499 case Plugin::PluginEventType::ABOVE_LOW_WATERLINE:
500 default:
501 MEDIA_LOG_I("Receive PLUGIN_EVENT, type: " PUBLIC_LOG_D32,
502 CppExt::to_underlying(pluginEvent.type));
503 break;
504 }
505 break;
506 }
507 default:
508 MEDIA_LOG_E("Unknown event(" PUBLIC_LOG_U32 ")", event.type);
509 }
510 }
511
DoSetSource(const std::shared_ptr<MediaSource> & source)512 ErrorCode HiPlayerImpl::DoSetSource(const std::shared_ptr<MediaSource>& source)
513 {
514 auto ret = audioSource_->SetSource(source);
515 if (ret != ErrorCode::SUCCESS) {
516 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
517 }
518 return ret;
519 }
520
PrepareFilters()521 ErrorCode HiPlayerImpl::PrepareFilters()
522 {
523 auto ret = pipeline_->Prepare();
524 if (ret != ErrorCode::SUCCESS) {
525 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
526 }
527 return ret;
528 }
529
DoPlay()530 ErrorCode HiPlayerImpl::DoPlay()
531 {
532 syncManager_->Resume();
533 auto ret = pipeline_->Start();
534 if (ret != ErrorCode::SUCCESS) {
535 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
536 }
537 return ret;
538 }
539
DoPause()540 ErrorCode HiPlayerImpl::DoPause()
541 {
542 auto ret = pipeline_->Pause();
543 syncManager_->Pause();
544 if (ret != ErrorCode::SUCCESS) {
545 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
546 }
547 return ret;
548 }
549
DoResume()550 ErrorCode HiPlayerImpl::DoResume()
551 {
552 syncManager_->Resume();
553 auto ret = pipeline_->Resume();
554 if (ret != ErrorCode::SUCCESS) {
555 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
556 }
557 return ret;
558 }
559
DoStop()560 ErrorCode HiPlayerImpl::DoStop()
561 {
562 mediaStats_.Reset();
563 auto ret = pipeline_->Stop();
564 syncManager_->Reset();
565 if (ret != ErrorCode::SUCCESS) {
566 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
567 }
568 return ret;
569 }
570
DoReset()571 ErrorCode HiPlayerImpl::DoReset()
572 {
573 return DoStop();
574 }
575
DoSeek(int64_t hstTime,Plugin::SeekMode mode,bool appTriggered)576 ErrorCode HiPlayerImpl::DoSeek(int64_t hstTime, Plugin::SeekMode mode, bool appTriggered)
577 {
578 if (appTriggered) {
579 fsm_.Notify(Intent::SEEK, ErrorCode::SUCCESS);
580 }
581 PROFILE_BEGIN();
582 int64_t seekPos = hstTime;
583 Plugin::SeekMode seekMode = mode;
584 if (appTriggered && (hstTime != lastSeekPosition_.load() || mode != lastSeekMode_.load())) { // Newer seek happened
585 seekPos = lastSeekPosition_.load();
586 seekMode = lastSeekMode_.load();
587 }
588 auto rtv = seekPos >= 0 ? ErrorCode::SUCCESS : ErrorCode::ERROR_INVALID_OPERATION;
589 if (rtv == ErrorCode::SUCCESS) {
590 pipeline_->FlushStart();
591 PROFILE_END("Flush start");
592 PROFILE_RESET();
593
594 MEDIA_LOG_I("Do seek ...");
595 syncManager_->Seek(seekPos);
596 rtv = demuxer_->SeekTo(seekPos, seekMode);
597 PROFILE_END("SeekTo");
598
599 pipeline_->FlushEnd();
600 PROFILE_END("Flush end");
601 PROFILE_RESET();
602 }
603 if (rtv != ErrorCode::SUCCESS) {
604 callbackLooper_.OnError(PLAYER_ERROR, MSERR_SEEK_FAILED);
605 } else {
606 Format format;
607 int64_t currentPos = Plugin::HstTime2Ms(seekPos);
608 MEDIA_LOG_I("Seek done, currentPos : " PUBLIC_LOG_D64 ", appTriggered: " PUBLIC_LOG_D32,
609 currentPos, appTriggered);
610 callbackLooper_.OnInfo(INFO_TYPE_SEEKDONE, static_cast<int32_t>(currentPos), format);
611 }
612 if (appTriggered && seekInProgress_.load()) {
613 OSAL::SleepFor(10); // 10 wait seek real complete
614 seekInProgress_.store(false);
615 }
616 if (appTriggered) {
617 return ErrorCode::ERROR_NO_NOTIFY;
618 }
619 return rtv;
620 }
621
DoOnReady()622 ErrorCode HiPlayerImpl::DoOnReady()
623 {
624 SetVolumeToSink(volume_, false); // do not report
625 auto tmpMeta = demuxer_->GetGlobalMetaInfo();
626 sourceMeta_ = tmpMeta;
627 int64_t duration = 0;
628 bool found = false;
629 if (tmpMeta->GetInt64(Media::Plugin::MetaID::MEDIA_DURATION, duration)) {
630 found = true;
631 }
632 streamMeta_.clear();
633 int64_t tmp = 0;
634 for (auto& streamMeta : demuxer_->GetStreamMetaInfo()) {
635 streamMeta_.push_back(streamMeta);
636 if (streamMeta->GetInt64(Media::Plugin::MetaID::MEDIA_DURATION, tmp)) {
637 duration = std::max(duration, tmp);
638 found = true;
639 }
640 }
641 if (found) {
642 duration_ = duration;
643 }
644 return ErrorCode::SUCCESS;
645 }
646
DoOnComplete()647 ErrorCode HiPlayerImpl::DoOnComplete()
648 {
649 MEDIA_LOG_I("OnComplete looping: " PUBLIC_LOG_D32 ".", singleLoop_.load());
650 Format format;
651 callbackLooper_.OnInfo(INFO_TYPE_EOS, static_cast<int32_t>(singleLoop_.load()), format);
652 if (!singleLoop_.load()) {
653 callbackLooper_.StopReportMediaProgress();
654 callbackLooper_.ManualReportMediaProgressOnce();
655 }
656 return ErrorCode::SUCCESS;
657 }
658
DoOnError(ErrorCode errorCode)659 ErrorCode HiPlayerImpl::DoOnError(ErrorCode errorCode)
660 {
661 UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR);
662 callbackLooper_.OnError(PLAYER_ERROR, TransErrorCode(errorCode));
663 return ErrorCode::SUCCESS;
664 }
665
SetVolumeToSink(float volume,bool reportUpward)666 ErrorCode HiPlayerImpl::SetVolumeToSink(float volume, bool reportUpward)
667 {
668 MEDIA_LOG_I("SetVolumeToSink entered.");
669 ErrorCode ret = ErrorCode::SUCCESS;
670 if (volume_ > 0) {
671 MEDIA_LOG_I("set volume " PUBLIC_LOG_F, volume);
672 ret = audioSink_->SetVolume(volume);
673 }
674
675 if (ret != ErrorCode::SUCCESS) {
676 MEDIA_LOG_E("SetVolume failed with error " PUBLIC_LOG_D32, static_cast<int>(ret));
677 callbackLooper_.OnError(PLAYER_ERROR, TransErrorCode(ret));
678 } else if (reportUpward) {
679 Format format;
680 callbackLooper_.OnInfo(INFO_TYPE_VOLUME_CHANGE, volume, format);
681 }
682 return ret;
683 }
684
CreateAudioDecoder(const std::string & desc)685 PFilter HiPlayerImpl::CreateAudioDecoder(const std::string& desc)
686 {
687 if (!audioDecoderMap_[desc]) {
688 audioDecoderMap_[desc] = FilterFactory::Instance().CreateFilterWithType<AudioDecoderFilter>(
689 "builtin.player.audiodecoder", "audiodecoder-" + desc);
690 // set parameters to decoder.
691 }
692 return audioDecoderMap_[desc];
693 }
694
SetLooping(bool loop)695 int32_t HiPlayerImpl::SetLooping(bool loop)
696 {
697 MEDIA_LOG_I("SetLooping entered, loop: " PUBLIC_LOG_D32, loop);
698 singleLoop_ = loop;
699 return TransErrorCode(ErrorCode::SUCCESS);
700 }
701
IsSingleLoop()702 bool HiPlayerImpl::IsSingleLoop()
703 {
704 // note that we should also consider the live source, which cannot be singleLoop!
705 return singleLoop_;
706 }
707
SetParameter(const Format & params)708 int32_t HiPlayerImpl::SetParameter(const Format& params)
709 {
710 MEDIA_LOG_I("SetParameter entered.");
711 if (params.ContainKey(PlayerKeys::VIDEO_SCALE_TYPE)) {
712 int32_t videoScaleType = 0;
713 params.GetIntValue(PlayerKeys::VIDEO_SCALE_TYPE, videoScaleType);
714 return SetVideoScaleType(VideoScaleType(videoScaleType));
715 }
716 if (params.ContainKey(PlayerKeys::CONTENT_TYPE) && params.ContainKey(PlayerKeys::STREAM_USAGE)) {
717 int32_t contentType;
718 int32_t streamUsage;
719 int32_t rendererFlag;
720 params.GetIntValue(PlayerKeys::CONTENT_TYPE, contentType);
721 params.GetIntValue(PlayerKeys::STREAM_USAGE, streamUsage);
722 params.GetIntValue(PlayerKeys::RENDERER_FLAG, rendererFlag);
723 return SetAudioRendererInfo(contentType, streamUsage, rendererFlag);
724 }
725 if (params.ContainKey(PlayerKeys::AUDIO_INTERRUPT_MODE)) {
726 int32_t interruptMode = 0;
727 params.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_MODE, interruptMode);
728 return SetAudioInterruptMode(interruptMode);
729 }
730 return TransErrorCode(ErrorCode::ERROR_UNIMPLEMENTED);
731 }
732
SetObs(const std::weak_ptr<IPlayerEngineObs> & obs)733 int32_t HiPlayerImpl::SetObs(const std::weak_ptr<IPlayerEngineObs>& obs)
734 {
735 MEDIA_LOG_I("SetObs entered.");
736 callbackLooper_.StartWithPlayerEngineObs(obs);
737 return TransErrorCode(ErrorCode::SUCCESS);
738 }
739
Reset()740 int32_t HiPlayerImpl::Reset()
741 {
742 MEDIA_LOG_I("Reset entered.");
743 singleLoop_ = false;
744 mediaStats_.Reset();
745 return TransErrorCode(fsm_.SendEvent(Intent::RESET));
746 }
747
GetCurrentTime(int32_t & currentPositionMs)748 int32_t HiPlayerImpl::GetCurrentTime(int32_t& currentPositionMs)
749 {
750 currentPositionMs = Plugin::HstTime2Ms(syncManager_->GetMediaTimeNow());
751 return TransErrorCode(ErrorCode::SUCCESS);
752 }
753
GetDuration(int32_t & durationMs)754 int32_t HiPlayerImpl::GetDuration(int32_t& durationMs)
755 {
756 durationMs = 0;
757 if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_PREPARING ||
758 audioSource_ == nullptr) {
759 MEDIA_LOG_E("GetDuration, invalid state or audioSource_ is null. state: " PUBLIC_LOG_S,
760 StringnessPlayerState(pipelineStates_).c_str());
761 return MSERR_INVALID_STATE;
762 }
763 if (duration_ < 0) {
764 durationMs = -1;
765 MEDIA_LOG_W("no valid duration");
766 return MSERR_UNKNOWN;
767 }
768 durationMs = Plugin::HstTime2Ms(duration_);
769 MEDIA_LOG_DD("GetDuration returned " PUBLIC_LOG_D32, durationMs);
770 return MSERR_OK;
771 }
772
SetPlaybackSpeed(PlaybackRateMode mode)773 int32_t HiPlayerImpl::SetPlaybackSpeed(PlaybackRateMode mode)
774 {
775 MEDIA_LOG_I("SetPlaybackSpeed entered.");
776 double playbackSpeed = ChangeModeToSpeed(mode);
777 demuxer_->SetParameter(static_cast<int32_t>(Plugin::Tag::MEDIA_PLAYBACK_SPEED), playbackSpeed);
778 return MSERR_OK;
779 }
GetPlaybackSpeed(PlaybackRateMode & mode)780 int32_t HiPlayerImpl::GetPlaybackSpeed(PlaybackRateMode& mode)
781 {
782 MEDIA_LOG_I("GetPlaybackSpeed entered.");
783 Plugin::Any any;
784 demuxer_->GetParameter(static_cast<int32_t>(Plugin::Tag::MEDIA_PLAYBACK_SPEED), any);
785 auto playbackSpeed = Plugin::AnyCast<double>(any);
786 mode = ChangeSpeedToMode(playbackSpeed);
787 return MSERR_OK;
788 }
789
OnStateChanged(StateId state)790 void HiPlayerImpl::OnStateChanged(StateId state)
791 {
792 MEDIA_LOG_I("OnStateChanged from " PUBLIC_LOG_D32 " to " PUBLIC_LOG_D32, curFsmState_.load(), state);
793 UpdateStateNoLock(TransStateId2PlayerState(state));
794 {
795 OSAL::ScopedLock lock(stateMutex_);
796 curFsmState_ = state;
797 cond_.NotifyOne();
798 }
799 }
800
OnCallback(const FilterCallbackType & type,Filter * filter,const Plugin::Any & parameter)801 ErrorCode HiPlayerImpl::OnCallback(const FilterCallbackType& type, Filter* filter, const Plugin::Any& parameter)
802 {
803 ErrorCode ret = ErrorCode::SUCCESS;
804 switch (type) {
805 case FilterCallbackType::PORT_ADDED:
806 ret = NewAudioPortFound(filter, parameter);
807 #ifdef VIDEO_SUPPORT
808 ret = NewVideoPortFound(filter, parameter);
809 #endif
810 break;
811 case FilterCallbackType::PORT_REMOVE:
812 ret = RemoveFilterChains(filter, parameter);
813 break;
814 default:
815 break;
816 }
817 return ret;
818 }
819
NewAudioPortFound(Filter * filter,const Plugin::Any & parameter)820 ErrorCode HiPlayerImpl::NewAudioPortFound(Filter* filter, const Plugin::Any& parameter)
821 {
822 if (!parameter.SameTypeWith(typeid(PortInfo))) {
823 return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
824 }
825 ErrorCode rtv = ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
826 auto param = Plugin::AnyCast<PortInfo>(parameter);
827 if (filter == demuxer_.get() && param.type == PortType::OUT) {
828 MEDIA_LOG_I("new port found on demuxer " PUBLIC_LOG_ZU, param.ports.size());
829 for (const auto& portDesc : param.ports) {
830 if (portDesc.name.compare(0, 5, "audio") != 0) { // 5 is length of "audio"
831 continue;
832 }
833 MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
834 auto fromPort = filter->GetOutPort(portDesc.name);
835 if (portDesc.isPcm) {
836 pipeline_->AddFilters({audioSink_.get()});
837 FAIL_LOG(pipeline_->LinkPorts(fromPort, audioSink_->GetInPort(PORT_NAME_DEFAULT)));
838 ActiveFilters({audioSink_.get()});
839 } else {
840 auto newAudioDecoder = CreateAudioDecoder(portDesc.name);
841 pipeline_->AddFilters({newAudioDecoder.get(), audioSink_.get()});
842 FAIL_LOG(pipeline_->LinkPorts(fromPort, newAudioDecoder->GetInPort(PORT_NAME_DEFAULT)));
843 FAIL_LOG(pipeline_->LinkPorts(newAudioDecoder->GetOutPort(PORT_NAME_DEFAULT),
844 audioSink_->GetInPort(PORT_NAME_DEFAULT)));
845 ActiveFilters({newAudioDecoder.get(), audioSink_.get()});
846 }
847 mediaStats_.Append(audioSink_->GetName());
848 rtv = ErrorCode::SUCCESS;
849 break;
850 }
851 }
852 return rtv;
853 }
854
855 #ifdef VIDEO_SUPPORT
NewVideoPortFound(Filter * filter,const Plugin::Any & parameter)856 ErrorCode HiPlayerImpl::NewVideoPortFound(Filter* filter, const Plugin::Any& parameter)
857 {
858 if (!parameter.SameTypeWith(typeid(PortInfo))) {
859 return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
860 }
861 auto param = Plugin::AnyCast<PortInfo>(parameter);
862 if (filter != demuxer_.get() || param.type != PortType::OUT) {
863 return ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
864 }
865 std::vector<Filter*> newFilters;
866 for (const auto& portDesc : param.ports) {
867 if (portDesc.name.compare(0, 5, "video") == 0) { // 5 is length of "video"
868 MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str());
869 videoDecoder_ = FilterFactory::Instance().CreateFilterWithType<VideoDecoderFilter>(
870 "builtin.player.videodecoder", "videodecoder-" + portDesc.name);
871 if (pipeline_->AddFilters({videoDecoder_.get()}) == ErrorCode::SUCCESS) {
872 // link demuxer and video decoder
873 auto fromPort = filter->GetOutPort(portDesc.name);
874 auto toPort = videoDecoder_->GetInPort(PORT_NAME_DEFAULT);
875 FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports
876 newFilters.emplace_back(videoDecoder_.get());
877
878 // link video decoder and video sink
879 if (pipeline_->AddFilters({videoSink_.get()}) == ErrorCode::SUCCESS) {
880 fromPort = videoDecoder_->GetOutPort(PORT_NAME_DEFAULT);
881 toPort = videoSink_->GetInPort(PORT_NAME_DEFAULT);
882 FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports
883 newFilters.push_back(videoSink_.get());
884 mediaStats_.Append(videoSink_->GetName());
885 }
886 }
887 break;
888 }
889 }
890 if (!newFilters.empty()) {
891 ActiveFilters(newFilters);
892 }
893 return ErrorCode::SUCCESS;
894 }
895 #endif
896
RemoveFilterChains(Filter * filter,const Plugin::Any & parameter)897 ErrorCode HiPlayerImpl::RemoveFilterChains(Filter* filter, const Plugin::Any& parameter)
898 {
899 ErrorCode ret = ErrorCode::SUCCESS;
900 auto param = Plugin::AnyCast<PortInfo>(parameter);
901 if (filter != demuxer_.get() || param.type != PortType::OUT) {
902 return ret;
903 }
904 for (const auto& portDesc : param.ports) {
905 MEDIA_LOG_I("remove filter chain for port: " PUBLIC_LOG_S, portDesc.name.c_str());
906 auto peerPort = filter->GetOutPort(portDesc.name)->GetPeerPort();
907 if (peerPort) {
908 auto nextFilter = const_cast<Filter*>(dynamic_cast<const Filter*>(peerPort->GetOwnerFilter()));
909 if (nextFilter) {
910 pipeline_->RemoveFilterChain(nextFilter);
911 }
912 }
913 }
914 return ret;
915 }
916
ActiveFilters(const std::vector<Filter * > & filters)917 void HiPlayerImpl::ActiveFilters(const std::vector<Filter*>& filters)
918 {
919 for (auto it = filters.rbegin(); it != filters.rend(); ++it) {
920 (*it)->Prepare();
921 }
922 }
923
ChangeModeToSpeed(const PlaybackRateMode & mode) const924 double HiPlayerImpl::ChangeModeToSpeed(const PlaybackRateMode& mode) const
925 {
926 switch (mode) {
927 case SPEED_FORWARD_0_75_X:
928 return SPEED_0_75_X;
929 case SPEED_FORWARD_1_00_X:
930 return SPEED_1_00_X;
931 case SPEED_FORWARD_1_25_X:
932 return SPEED_1_25_X;
933 case SPEED_FORWARD_1_75_X:
934 return SPEED_1_75_X;
935 case SPEED_FORWARD_2_00_X:
936 return SPEED_2_00_X;
937 default:
938 MEDIA_LOG_I("unknown mode:" PUBLIC_LOG_D32 ", return default speed(SPEED_1_00_X)", mode);
939 }
940 return SPEED_1_00_X;
941 }
942
ChangeSpeedToMode(double rate) const943 PlaybackRateMode HiPlayerImpl::ChangeSpeedToMode(double rate) const
944 {
945 if (abs(rate - SPEED_0_75_X) < EPSINON) {
946 return SPEED_FORWARD_0_75_X;
947 }
948 if (abs(rate - SPEED_1_00_X) < EPSINON) {
949 return SPEED_FORWARD_1_00_X;
950 }
951 if (abs(rate - SPEED_1_25_X) < EPSINON) {
952 return SPEED_FORWARD_1_25_X;
953 }
954 if (abs(rate - SPEED_1_75_X) < EPSINON) {
955 return SPEED_FORWARD_1_75_X;
956 }
957 if (abs(rate - SPEED_2_00_X) < EPSINON) {
958 return SPEED_FORWARD_2_00_X;
959 }
960 MEDIA_LOG_I("unknown rate:" PUBLIC_LOG_F ", return default speed(SPEED_FORWARD_1_00_X)", rate);
961 return SPEED_FORWARD_1_00_X;
962 }
963
SetVideoScaleType(VideoScaleType videoScaleType)964 int32_t HiPlayerImpl::SetVideoScaleType(VideoScaleType videoScaleType)
965 {
966 return TransErrorCode(ErrorCode::ERROR_UNIMPLEMENTED);
967 }
968
SetAudioRendererInfo(const int32_t contentType,const int32_t streamUsage,const int32_t rendererFlag)969 int32_t HiPlayerImpl::SetAudioRendererInfo(const int32_t contentType, const int32_t streamUsage,
970 const int32_t rendererFlag)
971 {
972 MEDIA_LOG_I("SetAudioRendererInfo entered.");
973 Plugin::AudioRenderInfo audioRenderInfo {contentType, streamUsage, rendererFlag};
974 auto ret = audioSink_->SetParameter(static_cast<int32_t>(Tag::AUDIO_RENDER_INFO), audioRenderInfo);
975 return TransErrorCode(ret);
976 }
977
SetAudioInterruptMode(const int32_t interruptMode)978 int32_t HiPlayerImpl::SetAudioInterruptMode(const int32_t interruptMode)
979 {
980 MEDIA_LOG_I("SetAudioInterruptMode entered.");
981 auto ret = audioSink_->SetParameter(static_cast<int32_t>(Tag::AUDIO_INTERRUPT_MODE), interruptMode);
982 return TransErrorCode(ret);
983 }
984 } // namespace Media
985 } // namespace OHOS
986