1 /*
2 * Copyright (C) 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 #include "player_engine_gst_impl.h"
17
18 #include <unistd.h>
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "directory_ex.h"
22 #include "audio_system_manager.h"
23 #include "player_sinkprovider.h"
24
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayerEngineGstImpl"};
27 }
28
29 namespace OHOS {
30 namespace Media {
31 constexpr float EPSINON = 0.0001;
32 constexpr float SPEED_0_75_X = 0.75;
33 constexpr float SPEED_1_00_X = 1.00;
34 constexpr float SPEED_1_25_X = 1.25;
35 constexpr float SPEED_1_75_X = 1.75;
36 constexpr float SPEED_2_00_X = 2.00;
37 constexpr size_t MAX_URI_SIZE = 4096;
38 constexpr int32_t MSEC_PER_USEC = 1000;
39 constexpr int32_t MSEC_PER_NSEC = 1000000;
40 constexpr int32_t BUFFER_TIME_DEFAULT = 15000; // 15s
41 constexpr uint32_t INTERRUPT_EVENT_SHIFT = 8;
42 constexpr int32_t POSITION_REPORT_PER_TIMES = 10;
43
PlayerEngineGstImpl(int32_t uid,int32_t pid)44 PlayerEngineGstImpl::PlayerEngineGstImpl(int32_t uid, int32_t pid)
45 : appuid_(uid), apppid_(pid)
46 {
47 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
48 }
49
~PlayerEngineGstImpl()50 PlayerEngineGstImpl::~PlayerEngineGstImpl()
51 {
52 (void)OnReset();
53 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
54 }
55
IsFileUrl(const std::string & url) const56 bool PlayerEngineGstImpl::IsFileUrl(const std::string &url) const
57 {
58 return url.find("://") == std::string::npos || url.find("file://") == 0;
59 }
60
GetRealPath(const std::string & url,std::string & realUrlPath) const61 int32_t PlayerEngineGstImpl::GetRealPath(const std::string &url, std::string &realUrlPath) const
62 {
63 std::string fileHead = "file://";
64 std::string tempUrlPath;
65
66 if (url.find(fileHead) == 0 && url.size() > fileHead.size()) {
67 tempUrlPath = url.substr(fileHead.size());
68 } else {
69 tempUrlPath = url;
70 }
71
72 bool ret = PathToRealPath(tempUrlPath, realUrlPath);
73 CHECK_AND_RETURN_RET_LOG(ret, MSERR_OPEN_FILE_FAILED,
74 "invalid url. The Url (%{public}s) path may be invalid.", url.c_str());
75
76 if (access(realUrlPath.c_str(), R_OK) != 0) {
77 return MSERR_FILE_ACCESS_FAILED;
78 }
79
80 return MSERR_OK;
81 }
82
SetSource(const std::string & url)83 int32_t PlayerEngineGstImpl::SetSource(const std::string &url)
84 {
85 std::unique_lock<std::mutex> lock(mutex_);
86 CHECK_AND_RETURN_RET_LOG(!url.empty(), MSERR_INVALID_VAL, "input url is empty!");
87 CHECK_AND_RETURN_RET_LOG(url.length() <= MAX_URI_SIZE, MSERR_INVALID_VAL, "input url length is invalid!");
88
89 int32_t ret = MSERR_OK;
90 if (IsFileUrl(url)) {
91 std::string realUriPath;
92 ret = GetRealPath(url, realUriPath);
93 if (ret != MSERR_OK) {
94 return ret;
95 }
96 url_ = "file://" + realUriPath;
97 } else {
98 url_ = url;
99 }
100
101 MEDIA_LOGD("set player source: %{public}s", url_.c_str());
102 return ret;
103 }
104
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)105 int32_t PlayerEngineGstImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
106 {
107 std::unique_lock<std::mutex> lock(mutex_);
108 CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "input dataSrc is empty!");
109 appsrcWrap_ = GstAppsrcWrap::Create(dataSrc);
110 CHECK_AND_RETURN_RET_LOG(appsrcWrap_ != nullptr, MSERR_NO_MEMORY, "new appsrcwrap failed!");
111 return MSERR_OK;
112 }
113
SetObs(const std::weak_ptr<IPlayerEngineObs> & obs)114 int32_t PlayerEngineGstImpl::SetObs(const std::weak_ptr<IPlayerEngineObs> &obs)
115 {
116 std::unique_lock<std::mutex> lock(mutex_);
117 obs_ = obs;
118 return MSERR_OK;
119 }
120
SetVideoSurface(sptr<Surface> surface)121 int32_t PlayerEngineGstImpl::SetVideoSurface(sptr<Surface> surface)
122 {
123 std::unique_lock<std::mutex> lock(mutex_);
124 CHECK_AND_RETURN_RET_LOG(surface != nullptr, MSERR_INVALID_VAL, "surface is nullptr");
125
126 producerSurface_ = surface;
127 return MSERR_OK;
128 }
129
Prepare()130 int32_t PlayerEngineGstImpl::Prepare()
131 {
132 std::unique_lock<std::mutex> lock(mutex_);
133 MEDIA_LOGD("Prepare in");
134
135 int32_t ret = PlayBinCtrlerInit();
136 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "PlayBinCtrlerInit failed");
137
138 CHECK_AND_RETURN_RET_LOG(playBinCtrler_ != nullptr, MSERR_INVALID_VAL, "playBinCtrler_ is nullptr");
139 ret = playBinCtrler_->Prepare();
140 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Prepare failed");
141
142 // The duration of some resources without header information cannot be obtained.
143 MEDIA_LOGD("Prepared ok out");
144 return MSERR_OK;
145 }
146
PrepareAsync()147 int32_t PlayerEngineGstImpl::PrepareAsync()
148 {
149 std::unique_lock<std::mutex> lock(mutex_);
150 MEDIA_LOGD("Prepare in");
151
152 int32_t ret = PlayBinCtrlerInit();
153 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "PlayBinCtrlerInit failed");
154
155 CHECK_AND_RETURN_RET_LOG(playBinCtrler_ != nullptr, MSERR_INVALID_VAL, "playBinCtrler_ is nullptr");
156 ret = playBinCtrler_->PrepareAsync();
157 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "PrepareAsync failed");
158
159 // The duration of some resources without header information cannot be obtained.
160 MEDIA_LOGD("Prepared ok out");
161 return MSERR_OK;
162 }
163
HandleErrorMessage(const PlayBinMessage & msg)164 void PlayerEngineGstImpl::HandleErrorMessage(const PlayBinMessage &msg)
165 {
166 MEDIA_LOGE("error happended, cancel inprocessing job");
167
168 int32_t errorCode = msg.code;
169 std::string errorMsg = "Unknown Error";
170 if (msg.subType == PlayBinMsgErrorSubType::PLAYBIN_SUB_MSG_ERROR_WITH_MESSAGE) {
171 errorMsg = std::any_cast<std::string>(msg.extra);
172 }
173
174 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
175 Format format;
176 if (notifyObs != nullptr) {
177 notifyObs->OnErrorMessage(errorCode, errorMsg);
178 notifyObs->OnInfo(INFO_TYPE_STATE_CHANGE, PLAYER_STATE_ERROR, format);
179 }
180 }
181
HandleInfoMessage(const PlayBinMessage & msg)182 void PlayerEngineGstImpl::HandleInfoMessage(const PlayBinMessage &msg)
183 {
184 MEDIA_LOGI("info msg type:%{public}d, value:%{public}d", msg.type, msg.code);
185
186 int32_t status = msg.code;
187 Format format;
188 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
189 if (notifyObs != nullptr) {
190 notifyObs->OnInfo(static_cast<PlayerOnInfoType>(msg.type), status, format);
191 }
192 }
193
HandleSeekDoneMessage(const PlayBinMessage & msg)194 void PlayerEngineGstImpl::HandleSeekDoneMessage(const PlayBinMessage &msg)
195 {
196 MEDIA_LOGI("seek done, seek position = %{public}dms", msg.code);
197
198 codecCtrl_.EnhanceSeekPerformance(false);
199
200 int32_t status = msg.code;
201 Format format;
202 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
203 if (notifyObs != nullptr) {
204 notifyObs->OnInfo(INFO_TYPE_SEEKDONE, status, format);
205 }
206 }
207
HandleSpeedDoneMessage(const PlayBinMessage & msg)208 void PlayerEngineGstImpl::HandleSpeedDoneMessage(const PlayBinMessage &msg)
209 {
210 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
211 if (notifyObs != nullptr) {
212 Format format;
213 double rate = std::any_cast<double>(msg.extra);
214 PlaybackRateMode speedMode = ChangeSpeedToMode(rate);
215 notifyObs->OnInfo(INFO_TYPE_SPEEDDONE, speedMode, format);
216 }
217 }
218
HandleBufferingStart()219 void PlayerEngineGstImpl::HandleBufferingStart()
220 {
221 percent_ = 0;
222 Format format;
223 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_START), 0);
224 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
225 if (notifyObs != nullptr) {
226 notifyObs->OnInfo(INFO_TYPE_BUFFERING_UPDATE, 0, format);
227 }
228 }
229
HandleBufferingEnd()230 void PlayerEngineGstImpl::HandleBufferingEnd()
231 {
232 Format format;
233 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_END), 0);
234 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
235 if (notifyObs != nullptr) {
236 notifyObs->OnInfo(INFO_TYPE_BUFFERING_UPDATE, 0, format);
237 }
238 }
239
HandleBufferingTime(const PlayBinMessage & msg)240 void PlayerEngineGstImpl::HandleBufferingTime(const PlayBinMessage &msg)
241 {
242 std::pair<uint32_t, int64_t> bufferingTimePair = std::any_cast<std::pair<uint32_t, int64_t>>(msg.extra);
243 uint32_t mqNumId = bufferingTimePair.first;
244 uint64_t bufferingTime = bufferingTimePair.second / MSEC_PER_NSEC;
245
246 if (bufferingTime > BUFFER_TIME_DEFAULT) {
247 bufferingTime = BUFFER_TIME_DEFAULT;
248 }
249
250 mqBufferingTime_[mqNumId] = bufferingTime;
251
252 MEDIA_LOGD("ProcessBufferingTime(%{public}" PRIu64 " ms), mqNumId = %{public}u, "
253 "mqNumUsedBuffering_ = %{public}u ms", bufferingTime, mqNumId, mqNumUsedBuffering_);
254
255 if (mqBufferingTime_.size() != mqNumUsedBuffering_) {
256 return;
257 }
258
259 uint64_t mqBufferingTime = BUFFER_TIME_DEFAULT;
260 for (auto iter = mqBufferingTime_.begin(); iter != mqBufferingTime_.end(); ++iter) {
261 if (iter->second < mqBufferingTime) {
262 mqBufferingTime = iter->second;
263 }
264 }
265
266 if (bufferingTime_ != mqBufferingTime) {
267 bufferingTime_ = mqBufferingTime;
268 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
269 if (notifyObs != nullptr) {
270 Format format;
271 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_CACHED_DURATION),
272 static_cast<int32_t>(mqBufferingTime));
273 notifyObs->OnInfo(INFO_TYPE_BUFFERING_UPDATE, 0, format);
274 }
275 }
276 }
277
HandleBufferingPercent(const PlayBinMessage & msg)278 void PlayerEngineGstImpl::HandleBufferingPercent(const PlayBinMessage &msg)
279 {
280 int32_t lastPercent = percent_;
281 percent_ = msg.code;
282
283 if (lastPercent == percent_) {
284 return;
285 }
286
287 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
288 if (tempObs != nullptr) {
289 Format format;
290 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT), percent_);
291 MEDIA_LOGD("percent = (%{public}d), percent_ = %{public}d, 0x%{public}06" PRIXPTR "",
292 lastPercent, percent_, FAKE_POINTER(this));
293 tempObs->OnInfo(INFO_TYPE_BUFFERING_UPDATE, 0, format);
294 }
295 }
296
HandleBufferingUsedMqNum(const PlayBinMessage & msg)297 void PlayerEngineGstImpl::HandleBufferingUsedMqNum(const PlayBinMessage &msg)
298 {
299 mqNumUsedBuffering_ = std::any_cast<uint32_t>(msg.extra);
300 }
301
HandleVideoRenderingStart()302 void PlayerEngineGstImpl::HandleVideoRenderingStart()
303 {
304 Format format;
305 MEDIA_LOGD("video rendering start");
306 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
307 if (notifyObs != nullptr) {
308 notifyObs->OnInfo(INFO_TYPE_MESSAGE, PlayerMessageType::PLAYER_INFO_VIDEO_RENDERING_START, format);
309 }
310 }
311
HandleVideoSizeChanged(const PlayBinMessage & msg)312 void PlayerEngineGstImpl::HandleVideoSizeChanged(const PlayBinMessage &msg)
313 {
314 std::pair<int32_t, int32_t> resolution = std::any_cast<std::pair<int32_t, int32_t>>(msg.extra);
315 Format format;
316 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_WIDTH), resolution.first);
317 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_HEIGHT), resolution.second);
318 MEDIA_LOGD("video size changed, width = %{public}d, height = %{public}d", resolution.first, resolution.second);
319 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
320 if (notifyObs != nullptr) {
321 notifyObs->OnInfo(INFO_TYPE_RESOLUTION_CHANGE, 0, format);
322 }
323 videoWidth_ = resolution.first;
324 videoHeight_ = resolution.second;
325 }
326
HandleBitRateCollect(const PlayBinMessage & msg)327 void PlayerEngineGstImpl::HandleBitRateCollect(const PlayBinMessage &msg)
328 {
329 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
330 if (notifyObs != nullptr) {
331 notifyObs->OnInfo(INFO_TYPE_BITRATE_COLLECT, 0, std::any_cast<Format>(msg.extra));
332 }
333 }
334
HandleSubTypeMessage(const PlayBinMessage & msg)335 void PlayerEngineGstImpl::HandleSubTypeMessage(const PlayBinMessage &msg)
336 {
337 switch (msg.subType) {
338 case PLAYBIN_SUB_MSG_BUFFERING_START: {
339 HandleBufferingStart();
340 break;
341 }
342 case PLAYBIN_SUB_MSG_BUFFERING_END: {
343 HandleBufferingEnd();
344 break;
345 }
346 case PLAYBIN_SUB_MSG_BUFFERING_TIME: {
347 HandleBufferingTime(msg);
348 break;
349 }
350 case PLAYBIN_SUB_MSG_BUFFERING_PERCENT: {
351 HandleBufferingPercent(msg);
352 break;
353 }
354 case PLAYBIN_SUB_MSG_BUFFERING_USED_MQ_NUM: {
355 HandleBufferingUsedMqNum(msg);
356 break;
357 }
358 case PLAYBIN_SUB_MSG_VIDEO_RENDERING_START: {
359 HandleVideoRenderingStart();
360 break;
361 }
362 case PLAYBIN_SUB_MSG_VIDEO_SIZE_CHANGED: {
363 HandleVideoSizeChanged(msg);
364 break;
365 }
366 case PLAYBIN_SUB_MSG_BITRATE_COLLECT: {
367 HandleBitRateCollect(msg);
368 break;
369 }
370 default: {
371 break;
372 }
373 }
374 }
375
HandleAudioMessage(const PlayBinMessage & msg)376 void PlayerEngineGstImpl::HandleAudioMessage(const PlayBinMessage &msg)
377 {
378 switch (msg.subType) {
379 case PLAYBIN_MSG_INTERRUPT_EVENT: {
380 HandleInterruptMessage(msg);
381 break;
382 }
383 case PLAYBIN_MSG_AUDIO_STATE_EVENT: {
384 HandleAudioStateMessage(msg);
385 break;
386 }
387 default: {
388 break;
389 }
390 }
391 }
392
HandleAudioStateMessage(const PlayBinMessage & msg)393 void PlayerEngineGstImpl::HandleAudioStateMessage(const PlayBinMessage &msg)
394 {
395 int32_t value = std::any_cast<int32_t>(msg.extra);
396 MEDIA_LOGI("HandleAudioStateMessage:%{public}d", value);
397
398 if (value == AudioStandard::RendererState::RENDERER_PAUSED) {
399 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
400 Format format;
401 if (notifyObs != nullptr) {
402 notifyObs->OnInfo(INFO_TYPE_STATE_CHANGE_BY_AUDIO, PlayerStates::PLAYER_PAUSED, format);
403 }
404 }
405 }
406
HandleInterruptMessage(const PlayBinMessage & msg)407 void PlayerEngineGstImpl::HandleInterruptMessage(const PlayBinMessage &msg)
408 {
409 MEDIA_LOGI("Audio interrupt event in");
410 uint32_t value = std::any_cast<uint32_t>(msg.extra);
411 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
412 if (notifyObs != nullptr) {
413 Format format;
414 int32_t hintType = value & 0x000000FF;
415 int32_t forceType = (value >> INTERRUPT_EVENT_SHIFT) & 0x000000FF;
416 int32_t eventType = value >> (INTERRUPT_EVENT_SHIFT * 2);
417 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventType);
418 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceType);
419 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintType);
420 notifyObs->OnInfo(INFO_TYPE_INTERRUPT_EVENT, 0, format);
421 }
422 }
423
HandlePositionUpdateMessage(const PlayBinMessage & msg)424 void PlayerEngineGstImpl::HandlePositionUpdateMessage(const PlayBinMessage &msg)
425 {
426 currentTime_ = msg.code;
427 int32_t duration = std::any_cast<int32_t>(msg.extra);
428 MEDIA_LOGD("update position %{public}d ms, duration %{public}d ms", currentTime_, duration);
429
430 if (duration != duration_) {
431 duration_ = duration;
432 Format format;
433 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
434 if (notifyObs != nullptr) {
435 notifyObs->OnInfo(INFO_TYPE_DURATION_UPDATE, duration_, format);
436 }
437 }
438
439 // 10: report once at 1000ms
440 if (currentTimeOnInfoCnt_ % POSITION_REPORT_PER_TIMES == 0 ||
441 msg.subType == PLAYBIN_SUB_MSG_POSITION_UPDATE_FORCE) {
442 Format format;
443 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
444 if (notifyObs != nullptr) {
445 notifyObs->OnInfo(INFO_TYPE_POSITION_UPDATE, currentTime_, format);
446 }
447 if (currentTimeOnInfoCnt_ % POSITION_REPORT_PER_TIMES == 0) {
448 currentTimeOnInfoCnt_ = 0;
449 }
450 }
451 if (msg.subType == PLAYBIN_SUB_MSG_POSITION_UPDATE_UNFORCE) {
452 currentTimeOnInfoCnt_++;
453 }
454 }
455
456 using MsgNotifyFunc = std::function<void(const PlayBinMessage&)>;
457
OnNotifyMessage(const PlayBinMessage & msg)458 void PlayerEngineGstImpl::OnNotifyMessage(const PlayBinMessage &msg)
459 {
460 const std::unordered_map<int32_t, MsgNotifyFunc> MSG_NOTIFY_FUNC_TABLE = {
461 { PLAYBIN_MSG_ERROR, std::bind(&PlayerEngineGstImpl::HandleErrorMessage, this, std::placeholders::_1) },
462 { PLAYBIN_MSG_SEEKDONE, std::bind(&PlayerEngineGstImpl::HandleSeekDoneMessage, this, std::placeholders::_1) },
463 { PLAYBIN_MSG_SPEEDDONE, std::bind(&PlayerEngineGstImpl::HandleSpeedDoneMessage, this, std::placeholders::_1) },
464 { PLAYBIN_MSG_BITRATEDONE, std::bind(&PlayerEngineGstImpl::HandleInfoMessage, this, std::placeholders::_1)},
465 { PLAYBIN_MSG_EOS, std::bind(&PlayerEngineGstImpl::HandleInfoMessage, this, std::placeholders::_1) },
466 { PLAYBIN_MSG_STATE_CHANGE, std::bind(&PlayerEngineGstImpl::HandleInfoMessage, this, std::placeholders::_1) },
467 { PLAYBIN_MSG_SUBTYPE, std::bind(&PlayerEngineGstImpl::HandleSubTypeMessage, this, std::placeholders::_1) },
468 { PLAYBIN_MSG_AUDIO_SINK, std::bind(&PlayerEngineGstImpl::HandleAudioMessage, this, std::placeholders::_1) },
469 { PLAYBIN_MSG_POSITION_UPDATE, std::bind(&PlayerEngineGstImpl::HandlePositionUpdateMessage, this,
470 std::placeholders::_1) },
471 };
472 if (MSG_NOTIFY_FUNC_TABLE.count(msg.type) != 0) {
473 MSG_NOTIFY_FUNC_TABLE.at(msg.type)(msg);
474 }
475 }
476
PlayBinCtrlerInit()477 int32_t PlayerEngineGstImpl::PlayBinCtrlerInit()
478 {
479 if (playBinCtrler_) {
480 return MSERR_OK;
481 }
482
483 MEDIA_LOGD("PlayBinCtrlerInit in");
484 int ret = PlayBinCtrlerPrepare();
485 if (ret != MSERR_OK) {
486 MEDIA_LOGE("PlayBinCtrlerPrepare failed");
487 PlayBinCtrlerDeInit();
488 return MSERR_INVALID_VAL;
489 }
490
491 MEDIA_LOGD("PlayBinCtrlerInit out");
492 return MSERR_OK;
493 }
494
PlayBinCtrlerDeInit()495 void PlayerEngineGstImpl::PlayBinCtrlerDeInit()
496 {
497 url_.clear();
498 useSoftDec_ = false;
499 appsrcWrap_ = nullptr;
500
501 if (playBinCtrler_ != nullptr) {
502 playBinCtrler_->SetElemSetupListener(nullptr);
503 playBinCtrler_->SetElemUnSetupListener(nullptr);
504 playBinCtrler_->SetAutoPlugSortListener(nullptr);
505 playBinCtrler_ = nullptr;
506 }
507
508 {
509 std::unique_lock<std::mutex> lk(trackParseMutex_);
510 trackParse_ = nullptr;
511 sinkProvider_ = nullptr;
512 }
513 }
514
PlayBinCtrlerPrepare()515 int32_t PlayerEngineGstImpl::PlayBinCtrlerPrepare()
516 {
517 uint8_t renderMode = IPlayBinCtrler::PlayBinRenderMode::DEFAULT_RENDER;
518 auto notifier = std::bind(&PlayerEngineGstImpl::OnNotifyMessage, this, std::placeholders::_1);
519
520 {
521 std::unique_lock<std::mutex> lk(trackParseMutex_);
522 sinkProvider_ = std::make_shared<PlayerSinkProvider>(producerSurface_);
523 sinkProvider_->SetAppInfo(appuid_, apppid_);
524 }
525
526 IPlayBinCtrler::PlayBinCreateParam createParam = {
527 static_cast<IPlayBinCtrler::PlayBinRenderMode>(renderMode), notifier, sinkProvider_
528 };
529 playBinCtrler_ = IPlayBinCtrler::Create(IPlayBinCtrler::PlayBinKind::PLAYBIN2, createParam);
530 CHECK_AND_RETURN_RET_LOG(playBinCtrler_ != nullptr, MSERR_INVALID_VAL, "playBinCtrler_ is nullptr");
531
532 int32_t ret;
533 if (appsrcWrap_ == nullptr) {
534 ret = playBinCtrler_->SetSource(url_);
535 } else {
536 ret = playBinCtrler_->SetSource(appsrcWrap_);
537 }
538 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "SetSource failed");
539
540 ret = SetVideoScaleType(videoScaleType_);
541 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "SetVideoScaleType failed");
542
543 ret = SetAudioRendererInfo(contentType_, streamUsage_, rendererFlag_);
544 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "SetAudioRendererInfo failed");
545
546 auto setupListener = std::bind(&PlayerEngineGstImpl::OnNotifyElemSetup, this, std::placeholders::_1);
547 playBinCtrler_->SetElemSetupListener(setupListener);
548
549 auto unSetupListener = std::bind(&PlayerEngineGstImpl::OnNotifyElemUnSetup, this, std::placeholders::_1);
550 playBinCtrler_->SetElemUnSetupListener(unSetupListener);
551
552 auto autoPlugSortListener = std::bind(&PlayerEngineGstImpl::OnNotifyAutoPlugSort, this, std::placeholders::_1);
553 playBinCtrler_->SetAutoPlugSortListener(autoPlugSortListener);
554
555 {
556 std::unique_lock<std::mutex> lk(trackParseMutex_);
557 trackParse_ = PlayerTrackParse::Create();
558 if (trackParse_ == nullptr) {
559 MEDIA_LOGE("creat track parse failed");
560 }
561 }
562
563 return MSERR_OK;
564 }
565
Play()566 int32_t PlayerEngineGstImpl::Play()
567 {
568 std::unique_lock<std::mutex> lock(mutex_);
569 CHECK_AND_RETURN_RET_LOG(playBinCtrler_ != nullptr, MSERR_INVALID_OPERATION, "playBinCtrler_ is nullptr");
570
571 MEDIA_LOGI("Play in");
572 playBinCtrler_->Play();
573 return MSERR_OK;
574 }
575
Pause()576 int32_t PlayerEngineGstImpl::Pause()
577 {
578 std::unique_lock<std::mutex> lock(mutex_);
579 CHECK_AND_RETURN_RET_LOG(playBinCtrler_ != nullptr, MSERR_INVALID_OPERATION, "playBinCtrler_ is nullptr");
580
581 MEDIA_LOGI("Pause in");
582 (void)playBinCtrler_->Pause();
583 return MSERR_OK;
584 }
585
GetCurrentTime(int32_t & currentTime)586 int32_t PlayerEngineGstImpl::GetCurrentTime(int32_t ¤tTime)
587 {
588 currentTime = currentTime_;
589 MEDIA_LOGD("Time in milliseconds: %{public}d", currentTime);
590 return MSERR_OK;
591 }
592
GetVideoTrackInfo(std::vector<Format> & videoTrack)593 int32_t PlayerEngineGstImpl::GetVideoTrackInfo(std::vector<Format> &videoTrack)
594 {
595 CHECK_AND_RETURN_RET_LOG(trackParse_ != nullptr, MSERR_INVALID_OPERATION, "trackParse_ is nullptr");
596
597 return trackParse_->GetVideoTrackInfo(videoTrack);
598 }
599
GetAudioTrackInfo(std::vector<Format> & audioTrack)600 int32_t PlayerEngineGstImpl::GetAudioTrackInfo(std::vector<Format> &audioTrack)
601 {
602 CHECK_AND_RETURN_RET_LOG(trackParse_ != nullptr, MSERR_INVALID_OPERATION, "trackParse_ is nullptr");
603
604 return trackParse_->GetAudioTrackInfo(audioTrack);
605 }
606
GetVideoWidth()607 int32_t PlayerEngineGstImpl::GetVideoWidth()
608 {
609 return videoWidth_;
610 }
611
GetVideoHeight()612 int32_t PlayerEngineGstImpl::GetVideoHeight()
613 {
614 return videoHeight_;
615 }
616
GetDuration(int32_t & duration)617 int32_t PlayerEngineGstImpl::GetDuration(int32_t &duration)
618 {
619 duration = duration_;
620 MEDIA_LOGD("Duration in milliseconds: %{public}d", duration);
621 return MSERR_OK;
622 }
623
ChangeModeToSpeed(const PlaybackRateMode & mode) const624 double PlayerEngineGstImpl::ChangeModeToSpeed(const PlaybackRateMode &mode) const
625 {
626 switch (mode) {
627 case SPEED_FORWARD_0_75_X:
628 return SPEED_0_75_X;
629 case SPEED_FORWARD_1_00_X:
630 return SPEED_1_00_X;
631 case SPEED_FORWARD_1_25_X:
632 return SPEED_1_25_X;
633 case SPEED_FORWARD_1_75_X:
634 return SPEED_1_75_X;
635 case SPEED_FORWARD_2_00_X:
636 return SPEED_2_00_X;
637 default:
638 MEDIA_LOGW("unknown mode:%{public}d, return default speed(SPEED_1_00_X)", mode);
639 }
640
641 return SPEED_1_00_X;
642 }
643
ChangeSpeedToMode(double rate) const644 PlaybackRateMode PlayerEngineGstImpl::ChangeSpeedToMode(double rate) const
645 {
646 if (abs(rate - SPEED_0_75_X) < EPSINON) {
647 return SPEED_FORWARD_0_75_X;
648 }
649 if (abs(rate - SPEED_1_00_X) < EPSINON) {
650 return SPEED_FORWARD_1_00_X;
651 }
652 if (abs(rate - SPEED_1_25_X) < EPSINON) {
653 return SPEED_FORWARD_1_25_X;
654 }
655 if (abs(rate - SPEED_1_75_X) < EPSINON) {
656 return SPEED_FORWARD_1_75_X;
657 }
658 if (abs(rate - SPEED_2_00_X) < EPSINON) {
659 return SPEED_FORWARD_2_00_X;
660 }
661
662 MEDIA_LOGW("unknown rate:%{public}lf, return default speed(SPEED_FORWARD_1_00_X)", rate);
663
664 return SPEED_FORWARD_1_00_X;
665 }
666
SetPlaybackSpeed(PlaybackRateMode mode)667 int32_t PlayerEngineGstImpl::SetPlaybackSpeed(PlaybackRateMode mode)
668 {
669 std::unique_lock<std::mutex> lock(mutex_);
670 if (playBinCtrler_ != nullptr) {
671 double rate = ChangeModeToSpeed(mode);
672 return playBinCtrler_->SetRate(rate);
673 }
674 return MSERR_OK;
675 }
676
GetPlaybackSpeed(PlaybackRateMode & mode)677 int32_t PlayerEngineGstImpl::GetPlaybackSpeed(PlaybackRateMode &mode)
678 {
679 std::unique_lock<std::mutex> lock(mutex_);
680 if (playBinCtrler_ != nullptr) {
681 double rate = playBinCtrler_->GetRate();
682 mode = ChangeSpeedToMode(rate);
683 }
684 return MSERR_OK;
685 }
686
SetLooping(bool loop)687 int32_t PlayerEngineGstImpl::SetLooping(bool loop)
688 {
689 if (playBinCtrler_ != nullptr) {
690 MEDIA_LOGD("SetLooping in");
691 return playBinCtrler_->SetLoop(loop);
692 }
693 return MSERR_OK;
694 }
695
SetParameter(const Format & param)696 int32_t PlayerEngineGstImpl::SetParameter(const Format ¶m)
697 {
698 if (param.ContainKey(PlayerKeys::VIDEO_SCALE_TYPE)) {
699 int32_t videoScaleType = 0;
700 param.GetIntValue(PlayerKeys::VIDEO_SCALE_TYPE, videoScaleType);
701 return SetVideoScaleType(VideoScaleType(videoScaleType));
702 }
703 if (param.ContainKey(PlayerKeys::CONTENT_TYPE) && param.ContainKey(PlayerKeys::STREAM_USAGE)) {
704 param.GetIntValue(PlayerKeys::CONTENT_TYPE, contentType_);
705 param.GetIntValue(PlayerKeys::STREAM_USAGE, streamUsage_);
706 param.GetIntValue(PlayerKeys::RENDERER_FLAG, rendererFlag_);
707 return SetAudioRendererInfo(contentType_, streamUsage_, rendererFlag_);
708 }
709 if (param.ContainKey(PlayerKeys::AUDIO_INTERRUPT_MODE)) {
710 int32_t interruptMode = 0;
711 param.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_MODE, interruptMode);
712 return SetAudioInterruptMode(interruptMode);
713 }
714 return MSERR_OK;
715 }
716
Stop()717 int32_t PlayerEngineGstImpl::Stop()
718 {
719 std::unique_lock<std::mutex> lock(mutex_);
720 CHECK_AND_RETURN_RET_LOG(playBinCtrler_ != nullptr, MSERR_INVALID_OPERATION, "playBinCtrler_ is nullptr");
721
722 MEDIA_LOGD("Stop in");
723 if (trackParse_ != nullptr) {
724 trackParse_->Stop();
725 }
726 playBinCtrler_->Stop(true);
727 return MSERR_OK;
728 }
729
Reset()730 int32_t PlayerEngineGstImpl::Reset()
731 {
732 MEDIA_LOGD("Reset in");
733 OnReset();
734 return MSERR_OK;
735 }
736
OnReset()737 void PlayerEngineGstImpl::OnReset()
738 {
739 if (taskQueue_ != nullptr) {
740 (void)taskQueue_->Stop();
741 }
742
743 std::unique_lock<std::mutex> lock(mutex_);
744 PlayBinCtrlerDeInit();
745 }
746
Seek(int32_t mSeconds,PlayerSeekMode mode)747 int32_t PlayerEngineGstImpl::Seek(int32_t mSeconds, PlayerSeekMode mode)
748 {
749 std::unique_lock<std::mutex> lock(mutex_);
750 CHECK_AND_RETURN_RET_LOG(playBinCtrler_ != nullptr, MSERR_INVALID_OPERATION, "playBinCtrler_ is nullptr");
751 MEDIA_LOGI("Seek in %{public}dms", mSeconds);
752
753 if (playBinCtrler_->QueryPosition() == mSeconds) {
754 MEDIA_LOGW("current time same to seek time, invalid seek");
755 Format format;
756 std::shared_ptr<IPlayerEngineObs> notifyObs = obs_.lock();
757 if (notifyObs != nullptr) {
758 notifyObs->OnInfo(INFO_TYPE_SEEKDONE, mSeconds, format);
759 }
760 return MSERR_OK;
761 }
762
763 codecCtrl_.EnhanceSeekPerformance(true);
764
765 int64_t position = static_cast<int64_t>(mSeconds) * MSEC_PER_USEC;
766 return playBinCtrler_->Seek(position, mode);
767 }
768
SetVolume(float leftVolume,float rightVolume)769 int32_t PlayerEngineGstImpl::SetVolume(float leftVolume, float rightVolume)
770 {
771 std::unique_lock<std::mutex> lock(mutex_);
772 if (playBinCtrler_ != nullptr) {
773 MEDIA_LOGD("SetVolume in");
774 playBinCtrler_->SetVolume(leftVolume, rightVolume);
775 }
776 return MSERR_OK;
777 }
778
SelectBitRate(uint32_t bitRate)779 int32_t PlayerEngineGstImpl::SelectBitRate(uint32_t bitRate)
780 {
781 std::unique_lock<std::mutex> lock(mutex_);
782 if (playBinCtrler_ != nullptr) {
783 MEDIA_LOGD("SelectBitRate in");
784 return playBinCtrler_->SelectBitRate(bitRate);
785 }
786 return MSERR_INVALID_OPERATION;
787 }
788
SetVideoScaleType(VideoScaleType videoScaleType)789 int32_t PlayerEngineGstImpl::SetVideoScaleType(VideoScaleType videoScaleType)
790 {
791 std::unique_lock<std::mutex> lock(mutex_, std::try_to_lock);
792 if (sinkProvider_ != nullptr) {
793 MEDIA_LOGD("SetVideoScaleType in");
794 sinkProvider_->SetVideoScaleType(static_cast<uint32_t>(videoScaleType));
795 }
796 videoScaleType_ = videoScaleType;
797 return MSERR_OK;
798 }
799
SetAudioRendererInfo(const int32_t contentType,const int32_t streamUsage,const int32_t rendererFlag)800 int32_t PlayerEngineGstImpl::SetAudioRendererInfo(const int32_t contentType,
801 const int32_t streamUsage, const int32_t rendererFlag)
802 {
803 std::unique_lock<std::mutex> lock(mutex_, std::try_to_lock);
804 contentType_ = contentType;
805 streamUsage_ = streamUsage;
806 rendererFlag_ = rendererFlag;
807 if (playBinCtrler_ != nullptr) {
808 MEDIA_LOGD("SetAudioRendererInfo in");
809 uint32_t rendererInfo(0);
810 rendererInfo |= (contentType | (static_cast<uint32_t>(streamUsage) <<
811 AudioStandard::RENDERER_STREAM_USAGE_SHIFT));
812 playBinCtrler_->SetAudioRendererInfo(rendererInfo, rendererFlag);
813 }
814 return MSERR_OK;
815 }
816
SetAudioInterruptMode(const int32_t interruptMode)817 int32_t PlayerEngineGstImpl::SetAudioInterruptMode(const int32_t interruptMode)
818 {
819 std::unique_lock<std::mutex> lock(mutex_);
820 if (playBinCtrler_ != nullptr) {
821 MEDIA_LOGD("SetAudioInterruptMode in");
822 playBinCtrler_->SetAudioInterruptMode(interruptMode);
823 }
824 return MSERR_OK;
825 }
826
OnNotifyAutoPlugSort(GValueArray & factories)827 GValueArray *PlayerEngineGstImpl::OnNotifyAutoPlugSort(GValueArray &factories)
828 {
829 if (isPlaySinkFlagsSet_) {
830 return nullptr;
831 }
832
833 if (useSoftDec_) {
834 GValueArray *result = g_value_array_new(factories.n_values);
835
836 for (uint32_t i = 0; i < factories.n_values; i++) {
837 GstElementFactory *factory =
838 static_cast<GstElementFactory *>(g_value_get_object(g_value_array_get_nth(&factories, i)));
839 if (strstr(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS),
840 "Codec/Decoder/Video/Hardware")) {
841 MEDIA_LOGD("set remove hardware codec plugins from pipeline");
842 continue;
843 }
844 GValue val = G_VALUE_INIT;
845 g_value_init(&val, G_TYPE_OBJECT);
846 g_value_set_object(&val, factory);
847 result = g_value_array_append(result, &val);
848 g_value_unset(&val);
849 }
850 return result;
851 } else {
852 for (uint32_t i = 0; i < factories.n_values; i++) {
853 GstElementFactory *factory =
854 static_cast<GstElementFactory *>(g_value_get_object(g_value_array_get_nth(&factories, i)));
855 if (strstr(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS),
856 "Codec/Decoder/Video/Hardware")) {
857 MEDIA_LOGD("set remove GstPlaySinkVideoConvert plugins from pipeline");
858 playBinCtrler_->RemoveGstPlaySinkVideoConvertPlugin();
859 isPlaySinkFlagsSet_ = true;
860 break;
861 }
862 }
863 }
864
865 return nullptr;
866 }
867
OnNotifyElemSetup(GstElement & elem)868 void PlayerEngineGstImpl::OnNotifyElemSetup(GstElement &elem)
869 {
870 std::unique_lock<std::mutex> lock(trackParseMutex_);
871
872 const gchar *metadata = gst_element_get_metadata(&elem, GST_ELEMENT_METADATA_KLASS);
873 CHECK_AND_RETURN_LOG(metadata != nullptr, "gst_element_get_metadata return nullptr");
874
875 MEDIA_LOGD("get element_name %{public}s, get metadata %{public}s", GST_ELEMENT_NAME(&elem), metadata);
876 std::string metaStr(metadata);
877
878 if (trackParse_ != nullptr && trackParse_->GetDemuxerElementFind() == false) {
879 if (metaStr.find("Codec/Demuxer") != std::string::npos) {
880 trackParse_->SetUpDemuxerElementCb(elem);
881 trackParse_->SetDemuxerElementFind(true);
882 } else if (metaStr.find("Codec/Parser") != std::string::npos) {
883 trackParse_->SetUpParseElementCb(elem);
884 trackParse_->SetDemuxerElementFind(true);
885 }
886 }
887
888 if (metaStr.find("Codec/Decoder/Video") != std::string::npos || metaStr.find("Sink/Video") != std::string::npos) {
889 if (producerSurface_ != nullptr) {
890 CHECK_AND_RETURN_LOG(sinkProvider_ != nullptr, "sinkProvider_ is nullptr");
891 GstElement *videoSink = sinkProvider_->GetVideoSink();
892 CHECK_AND_RETURN_LOG(videoSink != nullptr, "videoSink is nullptr");
893 codecCtrl_.DetectCodecSetup(metaStr, &elem, videoSink);
894 auto notifier = std::bind(&PlayerEngineGstImpl::OnCapsFixError, this);
895 codecCtrl_.SetCapsFixErrorCb(notifier);
896 }
897 }
898 }
899
OnNotifyElemUnSetup(GstElement & elem)900 void PlayerEngineGstImpl::OnNotifyElemUnSetup(GstElement &elem)
901 {
902 std::unique_lock<std::mutex> lock(trackParseMutex_);
903
904 const gchar *metadata = gst_element_get_metadata(&elem, GST_ELEMENT_METADATA_KLASS);
905 CHECK_AND_RETURN_LOG(metadata != nullptr, "gst_element_get_metadata return nullptr");
906
907 MEDIA_LOGD("get element_name %{public}s, get metadata %{public}s", GST_ELEMENT_NAME(&elem), metadata);
908 std::string metaStr(metadata);
909
910 if (metaStr.find("Codec/Decoder/Video") != std::string::npos) {
911 if (producerSurface_ != nullptr) {
912 CHECK_AND_RETURN_LOG(sinkProvider_ != nullptr, "sinkProvider_ is nullptr");
913 GstElement *videoSink = sinkProvider_->GetVideoSink();
914 CHECK_AND_RETURN_LOG(videoSink != nullptr, "videoSink is nullptr");
915 codecCtrl_.DetectCodecUnSetup(&elem, videoSink);
916 }
917 }
918 }
919
OnCapsFixError()920 void PlayerEngineGstImpl::OnCapsFixError()
921 {
922 MEDIA_LOGD("OnCapsFixError in");
923
924 if (taskQueue_ == nullptr) {
925 taskQueue_ = std::make_unique<TaskQueue>("reset-playbin-task");
926 int32_t ret = taskQueue_->Start();
927 CHECK_AND_RETURN_LOG(ret == MSERR_OK, "task queue start failed");
928 }
929
930 useSoftDec_ = true;
931 auto resetTask = std::make_shared<TaskHandler<void>>([this]() {
932 ResetPlaybinToSoftDec();
933 });
934 (void)taskQueue_->EnqueueTask(resetTask);
935 }
936
937 // fix video with small resolution cannot play in hardware decoding
938 // reset pipeline to use software decoder
ResetPlaybinToSoftDec()939 void PlayerEngineGstImpl::ResetPlaybinToSoftDec()
940 {
941 std::unique_lock<std::mutex> lock(mutex_);
942 CHECK_AND_RETURN_LOG(playBinCtrler_ != nullptr, "playBinCtrler_ is nullptr");
943
944 MEDIA_LOGD("ResetPlaybinToSoftDec in");
945 isPlaySinkFlagsSet_ = false;
946
947 if (playBinCtrler_ != nullptr) {
948 playBinCtrler_->SetNotifier(nullptr);
949 playBinCtrler_->Stop(false);
950 playBinCtrler_->SetElemSetupListener(nullptr);
951 playBinCtrler_->SetElemUnSetupListener(nullptr);
952 playBinCtrler_->SetAutoPlugSortListener(nullptr);
953 playBinCtrler_ = nullptr;
954 }
955
956 {
957 std::unique_lock<std::mutex> lk(trackParseMutex_);
958 trackParse_ = nullptr;
959 sinkProvider_ = nullptr;
960 }
961
962 lock.unlock();
963 PrepareAsync();
964 }
965 } // namespace Media
966 } // namespace OHOS
967