• 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 "playbin_ctrler_base.h"
17 #include <gst/playback/gstplay-enum.h>
18 #include "nocopyable.h"
19 #include "string_ex.h"
20 #include "media_errors.h"
21 #include "media_log.h"
22 #include "player.h"
23 #include "format.h"
24 #include "uri_helper.h"
25 #include "scope_guard.h"
26 #include "playbin_state.h"
27 #include "gst_utils.h"
28 #include "media_dfx.h"
29 #include "player_xcollie.h"
30 
31 namespace {
32     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayBinCtrlerBase"};
33     constexpr uint64_t RING_BUFFER_MAX_SIZE = 5242880; // 5 * 1024 * 1024
34     constexpr int32_t PLAYBIN_QUEUE_MAX_SIZE = 100 * 1024 * 1024; // 100 * 1024 * 1024 Bytes
35     constexpr uint64_t BUFFER_DURATION = 15000000000; // 15s
36     constexpr int32_t BUFFER_LOW_PERCENT_DEFAULT = 1;
37     constexpr int32_t BUFFER_HIGH_PERCENT_DEFAULT = 4;
38     constexpr int32_t BUFFER_PERCENT_THRESHOLD = 100;
39     constexpr uint32_t HTTP_TIME_OUT_DEFAULT = 15; // 15s
40     constexpr int32_t NANO_SEC_PER_USEC = 1000;
41     constexpr int32_t USEC_PER_MSEC = 1000;
42     constexpr double DEFAULT_RATE = 1.0;
43     constexpr uint32_t INTERRUPT_EVENT_SHIFT = 8;
44 }
45 
46 namespace OHOS {
47 namespace Media {
48 static const std::unordered_map<int32_t, int32_t> SEEK_OPTION_TO_GST_SEEK_FLAGS = {
49     {
50         IPlayBinCtrler::PlayBinSeekMode::PREV_SYNC,
51         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
52     },
53     {
54         IPlayBinCtrler::PlayBinSeekMode::NEXT_SYNC,
55         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_AFTER,
56     },
57     {
58         IPlayBinCtrler::PlayBinSeekMode::CLOSET_SYNC,
59         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_NEAREST,
60     },
61     {
62         IPlayBinCtrler::PlayBinSeekMode::CLOSET,
63         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE,
64     }
65 };
66 
67 using PlayBinCtrlerWrapper = ThizWrapper<PlayBinCtrlerBase>;
68 
ElementSetup(const GstElement * playbin,GstElement * elem,gpointer userData)69 void PlayBinCtrlerBase::ElementSetup(const GstElement *playbin, GstElement *elem, gpointer userData)
70 {
71     (void)playbin;
72     if (elem == nullptr || userData == nullptr) {
73         return;
74     }
75 
76     auto thizStrong = PlayBinCtrlerWrapper::TakeStrongThiz(userData);
77     if (thizStrong != nullptr) {
78         return thizStrong->OnElementSetup(*elem);
79     }
80 }
81 
ElementUnSetup(const GstElement * playbin,GstElement * subbin,GstElement * child,gpointer userData)82 void PlayBinCtrlerBase::ElementUnSetup(const GstElement *playbin, GstElement *subbin,
83     GstElement *child, gpointer userData)
84 {
85     (void)playbin;
86     (void)subbin;
87     if (child == nullptr || userData == nullptr) {
88         return;
89     }
90 
91     auto thizStrong = PlayBinCtrlerWrapper::TakeStrongThiz(userData);
92     if (thizStrong != nullptr) {
93         return thizStrong->OnElementUnSetup(*child);
94     }
95 }
96 
SourceSetup(const GstElement * playbin,GstElement * elem,gpointer userData)97 void PlayBinCtrlerBase::SourceSetup(const GstElement *playbin, GstElement *elem, gpointer userData)
98 {
99     if (elem == nullptr || userData == nullptr) {
100         return;
101     }
102 
103     auto thizStrong = PlayBinCtrlerWrapper::TakeStrongThiz(userData);
104     if (thizStrong != nullptr) {
105         return thizStrong->OnSourceSetup(playbin, elem, thizStrong);
106     }
107 }
108 
PlayBinCtrlerBase(const PlayBinCreateParam & createParam)109 PlayBinCtrlerBase::PlayBinCtrlerBase(const PlayBinCreateParam &createParam)
110     : renderMode_(createParam.renderMode),
111     notifier_(createParam.notifier),
112     sinkProvider_(createParam.sinkProvider)
113 {
114     MEDIA_LOGD("enter ctor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
115 }
116 
~PlayBinCtrlerBase()117 PlayBinCtrlerBase::~PlayBinCtrlerBase()
118 {
119     MEDIA_LOGD("enter dtor, instance: 0x%{public}06" PRIXPTR "", FAKE_POINTER(this));
120     if (Reset() == MSERR_OK) {
121         sinkProvider_ = nullptr;
122         notifier_ = nullptr;
123     }
124 }
125 
Init()126 int32_t PlayBinCtrlerBase::Init()
127 {
128     CHECK_AND_RETURN_RET_LOG(sinkProvider_ != nullptr, MSERR_INVALID_VAL, "sinkprovider is nullptr");
129 
130     idleState_ = std::make_shared<IdleState>(*this);
131     initializedState_ = std::make_shared<InitializedState>(*this);
132     preparingState_ = std::make_shared<PreparingState>(*this);
133     preparedState_ = std::make_shared<PreparedState>(*this);
134     playingState_ = std::make_shared<PlayingState>(*this);
135     pausedState_ = std::make_shared<PausedState>(*this);
136     stoppingState_ = std::make_shared<StoppingState>(*this);
137     stoppedState_ = std::make_shared<StoppedState>(*this);
138     playbackCompletedState_ = std::make_shared<PlaybackCompletedState>(*this);
139 
140     rate_ = DEFAULT_RATE;
141 
142     ChangeState(idleState_);
143 
144     msgQueue_ = std::make_unique<TaskQueue>("PlaybinCtrl");
145     int32_t ret = msgQueue_->Start();
146     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "msgqueue start failed");
147 
148     return ret;
149 }
150 
IsLiveSource() const151 bool PlayBinCtrlerBase::IsLiveSource() const
152 {
153     if (appsrcWrap_ != nullptr && appsrcWrap_->IsLiveMode()) {
154         return true;
155     }
156     return false;
157 }
158 
SetSource(const std::string & url)159 int32_t PlayBinCtrlerBase::SetSource(const std::string &url)
160 {
161     std::unique_lock<std::mutex> lock(mutex_);
162     uri_ = url;
163     if (url.find("http") == 0 || url.find("https") == 0) {
164         isNetWorkPlay_ = true;
165     }
166 
167     MEDIA_LOGI("Set source: %{public}s", url.c_str());
168     return MSERR_OK;
169 }
170 
SetSource(const std::shared_ptr<GstAppsrcWrap> & appsrcWrap)171 int32_t PlayBinCtrlerBase::SetSource(const std::shared_ptr<GstAppsrcWrap> &appsrcWrap)
172 {
173     std::unique_lock<std::mutex> lock(mutex_);
174     appsrcWrap_ = appsrcWrap;
175     return MSERR_OK;
176 }
177 
Prepare()178 int32_t PlayBinCtrlerBase::Prepare()
179 {
180     MEDIA_LOGD("enter");
181 
182     std::unique_lock<std::mutex> lock(mutex_);
183 
184     int32_t ret = PrepareAsyncInternal();
185     CHECK_AND_RETURN_RET(ret == MSERR_OK, ret);
186 
187     {
188         MEDIA_LOGD("Prepare Start");
189         preparingCond_.wait(lock);
190         MEDIA_LOGD("Prepare End");
191     }
192 
193     if (isErrorHappened_) {
194         MEDIA_LOGE("Prepare failed");
195         GstStateChangeReturn gstRet = gst_element_set_state(GST_ELEMENT_CAST(playbin_), GST_STATE_READY);
196         if (gstRet == GST_STATE_CHANGE_FAILURE) {
197             MEDIA_LOGE("Failed to change playbin's state to %{public}s", gst_element_state_get_name(GST_STATE_READY));
198         }
199         return MSERR_INVALID_STATE;
200     }
201 
202     MEDIA_LOGD("exit");
203     return MSERR_OK;
204 }
205 
PrepareAsync()206 int32_t PlayBinCtrlerBase::PrepareAsync()
207 {
208     MEDIA_LOGD("enter");
209 
210     std::unique_lock<std::mutex> lock(mutex_);
211     return PrepareAsyncInternal();
212 }
213 
Play()214 int32_t PlayBinCtrlerBase::Play()
215 {
216     MEDIA_LOGD("enter");
217 
218     std::unique_lock<std::mutex> lock(mutex_);
219 
220     if (GetCurrState() == playingState_) {
221         MEDIA_LOGI("already at playing state, skip");
222         return MSERR_OK;
223     }
224 
225     if (isBuffering_) {
226         ChangeState(playingState_);
227         return MSERR_OK;
228     }
229 
230     auto currState = std::static_pointer_cast<BaseState>(GetCurrState());
231     int32_t ret = currState->Play();
232     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Play failed");
233 
234     return MSERR_OK;
235 }
236 
Pause()237 int32_t PlayBinCtrlerBase::Pause()
238 {
239     MEDIA_LOGD("enter");
240 
241     std::unique_lock<std::mutex> lock(mutex_);
242 
243     if (GetCurrState() == pausedState_ || GetCurrState() == preparedState_) {
244         MEDIA_LOGI("already at paused state, skip");
245         return MSERR_OK;
246     }
247 
248     auto currState = std::static_pointer_cast<BaseState>(GetCurrState());
249     int32_t ret = currState->Pause();
250     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Pause failed");
251 
252     return MSERR_OK;
253 }
254 
Seek(int64_t timeUs,int32_t seekOption)255 int32_t PlayBinCtrlerBase::Seek(int64_t timeUs, int32_t seekOption)
256 {
257     MEDIA_LOGD("enter");
258 
259     if (SEEK_OPTION_TO_GST_SEEK_FLAGS.find(seekOption) == SEEK_OPTION_TO_GST_SEEK_FLAGS.end()) {
260         MEDIA_LOGE("unsupported seek option: %{public}d", seekOption);
261         return MSERR_INVALID_VAL;
262     }
263 
264     std::unique_lock<std::mutex> lock(mutex_);
265     std::unique_lock<std::mutex> cacheLock(cacheCtrlMutex_);
266 
267     auto currState = std::static_pointer_cast<BaseState>(GetCurrState());
268     int32_t ret = currState->Seek(timeUs, seekOption);
269     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "Seek failed");
270 
271     return MSERR_OK;
272 }
273 
Stop(bool needWait)274 int32_t PlayBinCtrlerBase::Stop(bool needWait)
275 {
276     MEDIA_LOGD("enter");
277     std::unique_lock<std::mutex> lock(mutex_);
278 
279     if (GetCurrState() == preparingState_ && needWait) {
280         MEDIA_LOGD("begin wait stop for current status is preparing");
281         static constexpr int32_t timeout = 2;
282         preparedCond_.wait_for(lock, std::chrono::seconds(timeout));
283         MEDIA_LOGD("end wait stop for current status is preparing");
284     }
285 
286     if (appsrcWrap_ != nullptr) {
287         appsrcWrap_->Stop();
288     }
289 
290     g_object_set(playbin_, "exit-block", 1, nullptr);
291     auto currState = std::static_pointer_cast<BaseState>(GetCurrState());
292     (void)currState->Stop();
293 
294     {
295         MEDIA_LOGD("Stop Start");
296         if (GetCurrState() != stoppedState_) {
297             int32_t id = PlayerXCollie::GetInstance().SetTimerByLog("stoppingCond_.wait");
298             stoppingCond_.wait(lock);
299             PlayerXCollie::GetInstance().CancelTimer(id);
300         }
301         MEDIA_LOGD("Stop End");
302     }
303 
304     if (GetCurrState() != stoppedState_) {
305         MEDIA_LOGE("Stop failed");
306         return MSERR_INVALID_STATE;
307     }
308     return MSERR_OK;
309 }
310 
ChooseSetRateFlags(double rate)311 GstSeekFlags PlayBinCtrlerBase::ChooseSetRateFlags(double rate)
312 {
313     GstSeekFlags seekFlags;
314 
315     if (rate > 0.0) {
316         seekFlags = static_cast<GstSeekFlags>(GST_SEEK_FLAG_FLUSH |
317             GST_SEEK_FLAG_TRICKMODE | GST_SEEK_FLAG_SNAP_AFTER);
318     } else {
319         seekFlags = static_cast<GstSeekFlags>(GST_SEEK_FLAG_FLUSH |
320             GST_SEEK_FLAG_TRICKMODE | GST_SEEK_FLAG_SNAP_BEFORE);
321     }
322 
323     return seekFlags;
324 }
325 
SetRateInternal(double rate)326 int32_t PlayBinCtrlerBase::SetRateInternal(double rate)
327 {
328     MEDIA_LOGD("execute set rate, rate: %{public}lf", rate);
329 
330     gint64 position;
331     gboolean ret;
332 
333     isRating_ = true;
334     if (isDuration_.load()) {
335         position = duration_ * NANO_SEC_PER_USEC;
336     } else {
337         ret = gst_element_query_position(GST_ELEMENT_CAST(playbin_), GST_FORMAT_TIME, &position);
338         if (!ret) {
339             MEDIA_LOGW("query position failed, use lastTime");
340             position = lastTime_;
341         }
342     }
343 
344     GstSeekFlags flags = ChooseSetRateFlags(rate);
345     int64_t start = rate > 0 ? position : 0;
346     int64_t stop = rate > 0 ? static_cast<int64_t>(GST_CLOCK_TIME_NONE) : position;
347 
348     GstEvent *event = gst_event_new_seek(rate, GST_FORMAT_TIME, flags,
349         GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_SET, stop);
350     CHECK_AND_RETURN_RET_LOG(event != nullptr, MSERR_NO_MEMORY, "set rate failed");
351 
352     ret = gst_element_send_event(GST_ELEMENT_CAST(playbin_), event);
353     CHECK_AND_RETURN_RET_LOG(ret, MSERR_SEEK_FAILED, "set rate failed");
354 
355     rate_ = rate;
356 
357     return MSERR_OK;
358 }
359 
SetRate(double rate)360 int32_t PlayBinCtrlerBase::SetRate(double rate)
361 {
362     MEDIA_LOGD("enter");
363     std::unique_lock<std::mutex> lock(mutex_);
364     std::unique_lock<std::mutex> cacheLock(cacheCtrlMutex_);
365 
366     if (IsLiveSource()) {
367         return MSERR_INVALID_OPERATION;
368     }
369 
370     auto currState = std::static_pointer_cast<BaseState>(GetCurrState());
371     int32_t ret = currState->SetRate(rate);
372     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "SetRate failed");
373 
374     return MSERR_OK;
375 }
376 
GetRate()377 double PlayBinCtrlerBase::GetRate()
378 {
379     std::unique_lock<std::mutex> lock(mutex_);
380     MEDIA_LOGI("get rate=%{public}lf", rate_);
381     return rate_;
382 }
383 
SetLoop(bool loop)384 int32_t PlayBinCtrlerBase::SetLoop(bool loop)
385 {
386     if (IsLiveSource()) {
387         return MSERR_INVALID_OPERATION;
388     }
389     enableLooping_ = loop;
390     return MSERR_OK;
391 }
392 
SetVolume(const float & leftVolume,const float & rightVolume)393 void PlayBinCtrlerBase::SetVolume(const float &leftVolume, const float &rightVolume)
394 {
395     (void)rightVolume;
396     std::unique_lock<std::mutex> lock(mutex_);
397     float volume = leftVolume;
398     if (audioSink_ != nullptr) {
399         MEDIA_LOGI("SetVolume(%{public}f) to audio sink", volume);
400         g_object_set(audioSink_, "volume", volume, nullptr);
401     }
402 }
403 
SetAudioRendererInfo(const uint32_t rendererInfo,const int32_t rendererFlag)404 int32_t PlayBinCtrlerBase::SetAudioRendererInfo(const uint32_t rendererInfo, const int32_t rendererFlag)
405 {
406     std::unique_lock<std::mutex> lock(mutex_, std::try_to_lock);
407     rendererInfo_ = rendererInfo;
408     rendererFlag_ = rendererFlag;
409     if (audioSink_ != nullptr) {
410         g_object_set(audioSink_, "audio-renderer-desc", rendererInfo, nullptr);
411         g_object_set(audioSink_, "audio-renderer-flag", rendererFlag, nullptr);
412     }
413     return MSERR_OK;
414 }
415 
SetAudioInterruptMode(const int32_t interruptMode)416 void PlayBinCtrlerBase::SetAudioInterruptMode(const int32_t interruptMode)
417 {
418     std::unique_lock<std::mutex> lock(mutex_);
419     if (audioSink_ != nullptr) {
420         g_object_set(audioSink_, "audio-interrupt-mode", interruptMode, nullptr);
421     }
422 }
423 
SelectBitRate(uint32_t bitRate)424 int32_t PlayBinCtrlerBase::SelectBitRate(uint32_t bitRate)
425 {
426     std::unique_lock<std::mutex> lock(mutex_);
427     if (bitRateVec_.empty()) {
428         MEDIA_LOGE("BitRate is empty");
429         return MSERR_INVALID_OPERATION;
430     }
431 
432     g_object_set(playbin_, "connection-speed", static_cast<uint64_t>(bitRate), nullptr);
433 
434     PlayBinMessage msg = { PLAYBIN_MSG_BITRATEDONE, 0, static_cast<int32_t>(bitRate), {} };
435     ReportMessage(msg);
436 
437     return MSERR_OK;
438 }
439 
Reset()440 int32_t PlayBinCtrlerBase::Reset() noexcept
441 {
442     MEDIA_LOGD("enter");
443 
444     std::unique_lock<std::mutex> lock(mutex_);
445     {
446         std::unique_lock<std::mutex> lk(listenerMutex_);
447         elemSetupListener_ = nullptr;
448         elemUnSetupListener_ = nullptr;
449         autoPlugSortListener_ = nullptr;
450     }
451     // Do it here before the ChangeState to IdleState, for avoding the deadlock when msg handler
452     // try to call the ChangeState.
453     ExitInitializedState();
454     ChangeState(idleState_);
455 
456     if (msgQueue_ != nullptr) {
457         (void)msgQueue_->Stop();
458     }
459 
460     uri_.clear();
461     isErrorHappened_ = false;
462     enableLooping_ = false;
463     {
464         std::unique_lock<std::mutex> appsrcLock(appsrcMutex_);
465         appsrcWrap_ = nullptr;
466     }
467 
468     rate_ = DEFAULT_RATE;
469     seekPos_ = 0;
470     lastTime_ = 0;
471     isSeeking_ = false;
472     isRating_ = false;
473     isBuffering_ = false;
474     cachePercent_ = BUFFER_PERCENT_THRESHOLD;
475     isDuration_ = false;
476     isUserSetPause_ = false;
477 
478     MEDIA_LOGD("exit");
479     return MSERR_OK;
480 }
481 
SetElemSetupListener(ElemSetupListener listener)482 void PlayBinCtrlerBase::SetElemSetupListener(ElemSetupListener listener)
483 {
484     std::unique_lock<std::mutex> lock(mutex_);
485     std::unique_lock<std::mutex> lk(listenerMutex_);
486     elemSetupListener_ = listener;
487 }
488 
SetElemUnSetupListener(ElemSetupListener listener)489 void PlayBinCtrlerBase::SetElemUnSetupListener(ElemSetupListener listener)
490 {
491     std::unique_lock<std::mutex> lock(mutex_);
492     std::unique_lock<std::mutex> lk(listenerMutex_);
493     elemUnSetupListener_ = listener;
494 }
495 
SetAutoPlugSortListener(AutoPlugSortListener listener)496 void PlayBinCtrlerBase::SetAutoPlugSortListener(AutoPlugSortListener listener)
497 {
498     std::unique_lock<std::mutex> lock(mutex_);
499     std::unique_lock<std::mutex> lk(listenerMutex_);
500     autoPlugSortListener_ = listener;
501 }
502 
DoInitializeForHttp()503 void PlayBinCtrlerBase::DoInitializeForHttp()
504 {
505     if (isNetWorkPlay_) {
506         g_object_set(playbin_, "ring-buffer-max-size", RING_BUFFER_MAX_SIZE, nullptr);
507         g_object_set(playbin_, "buffering-flags", true, "buffer-size", PLAYBIN_QUEUE_MAX_SIZE,
508             "buffer-duration", BUFFER_DURATION, "low-percent", BUFFER_LOW_PERCENT_DEFAULT,
509             "high-percent", BUFFER_HIGH_PERCENT_DEFAULT, nullptr);
510         g_object_set(playbin_, "timeout", HTTP_TIME_OUT_DEFAULT, nullptr);
511 
512         PlayBinCtrlerWrapper *wrapper = new(std::nothrow) PlayBinCtrlerWrapper(shared_from_this());
513         CHECK_AND_RETURN_LOG(wrapper != nullptr, "can not create this wrapper");
514 
515         gulong id = g_signal_connect_data(playbin_, "bitrate-parse-complete",
516             G_CALLBACK(&PlayBinCtrlerBase::OnBitRateParseCompleteCb), wrapper,
517             (GClosureNotify)&PlayBinCtrlerWrapper::OnDestory, static_cast<GConnectFlags>(0));
518         (void)signalIds_.emplace_back(SignalInfo { GST_ELEMENT_CAST(playbin_), id });
519     }
520 }
521 
EnterInitializedState()522 int32_t PlayBinCtrlerBase::EnterInitializedState()
523 {
524     if (isInitialized_) {
525         return MSERR_OK;
526     }
527     MediaTrace("PlayBinCtrlerBase::InitializedState");
528     MEDIA_LOGD("EnterInitializedState enter");
529 
530     ON_SCOPE_EXIT(0) {
531         ExitInitializedState();
532         PlayBinMessage msg { PlayBinMsgType::PLAYBIN_MSG_ERROR,
533             PlayBinMsgErrorSubType::PLAYBIN_SUB_MSG_ERROR_NO_MESSAGE,
534             MSERR_CREATE_PLAYER_ENGINE_FAILED, "failed to EnterInitializedState" };
535         ReportMessage(msg);
536         MEDIA_LOGE("enter initialized state failed");
537     };
538 
539     int32_t ret = OnInit();
540     CHECK_AND_RETURN_RET(ret == MSERR_OK, ret);
541     CHECK_AND_RETURN_RET(playbin_ != nullptr, static_cast<int32_t>(MSERR_CREATE_PLAYER_ENGINE_FAILED));
542 
543     ret = DoInitializeForDataSource();
544     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "DoInitializeForDataSource failed!");
545 
546     SetupCustomElement();
547     ret = SetupSignalMessage();
548     CHECK_AND_RETURN_RET(ret == MSERR_OK, ret);
549     ret = SetupElementUnSetupSignal();
550     CHECK_AND_RETURN_RET(ret == MSERR_OK, ret);
551     SetAudioRendererInfo(rendererInfo_, rendererFlag_);
552 
553     uint32_t flags = 0;
554     g_object_get(playbin_, "flags", &flags, nullptr);
555     if ((renderMode_ & PlayBinRenderMode::DEFAULT_RENDER) != 0) {
556         flags &= ~GST_PLAY_FLAG_VIS;
557     }
558     if ((renderMode_ & PlayBinRenderMode::NATIVE_STREAM) != 0) {
559         flags |= GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_NATIVE_AUDIO;
560         flags &= ~(GST_PLAY_FLAG_SOFT_COLORBALANCE | GST_PLAY_FLAG_SOFT_VOLUME);
561     }
562     if ((renderMode_ & PlayBinRenderMode::DISABLE_TEXT) != 0) {
563         flags &= ~GST_PLAY_FLAG_TEXT;
564     }
565     g_object_set(playbin_, "flags", flags, nullptr);
566 
567     // There may be a risk of data competition, but the uri is unlikely to be reconfigured.
568     if (!uri_.empty()) {
569         g_object_set(playbin_, "uri", uri_.c_str(), nullptr);
570     }
571 
572     DoInitializeForHttp();
573 
574     isInitialized_ = true;
575     ChangeState(initializedState_);
576 
577     CANCEL_SCOPE_EXIT_GUARD(0);
578     MEDIA_LOGD("EnterInitializedState exit");
579 
580     return MSERR_OK;
581 }
582 
ExitInitializedState()583 void PlayBinCtrlerBase::ExitInitializedState()
584 {
585     MEDIA_LOGD("ExitInitializedState enter");
586 
587     if (!isInitialized_) {
588         return;
589     }
590     isInitialized_ = false;
591 
592     mutex_.unlock();
593     if (msgProcessor_ != nullptr) {
594         msgProcessor_->Reset();
595         msgProcessor_ = nullptr;
596     }
597     mutex_.lock();
598 
599     if (sinkProvider_ != nullptr) {
600         sinkProvider_->SetMsgNotifier(nullptr);
601     }
602     for (auto &item : signalIds_) {
603         g_signal_handler_disconnect(item.element, item.signalId);
604     }
605     signalIds_.clear();
606 
607     MEDIA_LOGD("unref playbin start");
608     if (playbin_ != nullptr) {
609         (void)gst_element_set_state(GST_ELEMENT_CAST(playbin_), GST_STATE_NULL);
610         gst_object_unref(playbin_);
611         playbin_ = nullptr;
612     }
613     MEDIA_LOGD("unref playbin stop");
614 
615     MEDIA_LOGD("ExitInitializedState exit");
616 }
617 
PrepareAsyncInternal()618 int32_t PlayBinCtrlerBase::PrepareAsyncInternal()
619 {
620     if ((GetCurrState() == preparingState_) || (GetCurrState() == preparedState_)) {
621         MEDIA_LOGI("already at preparing state, skip");
622         return MSERR_OK;
623     }
624 
625     CHECK_AND_RETURN_RET_LOG((!uri_.empty() || appsrcWrap_), MSERR_INVALID_OPERATION, "Set uri firsty!");
626 
627     int32_t ret = EnterInitializedState();
628     CHECK_AND_RETURN_RET(ret == MSERR_OK, ret);
629 
630     auto currState = std::static_pointer_cast<BaseState>(GetCurrState());
631     ret = currState->Prepare();
632     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "PrepareAsyncInternal failed");
633 
634     return MSERR_OK;
635 }
636 
SeekInternal(int64_t timeUs,int32_t seekOption)637 int32_t PlayBinCtrlerBase::SeekInternal(int64_t timeUs, int32_t seekOption)
638 {
639     MEDIA_LOGI("execute seek, time: %{public}" PRIi64 ", option: %{public}d", timeUs, seekOption);
640 
641     int32_t seekFlags = SEEK_OPTION_TO_GST_SEEK_FLAGS.at(seekOption);
642     timeUs = timeUs > duration_ ? duration_ : timeUs;
643     timeUs = timeUs < 0 ? 0 : timeUs;
644 
645     constexpr int32_t usecToNanoSec = 1000;
646     int64_t timeNs = timeUs * usecToNanoSec;
647     seekPos_ = timeUs;
648     isSeeking_ = true;
649     GstEvent *event = gst_event_new_seek(rate_, GST_FORMAT_TIME, static_cast<GstSeekFlags>(seekFlags),
650         GST_SEEK_TYPE_SET, timeNs, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE);
651     CHECK_AND_RETURN_RET_LOG(event != nullptr, MSERR_NO_MEMORY, "seek failed");
652 
653     gboolean ret = gst_element_send_event(GST_ELEMENT_CAST(playbin_), event);
654     CHECK_AND_RETURN_RET_LOG(ret, MSERR_SEEK_FAILED, "seek failed");
655 
656     return MSERR_OK;
657 }
658 
SetupInterruptEventCb()659 void PlayBinCtrlerBase::SetupInterruptEventCb()
660 {
661     PlayBinCtrlerWrapper *wrapper = new(std::nothrow) PlayBinCtrlerWrapper(shared_from_this());
662     CHECK_AND_RETURN_LOG(wrapper != nullptr, "can not create this wrapper");
663 
664     gulong id = g_signal_connect_data(audioSink_, "interrupt-event",
665         G_CALLBACK(&PlayBinCtrlerBase::OnInterruptEventCb), wrapper,
666         (GClosureNotify)&PlayBinCtrlerWrapper::OnDestory, static_cast<GConnectFlags>(0));
667     (void)signalIds_.emplace_back(SignalInfo { GST_ELEMENT_CAST(audioSink_), id });
668 }
669 
SetupAudioStateEventCb()670 void PlayBinCtrlerBase::SetupAudioStateEventCb()
671 {
672     PlayBinCtrlerWrapper *wrapper = new(std::nothrow) PlayBinCtrlerWrapper(shared_from_this());
673     CHECK_AND_RETURN_LOG(wrapper != nullptr, "can not create this wrapper");
674 
675     gulong id = g_signal_connect_data(audioSink_, "audio-state-event",
676         G_CALLBACK(&PlayBinCtrlerBase::OnAudioStateEventCb), wrapper,
677         (GClosureNotify)&PlayBinCtrlerWrapper::OnDestory, static_cast<GConnectFlags>(0));
678     (void)signalIds_.emplace_back(SignalInfo { GST_ELEMENT_CAST(audioSink_), id });
679 }
680 
SetupCustomElement()681 void PlayBinCtrlerBase::SetupCustomElement()
682 {
683     // There may be a risk of data competition, but the sinkProvider is unlikely to be reconfigured.
684     if (sinkProvider_ != nullptr) {
685         audioSink_ = sinkProvider_->CreateAudioSink();
686         if (audioSink_ != nullptr) {
687             g_object_set(playbin_, "audio-sink", audioSink_, nullptr);
688             SetupInterruptEventCb();
689             SetupAudioStateEventCb();
690         }
691         videoSink_ = sinkProvider_->CreateVideoSink();
692         if (videoSink_ != nullptr) {
693             g_object_set(playbin_, "video-sink", videoSink_, nullptr);
694         } else if (audioSink_ != nullptr) {
695             g_object_set(playbin_, "video-sink", audioSink_, nullptr);
696         }
697         auto msgNotifier = std::bind(&PlayBinCtrlerBase::OnSinkMessageReceived, this, std::placeholders::_1);
698         sinkProvider_->SetMsgNotifier(msgNotifier);
699     } else {
700         MEDIA_LOGD("no sinkprovider, delay the sink selection until the playbin enters pause state.");
701     }
702 
703     if ((renderMode_ & PlayBinRenderMode::NATIVE_STREAM) == 0) {
704         GstElement *audioFilter = gst_element_factory_make("scaletempo", "scaletempo");
705         if (audioFilter != nullptr) {
706             g_object_set(playbin_, "audio-filter", audioFilter, nullptr);
707         } else {
708             MEDIA_LOGD("can not create scaletempo, the audio playback speed can not be adjusted");
709         }
710     }
711 }
712 
SetupSignalMessage()713 int32_t PlayBinCtrlerBase::SetupSignalMessage()
714 {
715     MEDIA_LOGD("SetupSignalMessage enter");
716 
717     PlayBinCtrlerWrapper *wrapper = new(std::nothrow) PlayBinCtrlerWrapper(shared_from_this());
718     CHECK_AND_RETURN_RET_LOG(wrapper != nullptr, MSERR_NO_MEMORY, "can not create this wrapper");
719 
720     gulong id = g_signal_connect_data(playbin_, "element-setup",
721         G_CALLBACK(&PlayBinCtrlerBase::ElementSetup), wrapper, (GClosureNotify)&PlayBinCtrlerWrapper::OnDestory,
722         static_cast<GConnectFlags>(0));
723     (void)signalIds_.emplace_back(SignalInfo { GST_ELEMENT_CAST(playbin_), id });
724 
725     GstBus *bus = gst_pipeline_get_bus(playbin_);
726     CHECK_AND_RETURN_RET_LOG(bus != nullptr, MSERR_UNKNOWN, "can not get bus");
727 
728     auto msgNotifier = std::bind(&PlayBinCtrlerBase::OnMessageReceived, this, std::placeholders::_1);
729     msgProcessor_ = std::make_unique<GstMsgProcessor>(*bus, msgNotifier);
730 
731     gst_object_unref(bus);
732     bus = nullptr;
733 
734     int32_t ret = msgProcessor_->Init();
735     CHECK_AND_RETURN_RET(ret == MSERR_OK, ret);
736 
737     // only concern the msg from playbin
738     msgProcessor_->AddMsgFilter(ELEM_NAME(GST_ELEMENT_CAST(playbin_)));
739 
740     MEDIA_LOGD("SetupSignalMessage exit");
741     return MSERR_OK;
742 }
743 
SetupElementUnSetupSignal()744 int32_t PlayBinCtrlerBase::SetupElementUnSetupSignal()
745 {
746     MEDIA_LOGD("SetupElementUnSetupSignal enter");
747 
748     PlayBinCtrlerWrapper *wrapper = new(std::nothrow) PlayBinCtrlerWrapper(shared_from_this());
749     CHECK_AND_RETURN_RET_LOG(wrapper != nullptr, MSERR_NO_MEMORY, "can not create this wrapper");
750 
751     gulong id = g_signal_connect_data(playbin_, "deep-element-removed",
752         G_CALLBACK(&PlayBinCtrlerBase::ElementUnSetup), wrapper, (GClosureNotify)&PlayBinCtrlerWrapper::OnDestory,
753         static_cast<GConnectFlags>(0));
754     (void)signalIds_.emplace_back(SignalInfo { GST_ELEMENT_CAST(playbin_), id });
755 
756     return MSERR_OK;
757 }
758 
QueryDuration()759 void PlayBinCtrlerBase::QueryDuration()
760 {
761     auto state = GetCurrState();
762     if (state != preparedState_ && state != playingState_ && state != pausedState_ &&
763         state != playbackCompletedState_) {
764         MEDIA_LOGE("reuse the last query result: %{public}" PRIi64 " microsecond", duration_);
765         return;
766     }
767 
768     gint64 duration = -1;
769     gboolean ret = gst_element_query_duration(GST_ELEMENT_CAST(playbin_), GST_FORMAT_TIME, &duration);
770     CHECK_AND_RETURN_LOG(ret, "query duration failed");
771 
772     if (duration >= 0) {
773         duration_ = duration / NANO_SEC_PER_USEC;
774     }
775     MEDIA_LOGI("update the duration: %{public}" PRIi64 " microsecond", duration_);
776 }
777 
QueryPosition()778 int64_t PlayBinCtrlerBase::QueryPosition()
779 {
780     gint64 position = 0;
781     gboolean ret = gst_element_query_position(GST_ELEMENT_CAST(playbin_), GST_FORMAT_TIME, &position);
782     if (!ret) {
783         MEDIA_LOGW("query position failed");
784         return lastTime_ / USEC_PER_MSEC;
785     }
786 
787     int64_t curTime = position / NANO_SEC_PER_USEC;
788     if (duration_ >= 0) {
789         curTime = std::min(curTime, duration_);
790     }
791     lastTime_ = curTime;
792     MEDIA_LOGI("update the position: %{public}" PRIi64 " microsecond", curTime);
793     return curTime / USEC_PER_MSEC;
794 }
795 
ProcessEndOfStream()796 void PlayBinCtrlerBase::ProcessEndOfStream()
797 {
798     MEDIA_LOGD("End of stream");
799     isDuration_ = true;
800     if (IsLiveSource()) {
801         MEDIA_LOGD("appsrc livemode, can not loop");
802         return;
803     }
804 
805     if (!enableLooping_.load() && !isSeeking_) { // seek duration done->seeking->eos
806         ChangeState(playbackCompletedState_);
807     }
808 }
809 
DoInitializeForDataSource()810 int32_t PlayBinCtrlerBase::DoInitializeForDataSource()
811 {
812     if (appsrcWrap_ != nullptr) {
813         (void)appsrcWrap_->Prepare();
814         auto msgNotifier = std::bind(&PlayBinCtrlerBase::OnAppsrcErrorMessageReceived, this, std::placeholders::_1);
815         CHECK_AND_RETURN_RET_LOG(appsrcWrap_->SetErrorCallback(msgNotifier) == MSERR_OK,
816             MSERR_INVALID_OPERATION, "set appsrc error callback failed");
817 
818         PlayBinCtrlerWrapper *wrapper = new(std::nothrow) PlayBinCtrlerWrapper(shared_from_this());
819         CHECK_AND_RETURN_RET_LOG(wrapper != nullptr, MSERR_NO_MEMORY, "can not create this wrapper");
820 
821         gulong id = g_signal_connect_data(playbin_, "source-setup",
822             G_CALLBACK(&PlayBinCtrlerBase::SourceSetup), wrapper, (GClosureNotify)&PlayBinCtrlerWrapper::OnDestory,
823             static_cast<GConnectFlags>(0));
824         (void)signalIds_.emplace_back(SignalInfo { GST_ELEMENT_CAST(playbin_), id });
825 
826         g_object_set(playbin_, "uri", "appsrc://", nullptr);
827     }
828     return MSERR_OK;
829 }
830 
HandleCacheCtrl(int32_t percent)831 void PlayBinCtrlerBase::HandleCacheCtrl(int32_t percent)
832 {
833     MEDIA_LOGI("HandleCacheCtrl percent is %{public}d", percent);
834     if (!isBuffering_) {
835         HandleCacheCtrlWhenNoBuffering(percent);
836     } else {
837         HandleCacheCtrlWhenBuffering(percent);
838     }
839 }
840 
HandleCacheCtrlCb(const InnerMessage & msg)841 void PlayBinCtrlerBase::HandleCacheCtrlCb(const InnerMessage &msg)
842 {
843     if (isNetWorkPlay_) {
844         PlayBinMessage playBinMsg = { PLAYBIN_MSG_SUBTYPE, PLAYBIN_SUB_MSG_BUFFERING_PERCENT, msg.detail1, {} };
845         ReportMessage(playBinMsg);
846 
847         cachePercent_ = msg.detail1;
848         HandleCacheCtrl(cachePercent_);
849     }
850 }
851 
HandleCacheCtrlWhenNoBuffering(int32_t percent)852 void PlayBinCtrlerBase::HandleCacheCtrlWhenNoBuffering(int32_t percent)
853 {
854     if (percent < static_cast<float>(BUFFER_LOW_PERCENT_DEFAULT) / BUFFER_HIGH_PERCENT_DEFAULT *
855         BUFFER_PERCENT_THRESHOLD && !isSeeking_ && !isRating_ && !isUserSetPause_) {
856         isBuffering_ = true;
857         {
858             std::unique_lock<std::mutex> lock(cacheCtrlMutex_);
859             g_object_set(playbin_, "state-change", GST_PLAYER_STATUS_BUFFERING, nullptr);
860         }
861         if (GetCurrState() == playingState_) {
862             std::unique_lock<std::mutex> lock(cacheCtrlMutex_);
863             MEDIA_LOGI("HandleCacheCtrl percent is %{public}d, begin set to paused", percent);
864             GstStateChangeReturn ret = gst_element_set_state(GST_ELEMENT_CAST(playbin_), GST_STATE_PAUSED);
865             if (ret == GST_STATE_CHANGE_FAILURE) {
866                 MEDIA_LOGE("Failed to change playbin's state to GST_STATE_PAUSED");
867                 return;
868             }
869         }
870 
871         PlayBinMessage msg = { PLAYBIN_MSG_SUBTYPE, PLAYBIN_SUB_MSG_BUFFERING_START, 0, {} };
872         ReportMessage(msg);
873     }
874 }
875 
HandleCacheCtrlWhenBuffering(int32_t percent)876 void PlayBinCtrlerBase::HandleCacheCtrlWhenBuffering(int32_t percent)
877 {
878     if (percent >= BUFFER_PERCENT_THRESHOLD) {
879         isBuffering_ = false;
880         if (GetCurrState() == playingState_ && !isUserSetPause_) {
881             {
882                 std::unique_lock<std::mutex> lock(cacheCtrlMutex_);
883                 g_object_set(playbin_, "state-change", GST_PLAYER_STATUS_PLAYING, nullptr);
884             }
885             std::unique_lock<std::mutex> lock(cacheCtrlMutex_);
886             MEDIA_LOGI("HandleCacheCtrl percent is %{public}d, begin set to playing", percent);
887             GstStateChangeReturn ret = gst_element_set_state(GST_ELEMENT_CAST(playbin_), GST_STATE_PLAYING);
888             if (ret == GST_STATE_CHANGE_FAILURE) {
889                 MEDIA_LOGE("Failed to change playbin's state to GST_STATE_PLAYING");
890                 return;
891             }
892         } else {
893             std::unique_lock<std::mutex> lock(cacheCtrlMutex_);
894             g_object_set(playbin_, "state-change", GST_PLAYER_STATUS_PAUSED, nullptr);
895         }
896 
897         PlayBinMessage msg = { PLAYBIN_MSG_SUBTYPE, PLAYBIN_SUB_MSG_BUFFERING_END, 0, {} };
898         ReportMessage(msg);
899     }
900 }
901 
RemoveGstPlaySinkVideoConvertPlugin()902 void PlayBinCtrlerBase::RemoveGstPlaySinkVideoConvertPlugin()
903 {
904     uint32_t flags = 0;
905 
906     CHECK_AND_RETURN_LOG(playbin_ != nullptr, "playbin_ is nullptr");
907     g_object_get(playbin_, "flags", &flags, nullptr);
908     flags |= (GST_PLAY_FLAG_NATIVE_VIDEO | GST_PLAY_FLAG_HARDWARE_VIDEO);
909     flags &= ~GST_PLAY_FLAG_SOFT_COLORBALANCE;
910     MEDIA_LOGD("set gstplaysink flags %{public}d", flags);
911     // set playsink remove GstPlaySinkVideoConvert, for first-frame performance optimization
912     g_object_set(playbin_, "flags", flags, nullptr);
913 }
914 
AutoPlugSort(const GstElement * uriDecoder,GstPad * pad,GstCaps * caps,GValueArray * factories,gpointer userData)915 GValueArray *PlayBinCtrlerBase::AutoPlugSort(const GstElement *uriDecoder, GstPad *pad, GstCaps *caps,
916     GValueArray *factories, gpointer userData)
917 {
918     CHECK_AND_RETURN_RET_LOG(uriDecoder != nullptr, nullptr, "uriDecoder is null");
919     CHECK_AND_RETURN_RET_LOG(pad != nullptr, nullptr, "pad is null");
920     CHECK_AND_RETURN_RET_LOG(caps != nullptr, nullptr, "caps is null");
921     CHECK_AND_RETURN_RET_LOG(factories != nullptr, nullptr, "factories is null");
922 
923     auto thizStrong = PlayBinCtrlerWrapper::TakeStrongThiz(userData);
924     CHECK_AND_RETURN_RET_LOG(thizStrong != nullptr, nullptr, "thizStrong is null");
925     return thizStrong->OnAutoPlugSort(*factories);
926 }
OnAutoPlugSort(GValueArray & factories)927 GValueArray *PlayBinCtrlerBase::OnAutoPlugSort(GValueArray &factories)
928 {
929     MEDIA_LOGD("OnAutoPlugSort");
930 
931     decltype(autoPlugSortListener_) listener = nullptr;
932     {
933         std::unique_lock<std::mutex> lock(listenerMutex_);
934         listener = autoPlugSortListener_;
935     }
936 
937     if (listener != nullptr) {
938         return listener(factories);
939     }
940     return nullptr;
941 }
942 
OnSourceSetup(const GstElement * playbin,GstElement * src,const std::shared_ptr<PlayBinCtrlerBase> & playbinCtrl)943 void PlayBinCtrlerBase::OnSourceSetup(const GstElement *playbin, GstElement *src,
944     const std::shared_ptr<PlayBinCtrlerBase> &playbinCtrl)
945 {
946     (void)playbin;
947     CHECK_AND_RETURN_LOG(playbinCtrl != nullptr, "playbinCtrl is null");
948     CHECK_AND_RETURN_LOG(src != nullptr, "src is null");
949 
950     GstElementFactory *elementFac = gst_element_get_factory(src);
951     const gchar *eleTypeName = g_type_name(gst_element_factory_get_element_type(elementFac));
952     CHECK_AND_RETURN_LOG(eleTypeName != nullptr, "eleTypeName is nullptr");
953 
954     std::unique_lock<std::mutex> appsrcLock(appsrcMutex_);
955     if ((strstr(eleTypeName, "GstAppSrc") != nullptr) && (playbinCtrl->appsrcWrap_ != nullptr)) {
956         (void)playbinCtrl->appsrcWrap_->SetAppsrc(src);
957     } else if (strstr(eleTypeName, "GstCurlHttpSrc") != nullptr) {
958         g_object_set(src, "ssl-ca-file", "/etc/ssl/certs/cacert.pem", nullptr);
959         MEDIA_LOGI("setup curl_http ca_file done");
960     }
961 }
962 
OnVideoDecoderSetup(GstElement & elem)963 bool PlayBinCtrlerBase::OnVideoDecoderSetup(GstElement &elem)
964 {
965     const gchar *metadata = gst_element_get_metadata(&elem, GST_ELEMENT_METADATA_KLASS);
966     if (metadata == nullptr) {
967         MEDIA_LOGE("gst_element_get_metadata return nullptr");
968         return false;
969     }
970 
971     std::string metaStr(metadata);
972     if (metaStr.find("Decoder/Video") != std::string::npos) {
973         return true;
974     }
975 
976     return false;
977 }
978 
OnElementSetup(GstElement & elem)979 void PlayBinCtrlerBase::OnElementSetup(GstElement &elem)
980 {
981     MEDIA_LOGI("element setup: %{public}s", ELEM_NAME(&elem));
982 
983     // limit to the g-signal, send this notification at this thread, do not change the work thread.
984     // otherwise ,the avmetaengine will work improperly.
985 
986     if (OnVideoDecoderSetup(elem) || strncmp(ELEM_NAME(&elem), "multiqueue", strlen("multiqueue")) == 0 ||
987         strncmp(ELEM_NAME(&elem), "qtdemux", strlen("qtdemux")) == 0) {
988         MEDIA_LOGI("add msgfilter element: %{public}s", ELEM_NAME(&elem));
989         msgProcessor_->AddMsgFilter(ELEM_NAME(&elem));
990     }
991 
992     std::string elementName(GST_ELEMENT_NAME(&elem));
993     if (isNetWorkPlay_ == false && elementName.find("uridecodebin") != std::string::npos) {
994         PlayBinCtrlerWrapper *wrapper = new(std::nothrow) PlayBinCtrlerWrapper(shared_from_this());
995         CHECK_AND_RETURN_LOG(wrapper != nullptr, "can not create this wrapper");
996         gulong id = g_signal_connect_data(&elem, "autoplug-sort",
997             G_CALLBACK(&PlayBinCtrlerBase::AutoPlugSort), wrapper,
998             (GClosureNotify)&PlayBinCtrlerWrapper::OnDestory, static_cast<GConnectFlags>(0));
999         (void)signalIds_.emplace_back(SignalInfo { &elem, id });
1000     }
1001 
1002     decltype(elemSetupListener_) listener = nullptr;
1003     {
1004         std::unique_lock<std::mutex> lock(listenerMutex_);
1005         listener = elemSetupListener_;
1006     }
1007 
1008     if (listener != nullptr) {
1009         listener(elem);
1010     }
1011 }
1012 
OnElementUnSetup(GstElement & elem)1013 void PlayBinCtrlerBase::OnElementUnSetup(GstElement &elem)
1014 {
1015     MEDIA_LOGI("element unsetup: %{public}s", ELEM_NAME(&elem));
1016 
1017     decltype(elemUnSetupListener_) listener = nullptr;
1018     {
1019         std::unique_lock<std::mutex> lock(listenerMutex_);
1020         listener = elemUnSetupListener_;
1021     }
1022 
1023     if (listener != nullptr) {
1024         listener(elem);
1025     }
1026 }
1027 
OnInterruptEventCb(const GstElement * audioSink,const uint32_t eventType,const uint32_t forceType,const uint32_t hintType,gpointer userData)1028 void PlayBinCtrlerBase::OnInterruptEventCb(const GstElement *audioSink, const uint32_t eventType,
1029     const uint32_t forceType, const uint32_t hintType, gpointer userData)
1030 {
1031     (void)audioSink;
1032     if (userData == nullptr) {
1033         return;
1034     }
1035     auto thizStrong = PlayBinCtrlerWrapper::TakeStrongThiz(userData);
1036     if (thizStrong != nullptr) {
1037         uint32_t value = 0;
1038         value = (((eventType << INTERRUPT_EVENT_SHIFT) | forceType) << INTERRUPT_EVENT_SHIFT) | hintType;
1039         PlayBinMessage msg { PLAYBIN_MSG_AUDIO_SINK, PLAYBIN_MSG_INTERRUPT_EVENT, 0, value };
1040         thizStrong->ReportMessage(msg);
1041     }
1042 }
1043 
OnAudioStateEventCb(const GstElement * audioSink,const uint32_t audioState,gpointer userData)1044 void PlayBinCtrlerBase::OnAudioStateEventCb(const GstElement *audioSink, const uint32_t audioState, gpointer userData)
1045 {
1046     (void)audioSink;
1047     if (userData == nullptr) {
1048         return;
1049     }
1050     auto thizStrong = PlayBinCtrlerWrapper::TakeStrongThiz(userData);
1051     if (thizStrong != nullptr) {
1052         int32_t value = static_cast<int32_t>(audioState);
1053         PlayBinMessage msg { PLAYBIN_MSG_AUDIO_SINK, PLAYBIN_MSG_AUDIO_STATE_EVENT, 0, value };
1054         thizStrong->ReportMessage(msg);
1055     }
1056 }
1057 
OnBitRateParseCompleteCb(const GstElement * playbin,uint32_t * bitrateInfo,uint32_t bitrateNum,gpointer userData)1058 void PlayBinCtrlerBase::OnBitRateParseCompleteCb(const GstElement *playbin, uint32_t *bitrateInfo,
1059     uint32_t bitrateNum, gpointer userData)
1060 {
1061     (void)playbin;
1062     auto thizStrong = PlayBinCtrlerWrapper::TakeStrongThiz(userData);
1063     if (thizStrong != nullptr) {
1064         MEDIA_LOGD("bitrateNum = %{public}u", bitrateNum);
1065         for (uint32_t i = 0; i < bitrateNum; i++) {
1066             MEDIA_LOGD("bitrate = %{public}u", bitrateInfo[i]);
1067             thizStrong->bitRateVec_.push_back(bitrateInfo[i]);
1068         }
1069         Format format;
1070         (void)format.PutBuffer(std::string(PlayerKeys::PLAYER_BITRATE),
1071             static_cast<uint8_t *>(static_cast<void *>(bitrateInfo)), bitrateNum * sizeof(uint32_t));
1072         PlayBinMessage msg = { PLAYBIN_MSG_SUBTYPE, PLAYBIN_SUB_MSG_BITRATE_COLLECT, 0, format };
1073         thizStrong->ReportMessage(msg);
1074     }
1075 }
1076 
OnAppsrcErrorMessageReceived(int32_t errorCode)1077 void PlayBinCtrlerBase::OnAppsrcErrorMessageReceived(int32_t errorCode)
1078 {
1079     (void)errorCode;
1080     PlayBinMessage msg { PlayBinMsgType::PLAYBIN_MSG_ERROR,
1081         PlayBinMsgErrorSubType::PLAYBIN_SUB_MSG_ERROR_NO_MESSAGE,
1082         MSERR_DATA_SOURCE_IO_ERROR, "PlayBinCtrlerBase::OnAppsrcErrorMessageReceived" };
1083     ReportMessage(msg);
1084 }
1085 
OnMessageReceived(const InnerMessage & msg)1086 void PlayBinCtrlerBase::OnMessageReceived(const InnerMessage &msg)
1087 {
1088     HandleMessage(msg);
1089 }
1090 
OnSinkMessageReceived(const PlayBinMessage & msg)1091 void PlayBinCtrlerBase::OnSinkMessageReceived(const PlayBinMessage &msg)
1092 {
1093     ReportMessage(msg);
1094 }
1095 
SetNotifier(PlayBinMsgNotifier notifier)1096 void PlayBinCtrlerBase::SetNotifier(PlayBinMsgNotifier notifier)
1097 {
1098     std::unique_lock<std::mutex> lock(mutex_);
1099     notifier_ = notifier;
1100 }
1101 
ReportMessage(const PlayBinMessage & msg)1102 void PlayBinCtrlerBase::ReportMessage(const PlayBinMessage &msg)
1103 {
1104     if (msg.type == PlayBinMsgType::PLAYBIN_MSG_ERROR) {
1105         MEDIA_LOGE("error happend, error code: %{public}d", msg.code);
1106 
1107         {
1108             std::unique_lock<std::mutex> lock(mutex_);
1109             isErrorHappened_ = true;
1110             preparingCond_.notify_all();
1111             stoppingCond_.notify_all();
1112         }
1113     }
1114 
1115     MEDIA_LOGD("report msg, type: %{public}d", msg.type);
1116 
1117     PlayBinMsgNotifier notifier = notifier_;
1118     if (notifier != nullptr) {
1119         auto msgReportHandler = std::make_shared<TaskHandler<void>>([msg, notifier]() {
1120             int32_t id = PlayerXCollie::GetInstance().SetTimerByLog("PlayBinCtrlerBase::ReportMessage");
1121             notifier(msg);
1122             PlayerXCollie::GetInstance().CancelTimer(id);
1123         });
1124         int32_t ret = msgQueue_->EnqueueTask(msgReportHandler);
1125         if (ret != MSERR_OK) {
1126             MEDIA_LOGE("async report msg failed, type: %{public}d, subType: %{public}d, code: %{public}d",
1127                 msg.type, msg.subType, msg.code);
1128         };
1129     }
1130 
1131     if (msg.type == PlayBinMsgType::PLAYBIN_MSG_EOS) {
1132         ProcessEndOfStream();
1133     }
1134 }
1135 } // namespace Media
1136 } // namespace OHOS
1137 
1138