• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &currentTime)
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 &param)
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