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
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PlayerEngineGstImpl"};
25 }
26
27 namespace OHOS {
28 namespace Media {
29 constexpr float EPSINON = 0.0001;
30 constexpr float SPEED_0_75_X = 0.75;
31 constexpr float SPEED_1_00_X = 1.00;
32 constexpr float SPEED_1_25_X = 1.25;
33 constexpr float SPEED_1_75_X = 1.75;
34 constexpr float SPEED_2_00_X = 2.00;
35 constexpr size_t MAX_URI_SIZE = 4096;
36 constexpr uint64_t RING_BUFFER_MAX_SIZE = 5242880; // 5 * 1024 * 1024
37
PlayerEngineGstImpl()38 PlayerEngineGstImpl::PlayerEngineGstImpl()
39 {
40 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
41 }
42
~PlayerEngineGstImpl()43 PlayerEngineGstImpl::~PlayerEngineGstImpl()
44 {
45 (void)Reset();
46 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
47 }
48
IsFileUrl(const std::string & url) const49 bool PlayerEngineGstImpl::IsFileUrl(const std::string &url) const
50 {
51 if (url.find("://") == std::string::npos || url.find("file://") == 0) {
52 return true;
53 }
54 return false;
55 }
56
GetRealPath(const std::string & url,std::string & realUrlPath) const57 int32_t PlayerEngineGstImpl::GetRealPath(const std::string &url, std::string &realUrlPath) const
58 {
59 std::string fileHead = "file://";
60 std::string tempUrlPath;
61
62 if (url.find(fileHead) == 0 && url.size() > fileHead.size()) {
63 tempUrlPath = url.substr(fileHead.size());
64 } else {
65 tempUrlPath = url;
66 }
67
68 bool ret = PathToRealPath(tempUrlPath, realUrlPath);
69 CHECK_AND_RETURN_RET_LOG(ret, MSERR_OPEN_FILE_FAILED,
70 "invalid url. The Url (%{public}s) path may be invalid.", url.c_str());
71
72 if (access(realUrlPath.c_str(), R_OK) != 0) {
73 return MSERR_FILE_ACCESS_FAILED;
74 }
75
76 return MSERR_OK;
77 }
78
SetSource(const std::string & url)79 int32_t PlayerEngineGstImpl::SetSource(const std::string &url)
80 {
81 std::unique_lock<std::mutex> lock(mutex_);
82 CHECK_AND_RETURN_RET_LOG(!url.empty(), MSERR_INVALID_VAL, "input url is empty!");
83 CHECK_AND_RETURN_RET_LOG(url.length() <= MAX_URI_SIZE, MSERR_INVALID_VAL, "input url length is invalid!");
84
85 std::string realUriPath;
86 int32_t ret = MSERR_OK;
87
88 if (IsFileUrl(url)) {
89 ret = GetRealPath(url, realUriPath);
90 if (ret != MSERR_OK) {
91 return ret;
92 }
93 url_ = "file://" + realUriPath;
94 } else {
95 url_ = url;
96 }
97
98 MEDIA_LOGD("set player source: %{public}s", url_.c_str());
99 return ret;
100 }
101
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)102 int32_t PlayerEngineGstImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
103 {
104 std::unique_lock<std::mutex> lock(mutex_);
105 CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "input dataSrc is empty!");
106 appsrcWarp_ = GstAppsrcWarp::Create(dataSrc);
107 CHECK_AND_RETURN_RET_LOG(appsrcWarp_ != nullptr, MSERR_NO_MEMORY, "new appsrcwarp failed!");
108 return MSERR_OK;
109 }
110
SetObs(const std::weak_ptr<IPlayerEngineObs> & obs)111 int32_t PlayerEngineGstImpl::SetObs(const std::weak_ptr<IPlayerEngineObs> &obs)
112 {
113 std::unique_lock<std::mutex> lock(mutex_);
114 obs_ = obs;
115 return MSERR_OK;
116 }
117
SetVideoSurface(sptr<Surface> surface)118 int32_t PlayerEngineGstImpl::SetVideoSurface(sptr<Surface> surface)
119 {
120 std::unique_lock<std::mutex> lock(mutex_);
121 CHECK_AND_RETURN_RET_LOG(surface != nullptr, MSERR_INVALID_VAL, "surface is nullptr");
122
123 producerSurface_ = surface;
124 return MSERR_OK;
125 }
126
Prepare()127 int32_t PlayerEngineGstImpl::Prepare()
128 {
129 std::unique_lock<std::mutex> lock(mutex_);
130 MEDIA_LOGD("Prepare in");
131
132 int32_t ret = GstPlayerInit();
133 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "GstPlayerInit failed");
134
135 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_VAL, "playerCtrl_ is nullptr");
136 playerCtrl_->Prepare();
137
138 if (playerCtrl_->GetState() != PLAYER_PREPARED) {
139 MEDIA_LOGE("gstplayer prepare failed");
140 GstPlayerDeInit();
141 return MSERR_INVALID_VAL;
142 }
143
144 // The duration of some resources without header information cannot be obtained.
145 MEDIA_LOGD("Prepared ok out");
146 return MSERR_OK;
147 }
148
PrepareAsync()149 int32_t PlayerEngineGstImpl::PrepareAsync()
150 {
151 std::unique_lock<std::mutex> lock(mutex_);
152 MEDIA_LOGD("Prepare in");
153
154 int32_t ret = GstPlayerInit();
155 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "GstPlayerInit failed");
156
157 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_VAL, "playerCtrl_ is nullptr");
158 playerCtrl_->PrepareAsync();
159
160 // The duration of some resources without header information cannot be obtained.
161 MEDIA_LOGD("Prepared ok out");
162 return MSERR_OK;
163 }
164
PlayerLoop()165 void PlayerEngineGstImpl::PlayerLoop()
166 {
167 MEDIA_LOGD("PlayerLoop in");
168 playerBuild_ = std::make_unique<GstPlayerBuild>();
169 CHECK_AND_RETURN_LOG(playerBuild_ != nullptr, "playerBuild_ is nullptr");
170
171 rendererCtrl_ = playerBuild_->BuildRendererCtrl(producerSurface_);
172 CHECK_AND_RETURN_LOG(rendererCtrl_ != nullptr, "rendererCtrl_ is nullptr");
173
174 playerCtrl_ = playerBuild_->BuildPlayerCtrl();
175 CHECK_AND_RETURN_LOG(playerCtrl_ != nullptr, "playerCtrl_ is nullptr");
176
177 condVarSync_.notify_all();
178
179 MEDIA_LOGD("Start the player loop");
180 playerBuild_->CreateLoop();
181 MEDIA_LOGD("Stop the player loop");
182 }
183
GstPlayerInit()184 int32_t PlayerEngineGstImpl::GstPlayerInit()
185 {
186 if (gstPlayerInit_) {
187 return MSERR_OK;
188 }
189
190 MEDIA_LOGD("GstPlayerInit in");
191 playerThread_.reset(new(std::nothrow) std::thread(&PlayerEngineGstImpl::PlayerLoop, this));
192 CHECK_AND_RETURN_RET_LOG(playerThread_ != nullptr, MSERR_NO_MEMORY, "new std::thread failed.");
193
194 if (!playerCtrl_) {
195 MEDIA_LOGD("Player not yet initialized, wait for 1 second");
196 std::unique_lock<std::mutex> lockSync(mutexSync_);
197 (void)condVarSync_.wait_for(lockSync, std::chrono::seconds(1));
198 if (playerCtrl_ == nullptr) {
199 MEDIA_LOGE("gstplayer initialized failed");
200 GstPlayerDeInit();
201 return MSERR_INVALID_VAL;
202 }
203 }
204
205 int ret = GstPlayerPrepare();
206 if (ret != MSERR_OK) {
207 MEDIA_LOGE("GstPlayerPrepare failed");
208 GstPlayerDeInit();
209 return MSERR_INVALID_VAL;
210 }
211
212 playerBuild_->WaitMainLoopStart();
213
214 MEDIA_LOGD("GstPlayerInit out");
215 gstPlayerInit_ = true;
216 return MSERR_OK;
217 }
218
GstPlayerDeInit()219 void PlayerEngineGstImpl::GstPlayerDeInit()
220 {
221 if (playerBuild_ != nullptr) {
222 playerBuild_->DestroyLoop();
223 }
224
225 if (playerThread_ != nullptr && playerThread_->joinable()) {
226 playerThread_->join();
227 }
228
229 rendererCtrl_ = nullptr;
230 playerCtrl_ = nullptr;
231 playerBuild_ = nullptr;
232 gstPlayerInit_ = false;
233 appsrcWarp_ = nullptr;
234 }
235
GstPlayerPrepare() const236 int32_t PlayerEngineGstImpl::GstPlayerPrepare() const
237 {
238 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_VAL, "playerCtrl_ is nullptr");
239 int32_t ret;
240 if (appsrcWarp_ == nullptr) {
241 ret = playerCtrl_->SetUrl(url_);
242 playerCtrl_->SetRingBufferMaxSize(RING_BUFFER_MAX_SIZE);
243 playerCtrl_->SetBufferingInfo();
244 playerCtrl_->SetHttpTimeOut();
245 } else {
246 ret = playerCtrl_->SetSource(appsrcWarp_);
247 }
248 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "SetUrl failed");
249
250 ret = rendererCtrl_->SetCallbacks(obs_);
251 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "SetCallbacks failed");
252
253 ret = playerCtrl_->SetCallbacks(obs_);
254 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "SetCallbacks failed");
255
256 if (producerSurface_ == nullptr) {
257 playerCtrl_->SetVideoTrack(false);
258 }
259 return MSERR_OK;
260 }
261
Play()262 int32_t PlayerEngineGstImpl::Play()
263 {
264 std::unique_lock<std::mutex> lock(mutex_);
265 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
266
267 MEDIA_LOGD("Play in");
268 playerCtrl_->Play();
269 return MSERR_OK;
270 }
271
Pause()272 int32_t PlayerEngineGstImpl::Pause()
273 {
274 std::unique_lock<std::mutex> lock(mutex_);
275 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
276
277 playerCtrl_->Pause();
278 return MSERR_OK;
279 }
280
GetCurrentTime(int32_t & currentTime)281 int32_t PlayerEngineGstImpl::GetCurrentTime(int32_t ¤tTime)
282 {
283 std::unique_lock<std::mutex> lock(mutex_);
284
285 currentTime = -1;
286 if (playerCtrl_ != nullptr) {
287 uint64_t tempTime = playerCtrl_->GetPosition();
288 currentTime = static_cast<int32_t>(tempTime);
289 MEDIA_LOGD("Time in milli seconds: %{public}d", currentTime);
290 }
291 return MSERR_OK;
292 }
293
GetVideoTrackInfo(std::vector<Format> & videoTrack)294 int32_t PlayerEngineGstImpl::GetVideoTrackInfo(std::vector<Format> &videoTrack)
295 {
296 std::unique_lock<std::mutex> lock(mutex_);
297 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
298
299 int32_t retVal = playerCtrl_->GetVideoTrackInfo(videoTrack);
300 return retVal;
301 }
302
GetAudioTrackInfo(std::vector<Format> & audioTrack)303 int32_t PlayerEngineGstImpl::GetAudioTrackInfo(std::vector<Format> &audioTrack)
304 {
305 std::unique_lock<std::mutex> lock(mutex_);
306 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
307
308 int32_t retVal = playerCtrl_->GetAudioTrackInfo(audioTrack);
309 return retVal;
310 }
311
GetVideoWidth()312 int32_t PlayerEngineGstImpl::GetVideoWidth()
313 {
314 std::unique_lock<std::mutex> lock(mutex_);
315 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
316
317 return playerCtrl_->GetVideoWidth();
318 }
319
GetVideoHeight()320 int32_t PlayerEngineGstImpl::GetVideoHeight()
321 {
322 std::unique_lock<std::mutex> lock(mutex_);
323 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
324
325 return playerCtrl_->GetVideoHeight();
326 }
327
GetDuration(int32_t & duration)328 int32_t PlayerEngineGstImpl::GetDuration(int32_t &duration)
329 {
330 std::unique_lock<std::mutex> lock(mutex_);
331
332 duration = 0;
333 if (playerCtrl_ != nullptr) {
334 uint64_t tempDura = playerCtrl_->GetDuration();
335 if (tempDura != GST_CLOCK_TIME_NONE) {
336 duration = static_cast<int32_t>(tempDura);
337 } else {
338 duration = -1;
339 MEDIA_LOGD("it's live mode");
340 }
341
342 MEDIA_LOGD("Duration in milli seconds: %{public}d", duration);
343 }
344 return MSERR_OK;
345 }
346
ChangeModeToSpeed(const PlaybackRateMode & mode) const347 double PlayerEngineGstImpl::ChangeModeToSpeed(const PlaybackRateMode &mode) const
348 {
349 if (mode == SPEED_FORWARD_0_75_X) {
350 return SPEED_0_75_X;
351 }
352 if (mode == SPEED_FORWARD_1_00_X) {
353 return SPEED_1_00_X;
354 }
355 if (mode == SPEED_FORWARD_1_25_X) {
356 return SPEED_1_25_X;
357 }
358 if (mode == SPEED_FORWARD_1_75_X) {
359 return SPEED_1_75_X;
360 }
361 if (mode == SPEED_FORWARD_2_00_X) {
362 return SPEED_2_00_X;
363 }
364
365 MEDIA_LOGW("unknown mode:%{public}d, return default speed(SPEED_1_00_X)", mode);
366
367 return SPEED_1_00_X;
368 }
369
ChangeSpeedToMode(double rate) const370 PlaybackRateMode PlayerEngineGstImpl::ChangeSpeedToMode(double rate) const
371 {
372 if (abs(rate - SPEED_0_75_X) < EPSINON) {
373 return SPEED_FORWARD_0_75_X;
374 }
375 if (abs(rate - SPEED_1_00_X) < EPSINON) {
376 return SPEED_FORWARD_1_00_X;
377 }
378 if (abs(rate - SPEED_1_25_X) < EPSINON) {
379 return SPEED_FORWARD_1_25_X;
380 }
381 if (abs(rate - SPEED_1_75_X) < EPSINON) {
382 return SPEED_FORWARD_1_75_X;
383 }
384 if (abs(rate - SPEED_2_00_X) < EPSINON) {
385 return SPEED_FORWARD_2_00_X;
386 }
387
388 MEDIA_LOGW("unknown rate:%{public}lf, return default speed(SPEED_FORWARD_1_00_X)", rate);
389
390 return SPEED_FORWARD_1_00_X;
391 }
392
SetPlaybackSpeed(PlaybackRateMode mode)393 int32_t PlayerEngineGstImpl::SetPlaybackSpeed(PlaybackRateMode mode)
394 {
395 std::unique_lock<std::mutex> lock(mutex_);
396 if (playerCtrl_ != nullptr) {
397 double rate = ChangeModeToSpeed(mode);
398 return playerCtrl_->SetRate(rate);
399 }
400 return MSERR_OK;
401 }
402
GetPlaybackSpeed(PlaybackRateMode & mode)403 int32_t PlayerEngineGstImpl::GetPlaybackSpeed(PlaybackRateMode &mode)
404 {
405 std::unique_lock<std::mutex> lock(mutex_);
406 if (playerCtrl_ != nullptr) {
407 double rate = playerCtrl_->GetRate();
408 mode = ChangeSpeedToMode(rate);
409 }
410 return MSERR_OK;
411 }
412
SetLooping(bool loop)413 int32_t PlayerEngineGstImpl::SetLooping(bool loop)
414 {
415 std::unique_lock<std::mutex> lock(mutex_);
416 if (playerCtrl_ != nullptr) {
417 MEDIA_LOGD("SetLooping in");
418 return playerCtrl_->SetLoop(loop);
419 }
420 return MSERR_OK;
421 }
422
SetParameter(const Format & param)423 int32_t PlayerEngineGstImpl::SetParameter(const Format ¶m)
424 {
425 std::unique_lock<std::mutex> lock(mutex_);
426 if (playerCtrl_ != nullptr) {
427 return playerCtrl_->SetParameter(param);
428 }
429
430 return MSERR_OK;
431 }
432
Stop()433 int32_t PlayerEngineGstImpl::Stop()
434 {
435 std::unique_lock<std::mutex> lock(mutex_);
436 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
437
438 MEDIA_LOGD("Stop in");
439 playerCtrl_->Stop();
440 return MSERR_OK;
441 }
442
Reset()443 int32_t PlayerEngineGstImpl::Reset()
444 {
445 std::unique_lock<std::mutex> lock(mutex_);
446 MEDIA_LOGD("Reset in");
447 if (playerCtrl_ != nullptr) {
448 playerCtrl_->Stop();
449 }
450 GstPlayerDeInit();
451 return MSERR_OK;
452 }
453
Seek(int32_t mSeconds,PlayerSeekMode mode)454 int32_t PlayerEngineGstImpl::Seek(int32_t mSeconds, PlayerSeekMode mode)
455 {
456 std::unique_lock<std::mutex> lock(mutex_);
457 CHECK_AND_RETURN_RET_LOG(playerCtrl_ != nullptr, MSERR_INVALID_OPERATION, "playerCtrl_ is nullptr");
458 CHECK_AND_RETURN_RET_LOG(mSeconds >= 0, MSERR_INVALID_OPERATION, "seek time must >= 0");
459 MEDIA_LOGD("Seek in %{public}d", mSeconds);
460
461 uint64_t position = static_cast<uint64_t>(mSeconds);
462 return playerCtrl_->Seek(position, mode);
463 }
464
SetVolume(float leftVolume,float rightVolume)465 int32_t PlayerEngineGstImpl::SetVolume(float leftVolume, float rightVolume)
466 {
467 std::unique_lock<std::mutex> lock(mutex_);
468 if (playerCtrl_ != nullptr) {
469 MEDIA_LOGD("SetVolume in");
470 playerCtrl_->SetVolume(leftVolume, rightVolume);
471 }
472 return MSERR_OK;
473 }
474 } // namespace Media
475 } // namespace OHOS
476