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 "gst_player_ctrl.h"
17 #include "media_log.h"
18 #include "audio_system_manager.h"
19 #include "media_errors.h"
20 #include "audio_errors.h"
21
22 namespace {
23 constexpr float INVALID_VOLUME = -1.0;
24 constexpr double DEFAULT_RATE = 1.0;
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "GstPlayerCtrl"};
26 constexpr int MILLI = 1000;
27 constexpr int MICRO = MILLI * 1000;
28 // multiqueue property
29 constexpr int PLAYBIN_QUEUE_MAX_SIZE = 100 * 1024 * 1024; // 100 * 1024 * 1024 Bytes
30 constexpr int BUFFER_TIME_DEFAULT = 15000; // 15s
31 constexpr int HTTP_TIME_OUT_DEFAULT = 15000; // 15s
32 constexpr int BUFFER_LOW_PERCENT_DEFAULT = 1;
33 constexpr int BUFFER_HIGH_PERCENT_DEFAULT = 4;
34 constexpr int BUFFER_FULL_PERCENT_DEFAULT = 100;
35
36 using namespace OHOS::Media;
37 using StreamToServiceErrFunc = void (*)(const gchar *name, int32_t &errorCode);
38 static const std::unordered_map<int32_t, StreamToServiceErrFunc> STREAM_TO_SERVICE_ERR_FUNC_TABLE = {
39 { GST_STREAM_ERROR_DECODE, GstPlayerCtrl::StreamDecErrorParse },
40 };
41 static const std::unordered_map<int32_t, MediaServiceErrCode> STREAM_TO_SERVICE_ERR_TABLE = {
42 { GST_STREAM_ERROR_FORMAT, MSERR_UNSUPPORT_CONTAINER_TYPE },
43 { GST_STREAM_ERROR_TYPE_NOT_FOUND, MSERR_NOT_FIND_CONTAINER },
44 /* Currently, audio decoding and video decoding cannot be distinguished which is not supported by msg.
45 * By default, we set video decoding is not supported.
46 * The identification method must be added when the new demux pulgin in is use.
47 */
48 { GST_STREAM_ERROR_CODEC_NOT_FOUND, MSERR_UNSUPPORT_VID_DEC_TYPE },
49 { GST_STREAM_ERROR_DEMUX, MSERR_DEMUXER_FAILED },
50 };
51 static const std::unordered_map<int32_t, MediaServiceErrCode> RESOURCE_TO_SERVICE_ERR_TABLE = {
52 { GST_RESOURCE_ERROR_NOT_FOUND, MSERR_OPEN_FILE_FAILED },
53 { GST_RESOURCE_ERROR_OPEN_READ, MSERR_OPEN_FILE_FAILED },
54 { GST_RESOURCE_ERROR_READ, MSERR_FILE_ACCESS_FAILED },
55 { GST_RESOURCE_ERROR_NOT_AUTHORIZED, MSERR_FILE_ACCESS_FAILED },
56 { GST_RESOURCE_ERROR_TIME_OUT, MSERR_NETWORK_TIMEOUT },
57 };
58 }
59
60 namespace OHOS {
61 namespace Media {
GstPlayerCtrl(GstPlayer * gstPlayer)62 GstPlayerCtrl::GstPlayerCtrl(GstPlayer *gstPlayer)
63 : gstPlayer_(gstPlayer),
64 taskQue_("GstCtrlTask"),
65 volume_(INVALID_VOLUME),
66 rate_(DEFAULT_RATE)
67 {
68 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
69 (void)taskQue_.Start();
70 trackParse_ = GstPlayerTrackParse::Create();
71 if (trackParse_ == nullptr) {
72 MEDIA_LOGE("create track parse fail");
73 }
74 }
75
~GstPlayerCtrl()76 GstPlayerCtrl::~GstPlayerCtrl()
77 {
78 condVarPlaySync_.notify_all();
79 condVarPauseSync_.notify_all();
80 condVarStopSync_.notify_all();
81 condVarSeekSync_.notify_all();
82 condVarPreparingSync_.notify_all();
83 (void)taskQue_.Stop();
84 for (auto &signalId : signalIds_) {
85 g_signal_handler_disconnect(gstPlayer_, signalId);
86 }
87 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
88 }
89
SetRingBufferMaxSize(uint64_t size)90 void GstPlayerCtrl::SetRingBufferMaxSize(uint64_t size)
91 {
92 std::unique_lock<std::mutex> lock(mutex_);
93 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
94 g_object_set(gstPlayer_, "ring-buffer-max-size", static_cast<guint64>(size), nullptr);
95 }
96
SetBufferingInfo()97 void GstPlayerCtrl::SetBufferingInfo()
98 {
99 std::unique_lock<std::mutex> lock(mutex_);
100 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
101 MEDIA_LOGD("SetBufferingInfo");
102
103 bool flags = true;
104 g_object_set(gstPlayer_, "buffering-flags", flags, nullptr);
105
106 uint64_t bufferDuration = static_cast<uint64_t>(BUFFER_TIME_DEFAULT) * static_cast<uint64_t>(MICRO);
107 g_object_set(gstPlayer_, "buffer-size", PLAYBIN_QUEUE_MAX_SIZE,
108 "buffer-duration", bufferDuration, "low-percent", BUFFER_LOW_PERCENT_DEFAULT,
109 "high-percent", BUFFER_HIGH_PERCENT_DEFAULT, nullptr);
110 }
111
SetHttpTimeOut()112 void GstPlayerCtrl::SetHttpTimeOut()
113 {
114 std::unique_lock<std::mutex> lock(mutex_);
115 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
116 MEDIA_LOGD("SetHttpTimeOut");
117
118 g_object_set(gstPlayer_, "timeout", static_cast<uint32_t>(HTTP_TIME_OUT_DEFAULT / MILLI), nullptr);
119 }
120
SetUrl(const std::string & url)121 int32_t GstPlayerCtrl::SetUrl(const std::string &url)
122 {
123 std::unique_lock<std::mutex> lock(mutex_);
124 CHECK_AND_RETURN_RET_LOG(gstPlayer_ != nullptr, MSERR_INVALID_VAL, "gstPlayer_ is nullptr");
125 gst_player_set_uri(gstPlayer_, url.c_str());
126 currentState_ = PLAYER_PREPARING;
127 return MSERR_OK;
128 }
129
SetSource(const std::shared_ptr<GstAppsrcWarp> & appsrcWarp)130 int32_t GstPlayerCtrl::SetSource(const std::shared_ptr<GstAppsrcWarp> &appsrcWarp)
131 {
132 std::unique_lock<std::mutex> lock(mutex_);
133 CHECK_AND_RETURN_RET_LOG(gstPlayer_ != nullptr, MSERR_INVALID_OPERATION, "gstPlayer_ is nullptr");
134 appsrcWarp_ = appsrcWarp;
135 gst_player_set_uri(gstPlayer_, "appsrc://");
136 currentState_ = PLAYER_PREPARING;
137 return MSERR_OK;
138 }
139
SetCallbacks(const std::weak_ptr<IPlayerEngineObs> & obs)140 int32_t GstPlayerCtrl::SetCallbacks(const std::weak_ptr<IPlayerEngineObs> &obs)
141 {
142 CHECK_AND_RETURN_RET_LOG(obs.lock() != nullptr,
143 MSERR_INVALID_OPERATION, "obs is nullptr, please set callback");
144 if (appsrcWarp_ != nullptr) {
145 CHECK_AND_RETURN_RET_LOG(appsrcWarp_->SetErrorCallback(obs) == MSERR_OK,
146 MSERR_INVALID_OPERATION, "set obs failed");
147 }
148
149 signalIds_.push_back(g_signal_connect(gstPlayer_, "state-changed", G_CALLBACK(OnStateChangedCb), this));
150 signalIds_.push_back(g_signal_connect(gstPlayer_, "end-of-stream", G_CALLBACK(OnEndOfStreamCb), this));
151 signalIds_.push_back(g_signal_connect(gstPlayer_, "error-msg", G_CALLBACK(OnErrorCb), this));
152 signalIds_.push_back(g_signal_connect(gstPlayer_, "seek-done", G_CALLBACK(OnSeekDoneCb), this));
153 signalIds_.push_back(g_signal_connect(gstPlayer_, "position-updated", G_CALLBACK(OnPositionUpdatedCb), this));
154 signalIds_.push_back(g_signal_connect(gstPlayer_, "source-setup", G_CALLBACK(OnSourceSetupCb), this));
155 signalIds_.push_back(g_signal_connect(gstPlayer_, "buffering", G_CALLBACK(OnCachedPercentCb), this));
156 signalIds_.push_back(g_signal_connect(gstPlayer_, "buffering-time", G_CALLBACK(OnBufferingTimeCb), this));
157 signalIds_.push_back(g_signal_connect(gstPlayer_, "mq-num-use-buffering", G_CALLBACK(OnMqNumUseBufferingCb), this));
158 signalIds_.push_back(g_signal_connect(gstPlayer_, "resolution-changed", G_CALLBACK(OnResolutionChanegdCb), this));
159 signalIds_.push_back(g_signal_connect(gstPlayer_, "element-setup", G_CALLBACK(OnElementSetupCb), this));
160
161 obs_ = obs;
162 currentState_ = PLAYER_PREPARING;
163 return MSERR_OK;
164 }
165
OnElementSetupCb(const GstPlayer * player,GstElement * src,GstPlayerCtrl * playerGst)166 void GstPlayerCtrl::OnElementSetupCb(const GstPlayer *player, GstElement *src, GstPlayerCtrl *playerGst)
167 {
168 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
169 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
170 CHECK_AND_RETURN_LOG(src != nullptr, "src is null");
171
172 const gchar *metadata = gst_element_get_metadata(src, GST_ELEMENT_METADATA_KLASS);
173 if (metadata == nullptr) {
174 MEDIA_LOGE("gst_element_get_metadata return nullptr");
175 return;
176 }
177
178 MEDIA_LOGD("get element_name %{public}s, get metadata %{public}s", GST_ELEMENT_NAME(src), metadata);
179 std::string metaStr(metadata);
180
181 if (metaStr.find("Codec/Demuxer") != std::string::npos || metaStr.find("Codec/Parser") != std::string::npos) {
182 if (playerGst->trackParse_->GetDemuxerElementFind() == false) {
183 playerGst->signalIds_.push_back(g_signal_connect(src,
184 "pad-added", G_CALLBACK(GstPlayerTrackParse::OnPadAddedCb), playerGst->trackParse_.get()));
185 playerGst->trackParse_->SetDemuxerElementFind(true);
186 }
187 }
188
189 if (metaStr.find("Codec/Decoder/Video/Hardware") != std::string::npos) {
190 playerGst->isHardWare_ = true;
191 return;
192 }
193
194 if (metaStr.find("Sink/Video") != std::string::npos && playerGst->isHardWare_) {
195 GstCaps *caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "NV12", nullptr);
196 g_object_set(G_OBJECT(src), "caps", caps, nullptr);
197 return;
198 }
199 }
200
SetVideoTrack(bool enable)201 void GstPlayerCtrl::SetVideoTrack(bool enable)
202 {
203 std::unique_lock<std::mutex> lock(mutex_);
204 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
205
206 gst_player_set_video_track_enabled(gstPlayer_, static_cast<gboolean>(enable));
207 MEDIA_LOGI("SetVideoTrack Enabled %{public}d", enable);
208 }
209
Prepare()210 void GstPlayerCtrl::Prepare()
211 {
212 isExit_ = false;
213 PauseSync();
214 }
215
PrepareAsync()216 void GstPlayerCtrl::PrepareAsync()
217 {
218 isExit_ = false;
219 Pause();
220 }
221
Pause()222 void GstPlayerCtrl::Pause()
223 {
224 std::unique_lock<std::mutex> lock(mutex_);
225 auto task = std::make_shared<TaskHandler<void>>([this] { PauseSync(); });
226 (void)taskQue_.EnqueueTask(task);
227 }
228
PauseSync()229 void GstPlayerCtrl::PauseSync()
230 {
231 std::unique_lock<std::mutex> lock(mutex_);
232 if (appsrcWarp_ != nullptr) {
233 (void)appsrcWarp_->Prepare();
234 }
235
236 if (isExit_ ||
237 currentState_ == PLAYER_PAUSED ||
238 currentState_ == PLAYER_PREPARED ||
239 currentState_ == PLAYER_PLAYBACK_COMPLETE) {
240 return;
241 }
242
243 if (currentState_ == PLAYER_PREPARING) {
244 preparing_ = true;
245 }
246
247 MEDIA_LOGD("Pause start!");
248 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
249 gst_player_pause(gstPlayer_);
250
251 {
252 condVarPauseSync_.wait(lock);
253 MEDIA_LOGD("Pause finised!");
254 }
255 }
256
Play()257 void GstPlayerCtrl::Play()
258 {
259 std::unique_lock<std::mutex> lock(mutex_);
260 auto task = std::make_shared<TaskHandler<void>>([this] { PlaySync(); });
261 (void)taskQue_.EnqueueTask(task);
262 }
263
PlaySync()264 void GstPlayerCtrl::PlaySync()
265 {
266 std::unique_lock<std::mutex> lock(mutex_);
267 if (currentState_ == PLAYER_STARTED || isExit_) {
268 return;
269 }
270 if (IsLiveMode() && currentState_ == PLAYER_PLAYBACK_COMPLETE) {
271 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
272 if (tempObs != nullptr) {
273 tempObs->OnError(PLAYER_ERROR_UNKNOWN, MSERR_INVALID_STATE);
274 }
275 return;
276 }
277
278 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
279 gst_player_play(gstPlayer_);
280
281 {
282 condVarPlaySync_.wait(lock);
283 MEDIA_LOGD("Play finised!");
284 }
285 }
286
ChangeSeekModeToGstFlag(const PlayerSeekMode mode) const287 int32_t GstPlayerCtrl::ChangeSeekModeToGstFlag(const PlayerSeekMode mode) const
288 {
289 int32_t flag = 0;
290 switch (mode) {
291 case SEEK_PREVIOUS_SYNC:
292 flag = GST_SEEK_FLAG_SNAP_BEFORE | GST_SEEK_FLAG_KEY_UNIT;
293 break;
294 case SEEK_NEXT_SYNC:
295 flag = GST_SEEK_FLAG_SNAP_AFTER | GST_SEEK_FLAG_KEY_UNIT;
296 break;
297 case SEEK_CLOSEST_SYNC:
298 flag = GST_SEEK_FLAG_KEY_UNIT;
299 break;
300 case SEEK_CLOSEST:
301 break;
302 default:
303 MEDIA_LOGW("unknown seek mode");
304 break;
305 }
306 return flag;
307 }
308
Seek(uint64_t position,const PlayerSeekMode mode)309 int32_t GstPlayerCtrl::Seek(uint64_t position, const PlayerSeekMode mode)
310 {
311 std::unique_lock<std::mutex> lock(mutex_);
312 if (IsLiveMode()) {
313 return MSERR_INVALID_OPERATION;
314 }
315
316 if ((position == 0) && (position == GetPositionInner())) {
317 MEDIA_LOGW("Seek to the inner position");
318 return MSERR_OK;
319 }
320
321 position = (position > sourceDuration_) ? sourceDuration_ : position;
322 auto task = std::make_shared<TaskHandler<void>>([this, position, mode] { SeekSync(position, mode); });
323 if (taskQue_.EnqueueTask(task) != 0) {
324 MEDIA_LOGE("Seek fail");
325 return MSERR_INVALID_OPERATION;
326 }
327
328 if (seekTask_ != nullptr) {
329 MEDIA_LOGI("cancel pre seek Task");
330 seekTask_->Cancel();
331 }
332 seekTask_ = task;
333
334 return MSERR_OK;
335 }
336
SeekSync(uint64_t position,const PlayerSeekMode mode)337 void GstPlayerCtrl::SeekSync(uint64_t position, const PlayerSeekMode mode)
338 {
339 std::unique_lock<std::mutex> lock(mutex_);
340 seekTask_ = nullptr;
341 if (currentState_ == PLAYER_STOPPED || isExit_) {
342 return;
343 }
344
345 if (currentState_ == PLAYER_PLAYBACK_COMPLETE) {
346 currentState_ = PLAYER_PAUSED;
347 }
348
349 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
350 // need keep the seek and seek modes consistent.
351 g_object_set(gstPlayer_, "seek-mode", static_cast<gint>(ChangeSeekModeToGstFlag(mode)), nullptr);
352 GstClockTime time = static_cast<GstClockTime>(position * MICRO);
353 (void)GetPositionInner();
354 seeking_ = true;
355 gst_player_seek(gstPlayer_, time);
356
357 {
358 condVarSeekSync_.wait(lock);
359 MEDIA_LOGD("Seek finised!");
360 }
361 }
362
Stop()363 void GstPlayerCtrl::Stop()
364 {
365 std::unique_lock<std::mutex> lock(mutex_);
366 if (currentState_ <= PLAYER_PREPARING && !preparing_) {
367 isExit_ = true;
368 return;
369 }
370
371 if (currentState_ == PLAYER_PREPARING && preparing_) {
372 MEDIA_LOGD("begin wait stop for current status is preparing!");
373 static constexpr int32_t timeout = 1;
374 condVarPreparingSync_.wait_for(lock, std::chrono::seconds(timeout));
375 MEDIA_LOGD("end wait stop for current status is preparing!");
376 }
377
378 if (appsrcWarp_ != nullptr) {
379 appsrcWarp_->Stop();
380 }
381 if (currentState_ == PLAYER_STOPPED) {
382 return;
383 }
384
385 isExit_ = true;
386 userStop_ = true;
387 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
388 MEDIA_LOGD("Stop start!");
389 g_object_set(gstPlayer_, "exit-block", 1, nullptr);
390 gst_player_stop(gstPlayer_);
391
392 {
393 condVarStopSync_.wait(lock);
394 MEDIA_LOGD("Stop finised!");
395 }
396
397 condVarPlaySync_.notify_all();
398 condVarPauseSync_.notify_all();
399 condVarSeekSync_.notify_all();
400 bufferingStart_ = false;
401 nextSeekFlag_ = false;
402 enableLooping_ = false;
403 speeding_ = false;
404 seeking_ = false;
405 rate_ = DEFAULT_RATE;
406 lastTime_ = 0;
407 if (audioSink_ != nullptr) {
408 g_signal_handler_disconnect(audioSink_, signalIdVolume_);
409 signalIdVolume_ = 0;
410 gst_object_unref(audioSink_);
411 audioSink_ = nullptr;
412 }
413 if (rateTask_ != nullptr) {
414 rateTask_->Cancel();
415 rateTask_ = nullptr;
416 }
417 if (seekTask_ != nullptr) {
418 seekTask_->Cancel();
419 seekTask_ = nullptr;
420 }
421 }
422
SetLoop(bool loop)423 int32_t GstPlayerCtrl::SetLoop(bool loop)
424 {
425 std::unique_lock<std::mutex> lock(mutex_);
426 if (IsLiveMode()) {
427 return MSERR_INVALID_OPERATION;
428 }
429 enableLooping_ = loop;
430 return MSERR_OK;
431 }
432
SetVolume(const float & leftVolume,const float & rightVolume)433 void GstPlayerCtrl::SetVolume(const float &leftVolume, const float &rightVolume)
434 {
435 (void)rightVolume;
436 std::unique_lock<std::mutex> lock(mutex_);
437 volume_ = leftVolume;
438 if (audioSink_ != nullptr) {
439 MEDIA_LOGI("SetVolume(%{public}f) to audio sink", volume_);
440 g_object_set(audioSink_, "volume", volume_, nullptr);
441 }
442 }
443
SetParameter(const Format & param)444 int32_t GstPlayerCtrl::SetParameter(const Format ¶m)
445 {
446 std::unique_lock<std::mutex> lock(mutex_);
447 if (!SetAudioRendererInfo(param)) {
448 MEDIA_LOGE("unsupported params");
449 return MSERR_UNSUPPORT_AUD_PARAMS;
450 }
451
452 return MSERR_OK;
453 }
454
GetPosition()455 uint64_t GstPlayerCtrl::GetPosition()
456 {
457 std::unique_lock<std::mutex> lock(mutex_);
458 return GetPositionInner();
459 }
460
GetPositionInner()461 uint64_t GstPlayerCtrl::GetPositionInner()
462 {
463 CHECK_AND_RETURN_RET_LOG(gstPlayer_ != nullptr, 0, "gstPlayer_ is nullptr");
464
465 if (currentState_ == PLAYER_STOPPED) {
466 return 0;
467 }
468
469 if (currentState_ == PLAYER_PLAYBACK_COMPLETE) {
470 if (IsLiveMode()) {
471 return lastTime_;
472 }
473 return sourceDuration_;
474 }
475
476 if (seeking_ || speeding_) {
477 return lastTime_;
478 }
479
480 GstClockTime position = gst_player_get_position(gstPlayer_);
481 uint64_t curTime = static_cast<uint64_t>(position) / MICRO;
482 curTime = std::min(curTime, sourceDuration_);
483 lastTime_ = curTime;
484 MEDIA_LOGD("GetPosition curTime(%{public}" PRIu64 ") duration(%{public}" PRIu64 ")", curTime, sourceDuration_);
485 return curTime;
486 }
487
GetDuration()488 uint64_t GstPlayerCtrl::GetDuration()
489 {
490 std::unique_lock<std::mutex> lock(mutex_);
491 CHECK_AND_RETURN_RET_LOG(gstPlayer_ != nullptr, 0, "gstPlayer_ is nullptr");
492 if (IsLiveMode()) {
493 return GST_CLOCK_TIME_NONE;
494 }
495 if (currentState_ == PLAYER_STOPPED) {
496 return sourceDuration_;
497 }
498
499 InitDuration();
500 return sourceDuration_;
501 }
502
GetVideoTrackInfo(std::vector<Format> & videoTrack)503 int32_t GstPlayerCtrl::GetVideoTrackInfo(std::vector<Format> &videoTrack)
504 {
505 std::unique_lock<std::mutex> lock(mutex_);
506 CHECK_AND_RETURN_RET_LOG(trackParse_ != nullptr, 0, "trackParse_ is nullptr");
507
508 return trackParse_->GetVideoTrackInfo(videoTrack);
509 }
510
GetAudioTrackInfo(std::vector<Format> & audioTrack)511 int32_t GstPlayerCtrl::GetAudioTrackInfo(std::vector<Format> &audioTrack)
512 {
513 std::unique_lock<std::mutex> lock(mutex_);
514 CHECK_AND_RETURN_RET_LOG(trackParse_ != nullptr, 0, "trackParse_ is nullptr");
515
516 return trackParse_->GetAudioTrackInfo(audioTrack);
517 }
518
GetVideoWidth()519 int32_t GstPlayerCtrl::GetVideoWidth()
520 {
521 std::unique_lock<std::mutex> lock(mutex_);
522 return videoWidth_;
523 }
524
GetVideoHeight()525 int32_t GstPlayerCtrl::GetVideoHeight()
526 {
527 std::unique_lock<std::mutex> lock(mutex_);
528 return videoHeight_;
529 }
530
SetRate(double rate)531 int32_t GstPlayerCtrl::SetRate(double rate)
532 {
533 std::unique_lock<std::mutex> lock(mutex_);
534 if (IsLiveMode()) {
535 return MSERR_INVALID_OPERATION;
536 }
537 auto task = std::make_shared<TaskHandler<void>>([this, rate] { SetRateSync(rate); });
538 if (taskQue_.EnqueueTask(task) != 0) {
539 MEDIA_LOGE("set rate(%{public}lf) fail", rate);
540 return MSERR_INVALID_OPERATION;
541 }
542
543 if (rateTask_ != nullptr) {
544 MEDIA_LOGI("cancel pre rate task(%{public}lf)", rate_);
545 rateTask_->Cancel();
546 }
547 rateTask_ = task;
548 rate_ = rate;
549 return MSERR_OK;
550 }
551
SetRateSync(double rate)552 void GstPlayerCtrl::SetRateSync(double rate)
553 {
554 std::unique_lock<std::mutex> lock(mutex_);
555 if (isExit_) {
556 return;
557 }
558 rateTask_ = nullptr;
559
560 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
561 MEDIA_LOGD("SetRateSync in, rate=(%{public}lf)", rate);
562 (void)GetPositionInner();
563 speeding_ = true;
564 gst_player_set_rate(gstPlayer_, static_cast<gdouble>(rate));
565
566 condVarSeekSync_.wait(lock);
567 MEDIA_LOGD("SetRateSync out, rate=(%{public}lf)", rate);
568 }
569
GetRate()570 double GstPlayerCtrl::GetRate()
571 {
572 std::unique_lock<std::mutex> lock(mutex_);
573 CHECK_AND_RETURN_RET_LOG(gstPlayer_ != nullptr, 1.0, "gstPlayer_ is nullptr");
574
575 MEDIA_LOGD("get rate=%{public}lf", rate_);
576 return rate_;
577 }
578
GetState() const579 PlayerStates GstPlayerCtrl::GetState() const
580 {
581 return currentState_;
582 }
583
GetAudioSink()584 void GstPlayerCtrl::GetAudioSink()
585 {
586 GstElement *playbin = gst_player_get_pipeline(gstPlayer_);
587 CHECK_AND_RETURN_LOG(playbin != nullptr, "playbin is null");
588
589 if (audioSink_ != nullptr) {
590 gst_object_unref(audioSink_);
591 audioSink_ = nullptr;
592 }
593 g_object_get(playbin, "audio-sink", &audioSink_, nullptr);
594
595 CHECK_AND_RETURN_LOG(audioSink_ != nullptr, "get audio sink fail");
596
597 signalIdVolume_ = g_signal_connect(audioSink_, "notify::volume", G_CALLBACK(OnVolumeChangeCb), this);
598
599 gst_object_unref(playbin);
600 }
601
OnStateChangedCb(const GstPlayer * player,GstPlayerState state,GstPlayerCtrl * playerGst)602 void GstPlayerCtrl::OnStateChangedCb(const GstPlayer *player, GstPlayerState state, GstPlayerCtrl *playerGst)
603 {
604 MEDIA_LOGD("OnStateChangedCb gstplayer State changed: %{public}s", gst_player_state_get_name(state));
605 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
606 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
607 playerGst->ProcessStateChanged(player, state);
608 }
609
ProcessStateChanged(const GstPlayer * cbPlayer,GstPlayerState state)610 void GstPlayerCtrl::ProcessStateChanged(const GstPlayer *cbPlayer, GstPlayerState state)
611 {
612 std::unique_lock<std::mutex> lock(mutex_);
613 if (cbPlayer != gstPlayer_) {
614 MEDIA_LOGE("gstplay cb object error: cbPlayer != gstPlayer_");
615 return;
616 }
617
618 PlayerStates newState = PLAYER_IDLE;
619 switch (state) {
620 case GST_PLAYER_STATE_STOPPED: {
621 newState = ProcessStoppedState();
622 break;
623 }
624 case GST_PLAYER_STATE_BUFFERING: {
625 OnBufferingUpdate(std::string(PlayerKeys::PLAYER_BUFFERING_START));
626 bufferingStart_ = true;
627 percent_ = 0;
628 return;
629 }
630 case GST_PLAYER_STATE_PAUSED: {
631 newState = ProcessPausedState();
632 break;
633 }
634 case GST_PLAYER_STATE_PLAYING: {
635 newState = PLAYER_STARTED;
636 break;
637 }
638 default: {
639 return;
640 }
641 }
642
643 if (bufferingStart_) {
644 OnBufferingUpdate(std::string(PlayerKeys::PLAYER_BUFFERING_END));
645 bufferingStart_ = false;
646 }
647
648 MEDIA_LOGD("currentState_ = %{public}d, newState = %{public}d", currentState_, newState);
649 if (newState != PLAYER_IDLE && currentState_ != newState) {
650 OnStateChanged(newState);
651 }
652
653 OnNotify(newState);
654 /* call back sequence: statecb > seekdonecb */
655 OnSeekDone();
656 OnEndOfStream();
657 }
658
OnEndOfStreamCb(const GstPlayer * player,GstPlayerCtrl * playerGst)659 void GstPlayerCtrl::OnEndOfStreamCb(const GstPlayer *player, GstPlayerCtrl *playerGst)
660 {
661 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
662 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
663 return playerGst->ProcessEndOfStream(player);
664 }
665
ProcessEndOfStream(const GstPlayer * cbPlayer)666 void GstPlayerCtrl::ProcessEndOfStream(const GstPlayer *cbPlayer)
667 {
668 if (cbPlayer != gstPlayer_) {
669 MEDIA_LOGE("gstplay cb object error: cbPlayer != gstPlayer_");
670 return;
671 }
672 MEDIA_LOGD("End of stream");
673 endOfStreamCb_ = true;
674 if (IsLiveMode()) {
675 return;
676 }
677
678 if (enableLooping_) {
679 (void)Seek(0, SEEK_PREVIOUS_SYNC);
680 } else {
681 Pause();
682 }
683 }
684
StreamDecErrorParse(const gchar * name,int32_t & errorCode)685 void GstPlayerCtrl::StreamDecErrorParse(const gchar *name, int32_t &errorCode)
686 {
687 if (strstr(name, "aac") != nullptr) {
688 MEDIA_LOGE("tag:MSERR_AUD_DEC_FAILED");
689 errorCode = MSERR_AUD_DEC_FAILED;
690 } else if (strstr(name, "h264") != nullptr || strstr(name, "h265") != nullptr) {
691 MEDIA_LOGE("tag:MSERR_VID_DEC_FAILED");
692 errorCode = MSERR_VID_DEC_FAILED;
693 } else {
694 MEDIA_LOGE("tag:MSERR_UNKNOWN");
695 errorCode = MSERR_UNKNOWN;
696 }
697 }
698
StreamErrorParse(const gchar * name,const GError * err,int32_t & errorCode)699 void GstPlayerCtrl::StreamErrorParse(const gchar *name, const GError *err, int32_t &errorCode)
700 {
701 CHECK_AND_RETURN_LOG(name != nullptr, "name is null");
702 CHECK_AND_RETURN_LOG(err != nullptr, "err is null");
703 MEDIA_LOGE("domain:GST_STREAM_ERROR");
704 auto streamIter = STREAM_TO_SERVICE_ERR_TABLE.find(err->code);
705 if (streamIter != STREAM_TO_SERVICE_ERR_TABLE.end()) {
706 errorCode = streamIter->second;
707 return;
708 }
709 auto streamFuncIter = STREAM_TO_SERVICE_ERR_FUNC_TABLE.find(err->code);
710 if (streamFuncIter != STREAM_TO_SERVICE_ERR_FUNC_TABLE.end()) {
711 streamFuncIter->second(name, errorCode);
712 return;
713 }
714
715 errorCode = MSERR_UNKNOWN;
716 }
717
ResourceErrorParse(const GError * err,int32_t & errorCode)718 void GstPlayerCtrl::ResourceErrorParse(const GError *err, int32_t &errorCode)
719 {
720 CHECK_AND_RETURN_LOG(err != nullptr, "err is null");
721 MEDIA_LOGE("domain:GST_RESOURCE_ERROR");
722 auto resIter = RESOURCE_TO_SERVICE_ERR_TABLE.find(err->code);
723 if (resIter == RESOURCE_TO_SERVICE_ERR_TABLE.end()) {
724 errorCode = MSERR_UNKNOWN;
725 return;
726 }
727 errorCode = resIter->second;
728 }
729
MessageErrorProcess(const char * name,const GError * err,PlayerErrorType & errorType,int32_t & errorCode)730 void GstPlayerCtrl::MessageErrorProcess(const char *name, const GError *err,
731 PlayerErrorType &errorType, int32_t &errorCode)
732 {
733 CHECK_AND_RETURN_LOG(err != nullptr, "err is null");
734 CHECK_AND_RETURN_LOG(name != nullptr, "name is null");
735 char *errMsg = gst_error_get_message(err->domain, err->code);
736 MEDIA_LOGE("errMsg:%{public}s", errMsg);
737 if (err->domain == GST_STREAM_ERROR) {
738 errorType = PLAYER_ERROR;
739 StreamErrorParse(name, err, errorCode);
740 } else if (err->domain == GST_RESOURCE_ERROR) {
741 errorType = PLAYER_ERROR;
742 ResourceErrorParse(err, errorCode);
743 } else {
744 errorType = PLAYER_ERROR_UNKNOWN;
745 errorCode = MSERR_UNKNOWN;
746 }
747 g_free(errMsg);
748 }
749
ErrorProcess(const GstMessage * msg,PlayerErrorType & errorType,int32_t & errorCode)750 void GstPlayerCtrl::ErrorProcess(const GstMessage *msg, PlayerErrorType &errorType, int32_t &errorCode)
751 {
752 CHECK_AND_RETURN_LOG(msg != nullptr, "msg is null");
753 gchar *debug = nullptr;
754 GError *err = nullptr;
755 GstMessage *message = gst_message_copy(msg);
756 CHECK_AND_RETURN_LOG(message != nullptr, "msg copy failed");
757 gst_message_parse_error(message, &err, &debug);
758 if (msg->src == nullptr) {
759 g_clear_error(&err);
760 g_free(debug);
761 gst_message_unref(message);
762 MEDIA_LOGE("msg parse failed");
763 return;
764 }
765 gchar *name = gst_object_get_path_string(msg->src);
766 MessageErrorProcess(name, err, errorType, errorCode);
767 g_clear_error(&err);
768 g_free(debug);
769 g_free(name);
770 gst_message_unref(message);
771 }
772
OnErrorCb(const GstPlayer * player,const GstMessage * msg,GstPlayerCtrl * playerGst)773 void GstPlayerCtrl::OnErrorCb(const GstPlayer *player, const GstMessage *msg, GstPlayerCtrl *playerGst)
774 {
775 MEDIA_LOGE("Received error signal from pipeline.");
776 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
777 CHECK_AND_RETURN_LOG(msg != nullptr, "msg is null");
778 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
779
780 // If looping is enabled, then disable it else will keep looping forever
781 playerGst->enableLooping_ = false;
782 PlayerErrorType errorType = PLAYER_ERROR_UNKNOWN;
783 int32_t errorCode = MSERR_UNKNOWN;
784
785 ErrorProcess(msg, errorType, errorCode);
786
787 std::shared_ptr<IPlayerEngineObs> tempObs = playerGst->obs_.lock();
788 if (tempObs != nullptr) {
789 tempObs->OnError(errorType, errorCode);
790 }
791
792 playerGst->errorFlag_ = true;
793 }
794
OnResolutionChanegdCb(const GstPlayer * player,int32_t width,int32_t height,GstPlayerCtrl * playerGst)795 void GstPlayerCtrl::OnResolutionChanegdCb(const GstPlayer *player,
796 int32_t width, int32_t height, GstPlayerCtrl *playerGst)
797 {
798 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
799 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
800
801 playerGst->OnResolutionChange(width, height);
802 }
803
OnResolutionChange(int32_t width,int32_t height)804 void GstPlayerCtrl::OnResolutionChange(int32_t width, int32_t height)
805 {
806 Format format;
807 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_WIDTH), width);
808 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_HEIGHT), height);
809 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
810 if (tempObs != nullptr) {
811 MEDIA_LOGD("OnResolutionChange width:%{public}d, height:%{public}d", width, height);
812 tempObs->OnInfo(INFO_TYPE_RESOLUTION_CHANGE, 0, format);
813 }
814 videoWidth_ = width;
815 videoHeight_ = height;
816 }
817
OnSeekDoneCb(const GstPlayer * player,guint64 position,GstPlayerCtrl * playerGst)818 void GstPlayerCtrl::OnSeekDoneCb(const GstPlayer *player, guint64 position, GstPlayerCtrl *playerGst)
819 {
820 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
821 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
822 playerGst->ProcessSeekDone(player, static_cast<uint64_t>(position) / MICRO);
823 }
824
ProcessSeekDone(const GstPlayer * cbPlayer,uint64_t position)825 void GstPlayerCtrl::ProcessSeekDone(const GstPlayer *cbPlayer, uint64_t position)
826 {
827 if (cbPlayer != gstPlayer_) {
828 MEDIA_LOGE("gstplay cb object error: cbPlayer != gstPlayer_");
829 return;
830 }
831
832 position = std::min(position, sourceDuration_);
833 seekDoneNeedCb_ = true;
834 seekDonePosition_ = position;
835 MEDIA_LOGI("gstplay seek Done: (%{public}" PRIu64 ")", seekDonePosition_);
836 }
837
OnSourceSetupCb(const GstPlayer * player,GstElement * src,GstPlayerCtrl * playerGst)838 void GstPlayerCtrl::OnSourceSetupCb(const GstPlayer *player, GstElement *src, GstPlayerCtrl *playerGst)
839 {
840 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
841 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
842 CHECK_AND_RETURN_LOG(src != nullptr, "self is null");
843 if (playerGst->appsrcWarp_ == nullptr) {
844 MEDIA_LOGD("appsrc is null, is not stream mode");
845 return;
846 }
847 GstElementFactory *elementFac = gst_element_get_factory(src);
848 const gchar *eleTypeName = g_type_name(gst_element_factory_get_element_type(elementFac));
849 if ((eleTypeName != nullptr) && (strstr(eleTypeName, "GstAppSrc") != nullptr)) {
850 (void)playerGst->appsrcWarp_->SetAppsrc(src);
851 }
852 }
853
OnBufferingTimeCb(const GstPlayer * player,guint64 bufferingTime,guint mqNumId,GstPlayerCtrl * playerGst)854 void GstPlayerCtrl::OnBufferingTimeCb(const GstPlayer *player, guint64 bufferingTime,
855 guint mqNumId, GstPlayerCtrl *playerGst)
856 {
857 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
858 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
859 playerGst->ProcessBufferingTime(player, bufferingTime, mqNumId);
860 }
861
ProcessBufferingTime(const GstPlayer * cbPlayer,guint64 bufferingTime,guint mqNumId)862 void GstPlayerCtrl::ProcessBufferingTime(const GstPlayer *cbPlayer, guint64 bufferingTime, guint mqNumId)
863 {
864 if (cbPlayer != gstPlayer_) {
865 MEDIA_LOGE("gstplay cb object error: cbPlayer != gstPlayer_");
866 return;
867 }
868
869 if (currentState_ == PLAYER_PLAYBACK_COMPLETE) {
870 return;
871 }
872
873 bufferingTime = bufferingTime / MICRO;
874 if (bufferingTime > BUFFER_TIME_DEFAULT) {
875 bufferingTime = BUFFER_TIME_DEFAULT;
876 }
877
878 mqBufferingTime_[mqNumId] = bufferingTime;
879
880 MEDIA_LOGD("ProcessBufferingTime(%{public}" PRIu64 "), mqNumId = %{public}u mqNumUseBuffering_ = %{public}u",
881 bufferingTime, mqNumId, mqNumUseBuffering_);
882
883 if (mqBufferingTime_.size() != mqNumUseBuffering_) {
884 return;
885 }
886
887 guint64 mqBufferingTime = BUFFER_TIME_DEFAULT;
888 for (auto iter = mqBufferingTime_.begin(); iter != mqBufferingTime_.end(); ++iter) {
889 if (iter->second < mqBufferingTime) {
890 mqBufferingTime = iter->second;
891 }
892 }
893
894 if (bufferingTime_ != mqBufferingTime) {
895 bufferingTime_ = mqBufferingTime;
896 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
897 if (tempObs != nullptr) {
898 Format format;
899 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_CACHED_DURATION),
900 static_cast<int32_t>(mqBufferingTime));
901 tempObs->OnInfo(INFO_TYPE_BUFFERING_UPDATE, 0, format);
902 }
903 }
904 }
905
OnCachedPercentCb(const GstPlayer * player,guint percent,GstPlayerCtrl * playerGst)906 void GstPlayerCtrl::OnCachedPercentCb(const GstPlayer *player, guint percent, GstPlayerCtrl *playerGst)
907 {
908 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
909 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
910 playerGst->ProcessCachedPercent(player, percent);
911 }
912
ProcessCachedPercent(const GstPlayer * cbPlayer,int32_t percent)913 void GstPlayerCtrl::ProcessCachedPercent(const GstPlayer *cbPlayer, int32_t percent)
914 {
915 if (cbPlayer != gstPlayer_) {
916 MEDIA_LOGE("gstplay cb object error: cbPlayer != gstPlayer_");
917 return;
918 }
919
920 if (currentState_ == PLAYER_PLAYBACK_COMPLETE) {
921 return;
922 }
923
924 int32_t lastPercent = percent_;
925 if (percent >= BUFFER_HIGH_PERCENT_DEFAULT) {
926 percent_ = BUFFER_FULL_PERCENT_DEFAULT;
927 } else {
928 int per = percent * BUFFER_FULL_PERCENT_DEFAULT / BUFFER_HIGH_PERCENT_DEFAULT;
929 if (percent_ < per) {
930 percent_ = per;
931 }
932 }
933
934 if (lastPercent == percent_) {
935 return;
936 }
937
938 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
939 if (tempObs != nullptr) {
940 Format format;
941 (void)format.PutIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT), percent_);
942 MEDIA_LOGD("percent = (%{public}d), percent_ = %{public}d, 0x%{public}06" PRIXPTR "",
943 percent, percent_, FAKE_POINTER(this));
944 tempObs->OnInfo(INFO_TYPE_BUFFERING_UPDATE, 0, format);
945 }
946 }
947
OnMqNumUseBufferingCb(const GstPlayer * player,guint mqNumUseBuffering,GstPlayerCtrl * playerGst)948 void GstPlayerCtrl::OnMqNumUseBufferingCb(const GstPlayer *player, guint mqNumUseBuffering, GstPlayerCtrl *playerGst)
949 {
950 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
951 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
952 playerGst->ProcessMqNumUseBuffering(player, mqNumUseBuffering);
953 }
954
ProcessMqNumUseBuffering(const GstPlayer * cbPlayer,uint32_t mqNumUseBuffering)955 void GstPlayerCtrl::ProcessMqNumUseBuffering(const GstPlayer *cbPlayer, uint32_t mqNumUseBuffering)
956 {
957 if (cbPlayer != gstPlayer_) {
958 MEDIA_LOGE("gstplay cb object error: cbPlayer != gstPlayer_");
959 return;
960 }
961
962 MEDIA_LOGD("mqNumUseBuffering = (%{public}u)", mqNumUseBuffering);
963 mqNumUseBuffering_ = mqNumUseBuffering;
964 }
965
OnPositionUpdatedCb(const GstPlayer * player,guint64 position,GstPlayerCtrl * playerGst)966 void GstPlayerCtrl::OnPositionUpdatedCb(const GstPlayer *player, guint64 position, GstPlayerCtrl *playerGst)
967 {
968 CHECK_AND_RETURN_LOG(player != nullptr, "player is null");
969 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
970 playerGst->ProcessPositionUpdated(player, static_cast<uint64_t>(position) / MICRO);
971 }
972
ProcessPositionUpdated(const GstPlayer * cbPlayer,uint64_t position)973 void GstPlayerCtrl::ProcessPositionUpdated(const GstPlayer *cbPlayer, uint64_t position)
974 {
975 if (cbPlayer != gstPlayer_) {
976 MEDIA_LOGE("gstplay cb object error: cbPlayer != gstPlayer_");
977 return;
978 }
979 lastTime_ = position;
980
981 // position = 99643, duration_ = 99591
982 position = std::min(position, sourceDuration_);
983 Format format;
984 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
985 if (tempObs != nullptr) {
986 MEDIA_LOGD("ProcessPositionUpdated(%{public}" PRIu64 "), 0x%{public}06" PRIXPTR "",
987 position, FAKE_POINTER(this));
988 tempObs->OnInfo(INFO_TYPE_POSITION_UPDATE, static_cast<int32_t>(position), format);
989 }
990 }
991
OnVolumeChangeCb(const GObject * combiner,const GParamSpec * pspec,const GstPlayerCtrl * playerGst)992 void GstPlayerCtrl::OnVolumeChangeCb(const GObject *combiner, const GParamSpec *pspec, const GstPlayerCtrl *playerGst)
993 {
994 (void)combiner;
995 (void)pspec;
996
997 MEDIA_LOGI("OnVolumeChangeCb in");
998 CHECK_AND_RETURN_LOG(playerGst != nullptr, "playerGst is null");
999 playerGst->OnVolumeChange();
1000 }
1001
OnVolumeChange() const1002 void GstPlayerCtrl::OnVolumeChange() const
1003 {
1004 Format format;
1005 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
1006 if (tempObs != nullptr) {
1007 MEDIA_LOGI("OnVolumeChange");
1008 tempObs->OnInfo(INFO_TYPE_VOLUME_CHANGE, 0, format);
1009 }
1010 }
1011
OnStateChanged(PlayerStates state)1012 void GstPlayerCtrl::OnStateChanged(PlayerStates state)
1013 {
1014 if (state == PLAYER_PREPARED) {
1015 InitDuration();
1016 GetAudioSink();
1017 MEDIA_LOGW("KPI-TRACE: prepared");
1018 }
1019
1020 currentState_ = state;
1021 MEDIA_LOGI("On State callback state: %{public}d", state);
1022 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
1023 Format format;
1024 if (tempObs != nullptr) {
1025 MEDIA_LOGD("OnStateChanged %{public}d", state);
1026 tempObs->OnInfo(INFO_TYPE_STATE_CHANGE, static_cast<int32_t>(state), format);
1027 }
1028 }
1029
OnNotify(PlayerStates state)1030 void GstPlayerCtrl::OnNotify(PlayerStates state)
1031 {
1032 switch (state) {
1033 case PLAYER_PREPARED:
1034 condVarPauseSync_.notify_all();
1035 condVarPreparingSync_.notify_all();
1036 preparing_ = false;
1037 break;
1038 case PLAYER_STARTED:
1039 condVarPlaySync_.notify_all();
1040 break;
1041 case PLAYER_PAUSED:
1042 case PLAYER_PLAYBACK_COMPLETE:
1043 condVarPauseSync_.notify_all();
1044 break;
1045 case PLAYER_STOPPED:
1046 condVarStopSync_.notify_all();
1047 break;
1048 default:
1049 break;
1050 }
1051 }
1052
OnSeekDone()1053 void GstPlayerCtrl::OnSeekDone()
1054 {
1055 if (seekDoneNeedCb_) {
1056 MEDIA_LOGI("On Seek Done: (%{public}" PRIu64 ")", seekDonePosition_);
1057 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
1058 Format format;
1059 if (tempObs != nullptr) {
1060 if (speeding_) {
1061 tempObs->OnInfo(INFO_TYPE_SPEEDDONE, 0, format);
1062 speeding_ = false;
1063 } else {
1064 tempObs->OnInfo(INFO_TYPE_SEEKDONE, static_cast<int32_t>(seekDonePosition_), format);
1065 seeking_ = false;
1066 }
1067 }
1068 seekDoneNeedCb_ = false;
1069 condVarSeekSync_.notify_all();
1070 }
1071 }
1072
OnEndOfStream()1073 void GstPlayerCtrl::OnEndOfStream()
1074 {
1075 if (endOfStreamCb_) {
1076 MEDIA_LOGI("On EndOfStream: loop is %{public}d", enableLooping_);
1077 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
1078 Format format;
1079 if (tempObs != nullptr) {
1080 tempObs->OnInfo(INFO_TYPE_EOS, static_cast<int32_t>(enableLooping_), format);
1081 }
1082 endOfStreamCb_ = false;
1083 }
1084 }
1085
OnMessage(int32_t extra) const1086 void GstPlayerCtrl::OnMessage(int32_t extra) const
1087 {
1088 MEDIA_LOGI("On Message callback info: %{public}d", extra);
1089 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
1090 Format format;
1091 if (tempObs != nullptr) {
1092 tempObs->OnInfo(INFO_TYPE_MESSAGE, extra, format);
1093 }
1094 }
1095
OnBufferingUpdate(const std::string Message) const1096 void GstPlayerCtrl::OnBufferingUpdate(const std::string Message) const
1097 {
1098 MEDIA_LOGI("On Message callback info: %{public}s", Message.c_str());
1099 std::shared_ptr<IPlayerEngineObs> tempObs = obs_.lock();
1100 if (tempObs != nullptr) {
1101 Format format;
1102 (void)format.PutIntValue(Message, 0);
1103 tempObs->OnInfo(INFO_TYPE_BUFFERING_UPDATE, 0, format);
1104 }
1105 }
1106
ProcessStoppedState()1107 PlayerStates GstPlayerCtrl::ProcessStoppedState()
1108 {
1109 PlayerStates newState = PLAYER_STOPPED;
1110 if (userStop_ || errorFlag_) {
1111 userStop_ = false;
1112 } else if (IsLiveMode()) {
1113 if (currentState_ == PLAYER_STARTED) {
1114 newState = PLAYER_PLAYBACK_COMPLETE;
1115 }
1116 } else {
1117 if (currentState_ == PLAYER_STARTED) {
1118 newState = PLAYER_STARTED;
1119 locatedInEos_ = enableLooping_ ? false : true;
1120 }
1121 }
1122
1123 if (currentState_ == PLAYER_PREPARING) {
1124 // return stop when vidoe/audio prepare failed, notify pause finished
1125 condVarPauseSync_.notify_all();
1126 condVarPreparingSync_.notify_all();
1127 preparing_ = false;
1128 }
1129 return newState;
1130 }
1131
ProcessPausedState()1132 PlayerStates GstPlayerCtrl::ProcessPausedState()
1133 {
1134 PlayerStates newState = PLAYER_PAUSED;
1135
1136 if ((currentState_ == PLAYER_PREPARING) ||
1137 (currentState_ == PLAYER_STOPPED) ||
1138 (currentState_ == PLAYER_PREPARED)) {
1139 newState = PLAYER_PREPARED;
1140 } else if (currentState_ == PLAYER_PLAYBACK_COMPLETE) {
1141 newState = PLAYER_PLAYBACK_COMPLETE;
1142 } else if (currentState_ == PLAYER_STARTED && locatedInEos_) {
1143 newState = PLAYER_PLAYBACK_COMPLETE;
1144 locatedInEos_ = false;
1145 } else {
1146 newState = PLAYER_PAUSED;
1147 }
1148 MEDIA_LOGI("ProcessPausedState currentStatus: %{public}d, newState: %{public}d", currentState_, newState);
1149
1150 return newState;
1151 }
1152
InitDuration()1153 void GstPlayerCtrl::InitDuration()
1154 {
1155 CHECK_AND_RETURN_LOG(gstPlayer_ != nullptr, "gstPlayer_ is nullptr");
1156 GstClockTime time = gst_player_get_duration(gstPlayer_);
1157 if (time != GST_CLOCK_TIME_NONE) {
1158 sourceDuration_ = static_cast<uint64_t>(time) / MICRO;
1159 } else {
1160 sourceDuration_ = GST_CLOCK_TIME_NONE;
1161 }
1162
1163 MEDIA_LOGD("InitDuration duration(%{public}" PRIu64 ")", sourceDuration_);
1164 }
1165
IsLiveMode() const1166 bool GstPlayerCtrl::IsLiveMode() const
1167 {
1168 if (appsrcWarp_ != nullptr && appsrcWarp_->IsLiveMode()) {
1169 return true;
1170 }
1171
1172 if (sourceDuration_ == GST_CLOCK_TIME_NONE) {
1173 return true;
1174 }
1175
1176 return false;
1177 }
1178
SetAudioRendererInfo(const Format & param)1179 bool GstPlayerCtrl::SetAudioRendererInfo(const Format ¶m)
1180 {
1181 CHECK_AND_RETURN_RET_LOG(audioSink_ != nullptr, false, "audioSink_ is nullptr");
1182
1183 int32_t contentType = 0;
1184 int32_t streamUsage = 0;
1185
1186 if (param.GetIntValue(PlayerKeys::CONTENT_TYPE, contentType) &&
1187 param.GetIntValue(PlayerKeys::STREAM_USAGE, streamUsage)) {
1188 int32_t rendererInfo(0);
1189 CHECK_AND_RETURN_RET(streamUsage >= 0 && contentType >= 0, false);
1190 rendererInfo |= (contentType | (static_cast<uint32_t>(streamUsage) <<
1191 AudioStandard::RENDERER_STREAM_USAGE_SHIFT));
1192 g_object_set(audioSink_, "audio-renderer-desc", rendererInfo, nullptr);
1193 return true;
1194 } else {
1195 MEDIA_LOGI("parameter doesn't contain content_type or stream_usage");
1196 return false;
1197 }
1198 }
1199 } // namespace Media
1200 } // namespace OHOS
1201