• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "player_engine_gst_impl.h"
17 
18 #include <unistd.h>
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "directory_ex.h"
22 
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 &currentTime)
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 &param)
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