RDK Documentation (Open Sourced RDK Components)
mediaplayergeneric.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2018 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 #include "mediaplayergeneric.h"
20 
21 #include <fstream>
22 #include <limits>
23 #include <mutex>
24 #include <sstream>
25 #include <streambuf>
26 #include <string>
27 #include <unordered_map>
28 
29 #include <jansson.h>
30 #include <math.h>
31 
32 #include "logger.h"
33 
34 namespace {
35 
36 const char* kMediaConfigFilePath = "/etc/webkit_media_player_settings.json";
37 std::unordered_map<std::string, std::string> gMediaConfig;
38 bool gFlagGetVideoSinkFromPlaybin = true;
39 
40 bool loadMediaConfig(const char* configPath)
41 {
42  if (!gMediaConfig.empty())
43  return true;
44 
45  std::ifstream configStream(configPath);
46  if (!configStream.good())//CID:127521- Initialization
47  return false;
48 
49  std::string configBuffer((std::istreambuf_iterator<char>(configStream)),
50  std::istreambuf_iterator<char>());
51 
52  json_t *root;
53  json_error_t error;
54  root = json_loads(configBuffer.c_str(), 0, &error);
55  if(!root)
56  return false;
57 
58  if(!json_is_object(root))
59  {
60  json_decref(root);
61  return false;
62  }
63 
64  LOG_INFO("Media config:");
65  const char *key;
66  json_t *value;
67  json_object_foreach(root, key, value)
68  {
69  if (!json_is_string(value))
70  continue;
71  LOG_INFO("\t%s=%s", key, json_string_value(value));
72  gMediaConfig[std::string(key)] = json_string_value(value);
73  }
74 
75  // Set flags
76  auto it = gMediaConfig.find("get-video-sink-from-playbin");
77  if (it != gMediaConfig.end())
78  {
79  gFlagGetVideoSinkFromPlaybin = (it->second == "true");
80  }
81  if (!gFlagGetVideoSinkFromPlaybin)
82  {
83  it = gMediaConfig.find("video-sink");
84  gFlagGetVideoSinkFromPlaybin = (it == gMediaConfig.end()) || it->second.empty();
85  }
86 
87  json_decref(root);
88  return true;
89 }
90 
91 void mediaPlayerPrivateElementAddedCallback(GstBin *bin, GstElement *element, gpointer);
92 
93 void configureElement(GstElement* element, const char* elementName)
94 {
95  const std::string propsName = std::string(elementName).append("-props");
96  const auto& it = gMediaConfig.find(propsName);
97  if (it == gMediaConfig.end())
98  return;
99 
100  std::stringstream configStream(it->second);
101  std::string configValue;
102  while (std::getline(configStream, configValue, ','))
103  {
104  std::size_t idx = configValue.find("=");
105  std::string propName = configValue.substr(0, idx);
106  std::string propValue = "";
107  if (idx != std::string::npos)
108  propValue = configValue.substr(idx+1,std::string::npos);
109  LOG_TRACE("set prop for %s: %s=%s", elementName, propName.c_str(), propValue.c_str());
110  gst_util_set_object_arg(G_OBJECT(element), propName.c_str(), propValue.c_str());
111  }
112 }
113 
114 void configureElement(GstElement *element)
115 {
116  if (!element)
117  return;
118  gchar* elementName = gst_element_get_name(element);
119  if (elementName)
120  {
121  for (int i = strlen(elementName) - 1; i >= 0 && isdigit(elementName[i]); --i) {
122  elementName[i] = '\0';
123  }
124  configureElement(element, elementName);
125  g_free(elementName);
126  }
127  if(GST_IS_BIN(element))
128  {
129  g_signal_connect (element, "element-added", G_CALLBACK (mediaPlayerPrivateElementAddedCallback), nullptr);
130  GValue item = G_VALUE_INIT;
131  GstIterator* it = gst_bin_iterate_elements(GST_BIN(element));
132  while(GST_ITERATOR_OK == gst_iterator_next(it, &item))
133  {
134  GstElement *next = GST_ELEMENT(g_value_get_object(&item));
135  configureElement(next);
136  g_value_reset (&item);
137  }
138  gst_iterator_free(it);
139  }
140 }
141 
142 void mediaPlayerPrivateElementAddedCallback(GstBin *bin, GstElement *element, gpointer)
143 {
144  LOG_TRACE("added element=%s",GST_ELEMENT_NAME (element));
145  configureElement(element);
146 }
147 
148 }
149 
150 #define NOT_IMPLEMENTED() LOG_WARNING("Not implemented")
151 
152 void MediaPlayerGeneric::busMessageCallback(GstBus* bus, GstMessage* msg, gpointer data)
153 {
154  MediaPlayerGeneric& self = *static_cast<MediaPlayerGeneric*>(data);
155  self.handleBusMessage(bus, msg);
156 }
157 
158 MediaPlayerGeneric::MediaPlayerGeneric(MediaPlayerClient* client)
159  : m_playerClient(client)
160  , m_pipeline(nullptr)
161  , m_playerState(MediaPlayer::RMF_PLAYER_EMPTY)
162  , m_videoState(MediaPlayer::RMF_VIDEO_BUFFER_HAVENOTHING)
163  , m_errorOccured(false)
164  , m_seekIsPending(false)
165  , m_seekTime(0.f)
166 {
167  static std::once_flag loadConfigFlag;
168  std::call_once(loadConfigFlag, [](){
169  loadMediaConfig(kMediaConfigFilePath);
170  });
171  LOG_INFO("Generic video player created");
172 }
173 
174 MediaPlayerGeneric::~MediaPlayerGeneric()
175 {
176  LOG_INFO("Generic video player destroying");
177  cleanup();
178  m_playerClient = nullptr;
179  LOG_INFO("Generic video player destroyed");
180 }
181 
182 MediaPlayer::RMFPlayerState MediaPlayerGeneric::rmf_playerState() const
183 {
184  return m_playerState;
185 }
186 
187 MediaPlayer::RMFVideoBufferState MediaPlayerGeneric::rmf_videoState() const
188 {
189  return m_videoState;
190 }
191 
192 bool MediaPlayerGeneric::rmf_load(const std::string &url)
193 {
194  LOG_INFO("LOAD IS CALLED (%s)", url.c_str());
195 
196  cleanup();
197 
198  m_pipeline = gst_element_factory_make("playbin", nullptr);
199 
200  if (!m_pipeline)
201  {
202  m_errorMsg = "Failed to create playbin";
203  loadingFailed(MediaPlayer::RMF_PLAYER_DECODEERROR);
204  return false;
205  }
206 
207  configureElement(pipeline());
208 
209  std::string videoSinkName;
210  if(getenv("PLAYERSINKBIN_USE_WESTEROSSINK"))
211  {
212  videoSinkName = "westerossink";
213  }
214  else if(!gFlagGetVideoSinkFromPlaybin)
215  {
216  videoSinkName = gMediaConfig["video-sink"];
217  }
218  if(!videoSinkName.empty())
219  {
220  GstElement* videoSink = gst_element_factory_make(videoSinkName.c_str(), nullptr);
221  if (videoSink)
222  {
223  g_object_set(pipeline(), "video-sink", videoSink, NULL);
224  configureElement(videoSink);
225  gst_object_unref(videoSink);
226  }
227  else
228  {
229  LOG_WARNING("Failed to create '%s', fallback to playbin defaults", videoSinkName.c_str());
230  }
231  }
232 
233  m_url = url;
234  g_object_set(pipeline(), "uri", m_url.c_str(), nullptr);
235 
236  GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline()));
237  g_signal_connect(bus, "message", G_CALLBACK(busMessageCallback), this);
238  gst_bus_add_signal_watch(bus);
239  gst_object_unref(bus);
240 
241  updateStates();
242 
243  LOG_INFO("LOAD FINISHED");
244  return true;
245 }
246 
247 void MediaPlayerGeneric::rmf_play()
248 {
249  LOG_INFO("PLAY IS CALLED");
250 
251  bool rc = changePipelineState(GST_STATE_PLAYING);
252  if (!rc) {
253  LOG_ERROR("Play failed for some unknown reason..");
254  loadingFailed(MediaPlayer::RMF_PLAYER_EMPTY);
255  }
256 
257  LOG_INFO("PLAY");
258 }
259 
260 void MediaPlayerGeneric::rmf_stop()
261 {
262  LOG_INFO("STOP IS CALLED");
263 
264  cleanup();
265 
266  LOG_INFO("STOP");
267 }
268 
269 void MediaPlayerGeneric::rmf_pause()
270 {
271  LOG_INFO("PAUSE IS CALLED");
272 
273  changePipelineState(GST_STATE_PAUSED);
274 
275  LOG_INFO("PAUSE");
276 }
277 
278 bool MediaPlayerGeneric::rmf_canItPlay() const
279 {
280  return m_pipeline != nullptr && !m_url.empty();
281 }
282 
283 bool MediaPlayerGeneric::rmf_isPaused() const
284 {
285  GstState state = GST_STATE_NULL;
286  gst_element_get_state(pipeline(), &state, 0, 0);
287  return state <= GST_STATE_PAUSED;
288 }
289 
290 float MediaPlayerGeneric::rmf_getDuration() const
291 {
292  gint64 duration = GST_CLOCK_TIME_NONE;
293  gboolean rc =
294  gst_element_query_duration(pipeline(), GST_FORMAT_TIME, &duration);
295  if (rc && static_cast<GstClockTime>(duration) != GST_CLOCK_TIME_NONE)
296  return static_cast<float>(duration) / GST_SECOND;
297  return std::numeric_limits<float>::infinity();;
298 }
299 
300 float MediaPlayerGeneric::rmf_getCurrentTime() const
301 {
302  gint64 position = GST_CLOCK_TIME_NONE;
303  GstQuery *query= gst_query_new_position(GST_FORMAT_TIME);
304  if (gst_element_query(pipeline(), query))
305  gst_query_parse_position(query, 0, &position);
306  gst_query_unref(query);
307  if (static_cast<GstClockTime>(position) != GST_CLOCK_TIME_NONE)
308  return static_cast<float>(position) / GST_SECOND;
309  return 0.f;
310 }
311 
312 std::string MediaPlayerGeneric::rmf_getMediaErrorMessage() const
313 {
314  return m_errorMsg;
315 }
316 
317 void MediaPlayerGeneric::rmf_setRate(float speed)
318 {
319  NOT_IMPLEMENTED();
320 }
321 float MediaPlayerGeneric::rmf_getRate() const
322 {
323  return 1.f;
324 }
325 
326 void MediaPlayerGeneric::rmf_setVolume(float volume)
327 {
328  gdouble vol = static_cast<gdouble>(volume);
329  g_object_set(pipeline(), "volume", vol, NULL);
330 }
331 
332 float MediaPlayerGeneric::rmf_getVolume() const
333 {
334  gdouble volume;
335  g_object_get(pipeline(), "volume", &volume, NULL);
336  return static_cast<float>(volume);
337 }
338 
339 void MediaPlayerGeneric::rmf_setMute(bool mute)
340 {
341  NOT_IMPLEMENTED();
342 }
343 bool MediaPlayerGeneric::rmf_isMuted() const
344 {
345  return false;
346 }
347 
348 void MediaPlayerGeneric::rmf_seekToLivePosition()
349 {
350  rmf_seek(0.f);
351 }
352 void MediaPlayerGeneric::rmf_seekToStartPosition()
353 {
354  rmf_seek(0.f);
355 }
356 
357 static GstClockTime convertPositionToGstClockTime(float time)
358 {
359  // Extract the integer part of the time (seconds) and the fractional part (microseconds). Attempt to
360  // round the microseconds so no floating point precision is lost and we can perform an accurate seek.
361  double seconds;
362  float microSeconds = modf(time, &seconds) * 1000000;
363  GTimeVal timeValue;
364  timeValue.tv_sec = static_cast<glong>(seconds);
365  timeValue.tv_usec = static_cast<glong>(roundf(microSeconds / 10000) * 10000);
366  return GST_TIMEVAL_TO_TIME(timeValue);
367 }
368 
369 void MediaPlayerGeneric::rmf_seek(float time)
370 {
371  GstState state, pending;
372  gint64 startTime, endTime;
373 
374  if (!pipeline())
375  return;
376 
377  if (m_errorOccured)
378  return;
379 
380  LOG_INFO("[Seek] seek attempt to %f secs", time);
381 
382  // Avoid useless seeking.
383  float current = rmf_getCurrentTime();
384  if (time == current)
385  return;
386 
387  LOG_INFO("HTML5 video: Seeking from %f to %f seconds", current, time);
388 
389  GstClockTime clockTime = convertPositionToGstClockTime(time);
390 
391  GstStateChangeReturn ret = gst_element_get_state(pipeline(), &state, &pending, 250 * GST_NSECOND);
392  LOG_INFO ("state: %s, pending: %s, ret = %s", gst_element_state_get_name(state), gst_element_state_get_name(pending), gst_element_state_change_return_get_name(ret));
393 
394  if (ret == GST_STATE_CHANGE_ASYNC || state < GST_STATE_PAUSED) {
395  m_seekIsPending = true;
396  } else {
397  m_seekIsPending = false;
398 
399  startTime = clockTime;
400  endTime = GST_CLOCK_TIME_NONE;
401 
402  /* Call Seek Now */
403  if (!gst_element_seek(pipeline(), 1.0, GST_FORMAT_TIME, static_cast<GstSeekFlags>(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE), GST_SEEK_TYPE_SET, startTime, GST_SEEK_TYPE_SET, endTime)) {
404  LOG_WARNING("[Seek] seeking to %f failed", time);
405  }
406 
407  /* Set it to Play */
408  changePipelineState(GST_STATE_PLAYING);
409  }
410 
411  /* Update the seek time */
412  m_seekTime = time;
413 }
414 
415 bool MediaPlayerGeneric::rmf_isSeeking() const
416 {
417  return false;
418 }
419 unsigned long MediaPlayerGeneric::rmf_getCCDecoderHandle() const
420 {
421  NOT_IMPLEMENTED();
422  return 0;
423 }
424 std::string MediaPlayerGeneric::rmf_getAudioLanguages() const
425 {
426  NOT_IMPLEMENTED();
427  return "eng";
428 }
429 void MediaPlayerGeneric::rmf_setAudioLanguage(const std::string &)
430 {
431  NOT_IMPLEMENTED();
432 }
433 void MediaPlayerGeneric::rmf_setAudioMute(bool isMuted)
434 {
435  NOT_IMPLEMENTED();
436 }
437 void MediaPlayerGeneric::rmf_setEissFilterStatus(bool status)
438 {
439  NOT_IMPLEMENTED();
440 }
441 void MediaPlayerGeneric::rmf_setVideoZoom(unsigned short zoomVal)
442 {
443  NOT_IMPLEMENTED();
444 }
445 void MediaPlayerGeneric::rmf_setVideoBufferLength(float bufferLength)
446 {
447 // NOT_IMPLEMENTED();
448 }
449 void MediaPlayerGeneric::rmf_setInProgressRecording(bool isInProgress)
450 {
451  NOT_IMPLEMENTED();
452 }
453 bool MediaPlayerGeneric::rmf_isItInProgressRecording() const
454 {
455  NOT_IMPLEMENTED();
456  return false;
457 }
458 void MediaPlayerGeneric::rmf_changeSpeed(float speed, short overshootTime)
459 {
460  NOT_IMPLEMENTED();
461 }
462 std::string MediaPlayerGeneric::rmf_getMediaWarnDescription() const
463 {
464  NOT_IMPLEMENTED();
465  return "";
466 }
467 int MediaPlayerGeneric::rmf_getMediaWarnData() const
468 {
469  NOT_IMPLEMENTED();
470  return 0;
471 }
472 std::string MediaPlayerGeneric::rmf_getAvailableAudioTracks() const
473 {
474  NOT_IMPLEMENTED();
475  return "eng";
476 }
477 std::string MediaPlayerGeneric::rmf_getCaptionDescriptor() const
478 {
479  NOT_IMPLEMENTED();
480  return "";
481 }
482 std::string MediaPlayerGeneric::rmf_getEISSDataBuffer() const
483 {
484  NOT_IMPLEMENTED();
485  return "";
486 }
487 void MediaPlayerGeneric::rmf_setNetworkBufferSize(int bufferSize)
488 {
489  NOT_IMPLEMENTED();
490 }
491 int MediaPlayerGeneric::rmf_getNetworkBufferSize() const
492 {
493  NOT_IMPLEMENTED();
494  return 0;
495 }
496 void MediaPlayerGeneric::rmf_setVideoRectangle(unsigned x, unsigned y, unsigned w, unsigned h)
497 {
498  IntRect temp(x, y, w, h);
499  if (m_lastKnownRect == temp)
500  return;
501 
502  m_lastKnownRect = temp;
503 
504  if (!pipeline())
505  return;
506 
507  GstElement* videoSink;
508  g_object_get(pipeline(), "video-sink", &videoSink, nullptr);
509  if (!videoSink)
510  return;
511 
512  gchar* rectStr = g_strdup_printf("%d,%d,%d,%d", x, y, w, h);
513  if (!rectStr) {
514  gst_object_unref(videoSink);
515  return;
516  }
517 
518  g_object_set(videoSink, "rectangle", rectStr, nullptr);
519  gst_object_unref(videoSink);
520  g_free(rectStr);
521 }
522 
523 int MediaPlayerGeneric::rmf_getVideoPid() {
524  NOT_IMPLEMENTED();
525  return -1;
526 }
527 
528 int MediaPlayerGeneric::rmf_getAudioPid() {
529  NOT_IMPLEMENTED();
530  return -1;
531 }
532 
533 void MediaPlayerGeneric::rmf_setVideoKeySlot(const char* str)
534 {
535  NOT_IMPLEMENTED();
536  return;
537 }
538 
539 void MediaPlayerGeneric::rmf_setAudioKeySlot(const char* str)
540 {
541  NOT_IMPLEMENTED();
542  return;
543 }
544 
545 void MediaPlayerGeneric::rmf_deleteVideoKeySlot()
546 {
547  NOT_IMPLEMENTED();
548  return;
549 }
550 
551 void MediaPlayerGeneric::rmf_deleteAudioKeySlot()
552 {
553  NOT_IMPLEMENTED();
554  return;
555 }
556 
557 void MediaPlayerGeneric::handleBusMessage(GstBus* bus, GstMessage* msg)
558 {
559  bool isPlayerPipelineMessage = GST_MESSAGE_SRC(msg) == reinterpret_cast<GstObject*>(pipeline());
560 
561  switch (GST_MESSAGE_TYPE (msg))
562  {
563  case GST_MESSAGE_EOS: {
564  endOfStream();
565  break;
566  }
567  case GST_MESSAGE_STATE_CHANGED:
568  case GST_MESSAGE_ASYNC_DONE: {
569  if (isPlayerPipelineMessage)
570  updateStates();
571  break;
572  }
573  case GST_MESSAGE_ERROR: {
574  GError *err = nullptr;
575  gchar *dbg = nullptr;
576  gst_message_parse_error (msg, &err, &dbg);
577  if (err) {
578  notifyError(err->message);
579  g_error_free (err);
580  } else {
581  notifyError(nullptr);
582  }
583  if (dbg) {
584  LOG_ERROR("[Debug details: %s]", dbg);
585  g_free (dbg);
586  }
587  break;
588  }
589  default:
590  LOG_TRACE("Unhandled message type: %s", GST_MESSAGE_TYPE_NAME(msg));
591  break;
592  }
593 }
594 
595 void MediaPlayerGeneric::updateStates()
596 {
597  if (!pipeline())
598  return;
599 
600  if (m_errorOccured)
601  return;
602 
603  MediaPlayer::RMFPlayerState oldPlayerState = m_playerState;
604  MediaPlayer::RMFVideoBufferState oldVideoState = m_videoState;
605 
606  GstState state, pending;
607  GstStateChangeReturn ret =
608  gst_element_get_state(pipeline(), &state, &pending, 250 * GST_NSECOND);
609 
610  LOG_VERBOSE("updateStates(): state: %s, pending: %s, ret = %s",
611  gst_element_state_get_name(state),
612  gst_element_state_get_name(pending),
613  gst_element_state_change_return_get_name(ret));
614 
615  switch (ret)
616  {
617  case GST_STATE_CHANGE_SUCCESS:
618  {
619  if (state == GST_STATE_READY) {
620  m_videoState = MediaPlayer::RMF_VIDEO_BUFFER_HAVEMETADATA;
621  m_playerState = MediaPlayer::RMF_PLAYER_EMPTY;
622  } else if (state == GST_STATE_PAUSED) {
623  m_videoState = MediaPlayer::RMF_VIDEO_BUFFER_HAVECURRENTDATA;
624  m_playerState = MediaPlayer::RMF_PLAYER_LOADING;
625  } else if (state == GST_STATE_PLAYING) {
626  m_videoState = MediaPlayer::RMF_VIDEO_BUFFER_HAVEENOUGHDATA;
627  m_playerState = MediaPlayer::RMF_PLAYER_LOADED;
628  }
629  break;
630  }
631  case GST_STATE_CHANGE_NO_PREROLL:
632  {
633  if (state == GST_STATE_READY) {
634  m_videoState = MediaPlayer::RMF_VIDEO_BUFFER_HAVENOTHING;
635  } else if (state == GST_STATE_PAUSED) {
636  m_videoState = MediaPlayer::RMF_VIDEO_BUFFER_HAVEENOUGHDATA;
637  }
638  m_playerState = MediaPlayer::RMF_PLAYER_LOADING;
639  break;
640  }
641  default:
642  break;
643  }
644 
645  // update video rect on playback start
646  if (m_playerState != oldPlayerState && state == GST_STATE_PLAYING)
647  {
648  IntRect temp = m_lastKnownRect;
649  m_lastKnownRect = IntRect();
650  rmf_setVideoRectangle(temp.x(),temp.y(),temp.width(),temp.height());
651  }
652 
653  if (m_playerState != oldPlayerState)
654  {
655  LOG_INFO("Player State Changed from %u to %u",
656  oldPlayerState, m_playerState);
657  m_playerClient->playerStateChanged();
658  }
659  if (m_videoState != oldVideoState)
660  {
661  LOG_INFO("Video State Changed from %u to %u",
662  oldVideoState, m_videoState);
663  m_playerClient->videoStateChanged();
664  }
665 
666  if ((ret == GST_STATE_CHANGE_SUCCESS) && (state >= GST_STATE_PAUSED) && m_seekIsPending) {
667  LOG_INFO ("[Seek] committing pending seek to %f", m_seekTime);
668  m_seekIsPending = false;
669  rmf_seek(m_seekTime);
670  }
671 }
672 
673 void MediaPlayerGeneric::endOfStream()
674 {
675  LOG_TRACE("mediaPlaybackCompleted");
676  m_playerClient->mediaPlaybackCompleted();
677 }
678 
679 void MediaPlayerGeneric::notifyError(const char *message)
680 {
681  std::string tmp = "130:ErrorCode:Unknown Error";
682  if (message)
683  tmp = std::string(message);
684  m_errorMsg = tmp;
685  LOG_ERROR("error message='%s'", m_errorMsg.c_str());
686  loadingFailed(MediaPlayer::RMF_PLAYER_DECODEERROR);
687 }
688 
689 void MediaPlayerGeneric::loadingFailed(MediaPlayer::RMFPlayerState error)
690 {
691  LOG_ERROR("player state=%s", StateString(error));
692  m_errorOccured = true;
693  if (m_playerState != error) {
694  m_playerState = error;
695  m_playerClient->playerStateChanged();
696  }
697  if (m_videoState != MediaPlayer::RMF_VIDEO_BUFFER_HAVENOTHING) {
698  m_videoState = MediaPlayer::RMF_VIDEO_BUFFER_HAVENOTHING;
699  m_playerClient->videoStateChanged();
700  }
701 }
702 
703 GstElement* MediaPlayerGeneric::pipeline() const
704 {
705  return m_pipeline;
706 }
707 
708 bool MediaPlayerGeneric::changePipelineState(GstState newState)
709 {
710  GstState currentState, pending;
711 
712  gst_element_get_state(pipeline(), &currentState, &pending, 0);
713  if (currentState == newState || pending == newState) {
714  LOG_INFO("Rejected state change to %s from %s with %s pending",
715  gst_element_state_get_name(newState),
716  gst_element_state_get_name(currentState),
717  gst_element_state_get_name(pending));
718  return true;
719  }
720 
721  GstStateChangeReturn setStateResult = gst_element_set_state(pipeline(), newState);
722  if (setStateResult == GST_STATE_CHANGE_FAILURE) {
723  LOG_ERROR("Failed to change state to %s from %s with %s pending",
724  gst_element_state_get_name(newState),
725  gst_element_state_get_name(currentState),
726  gst_element_state_get_name(pending));
727  return false;
728  }
729  return true;
730 }
731 
732 void MediaPlayerGeneric::cleanup()
733 {
734  if (!m_pipeline)
735  return;
736 
737  GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline()));
738  gst_bus_remove_signal_watch(bus);
739  gst_object_unref(bus);
740 
741  gst_element_set_state(pipeline(), GST_STATE_NULL);
742  gst_object_unref(m_pipeline);
743 
744  m_pipeline = nullptr;
745  m_playerState = MediaPlayer::RMF_PLAYER_EMPTY;
746  m_videoState = MediaPlayer::RMF_VIDEO_BUFFER_HAVENOTHING;
747  m_url.clear();
748  m_errorMsg.clear();
749  m_errorOccured = false;
750  m_lastKnownRect = IntRect();
751 }
MediaPlayer
Definition: mediaplayer.h:51
MediaPlayerGeneric
Definition: mediaplayergeneric.h:28
MediaPlayerClient
Definition: mediaplayer.h:29
LOG_INFO
#define LOG_INFO(AAMP_JS_OBJECT, FORMAT,...)
Definition: jsutils.h:39
IntRect
Definition: intrect.h:22
LOG_TRACE
#define LOG_TRACE
Definition: rdk_debug_priv.c:83