43 gst_init(
nullptr,
nullptr);
58 return media::Player::PlaybackStatus::playing;
59 else if (state.
new_state == GST_STATE_PAUSED)
60 return media::Player::PlaybackStatus::paused;
61 else if (state.
new_state == GST_STATE_READY)
62 return media::Player::PlaybackStatus::ready;
63 else if (state.
new_state == GST_STATE_NULL)
64 return media::Player::PlaybackStatus::null;
66 return media::Player::PlaybackStatus::stopped;
71 if (p.second ==
"playbin")
73 MH_INFO(
"State changed on playbin: %s",
74 gst_element_state_get_name(p.first.new_state));
75 const auto status = gst_state_to_player_status(p.first);
80 if (status == media::Player::PlaybackStatus::paused &&
81 !playbin.can_play_streams()) {
82 MH_ERROR(
"** Cannot play: some codecs are missing");
87 playback_status_changed(status);
97 if (g_strcmp0(g_quark_to_string(ewi.
error->domain),
"gst-core-error-quark") == 0)
99 switch (ewi.
error->code)
101 case GST_CORE_ERROR_FAILED:
102 MH_ERROR(
"** Encountered a GST_CORE_ERROR_FAILED");
103 ret_error = media::Player::Error::resource_error;
105 case GST_CORE_ERROR_NEGOTIATION:
106 MH_ERROR(
"** Encountered a GST_CORE_ERROR_NEGOTIATION");
107 ret_error = media::Player::Error::resource_error;
109 case GST_CORE_ERROR_MISSING_PLUGIN:
110 MH_ERROR(
"** Encountered a GST_CORE_ERROR_MISSING_PLUGIN");
111 ret_error = media::Player::Error::format_error;
114 MH_ERROR(
"** Encountered an unhandled core error: '%s' (code: %d)",
116 ret_error = media::Player::Error::no_error;
120 else if (g_strcmp0(g_quark_to_string(ewi.
error->domain),
"gst-resource-error-quark") == 0)
122 switch (ewi.
error->code)
124 case GST_RESOURCE_ERROR_FAILED:
125 MH_ERROR(
"** Encountered a GST_RESOURCE_ERROR_FAILED");
126 ret_error = media::Player::Error::resource_error;
128 case GST_RESOURCE_ERROR_NOT_FOUND:
129 MH_ERROR(
"** Encountered a GST_RESOURCE_ERROR_NOT_FOUND");
130 ret_error = media::Player::Error::resource_error;
132 case GST_RESOURCE_ERROR_OPEN_READ:
133 MH_ERROR(
"** Encountered a GST_RESOURCE_ERROR_OPEN_READ");
134 ret_error = media::Player::Error::resource_error;
136 case GST_RESOURCE_ERROR_OPEN_WRITE:
137 MH_ERROR(
"** Encountered a GST_RESOURCE_ERROR_OPEN_WRITE");
138 ret_error = media::Player::Error::resource_error;
140 case GST_RESOURCE_ERROR_READ:
141 MH_ERROR(
"** Encountered a GST_RESOURCE_ERROR_READ");
142 ret_error = media::Player::Error::resource_error;
144 case GST_RESOURCE_ERROR_WRITE:
145 MH_ERROR(
"** Encountered a GST_RESOURCE_ERROR_WRITE");
146 ret_error = media::Player::Error::resource_error;
148 case GST_RESOURCE_ERROR_NOT_AUTHORIZED:
149 MH_ERROR(
"** Encountered a GST_RESOURCE_ERROR_NOT_AUTHORIZED");
150 ret_error = media::Player::Error::access_denied_error;
153 MH_ERROR(
"** Encountered an unhandled resource error: '%s' (code: %d)",
155 ret_error = media::Player::Error::no_error;
159 else if (g_strcmp0(g_quark_to_string(ewi.
error->domain),
"gst-stream-error-quark") == 0)
161 switch (ewi.
error->code)
163 case GST_STREAM_ERROR_FAILED:
164 MH_ERROR(
"** Encountered a GST_STREAM_ERROR_FAILED");
165 ret_error = media::Player::Error::resource_error;
167 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
168 MH_ERROR(
"** Encountered a GST_STREAM_ERROR_CODEC_NOT_FOUND");
170 ret_error = media::Player::Error::no_error;
172 case GST_STREAM_ERROR_DECODE:
173 MH_ERROR(
"** Encountered a GST_STREAM_ERROR_DECODE");
174 ret_error = media::Player::Error::format_error;
177 MH_ERROR(
"** Encountered an unhandled stream error: '%s' code(%d)",
179 ret_error = media::Player::Error::no_error;
184 if (ret_error != media::Player::Error::no_error) {
185 MH_ERROR(
"Resetting playbin pipeline after unrecoverable error");
194 if (e != media::Player::Error::no_error)
201 if (e != media::Player::Error::no_error)
207 MH_DEBUG(
"Got a playbin info message (no action taken): %s", ewi.
debug);
212 media::Track::MetaData md;
215 auto &tuple = track_meta_data.get();
216 if (playbin.uri() == std::get<0>(tuple))
217 md = std::get<1>(tuple);
220 track_meta_data.set(std::make_tuple(playbin.uri(), md));
225 playbin.set_volume(new_volume.value);
230 playbin.set_audio_stream_role(new_audio_role);
242 playbin.set_lifetime(lifetime);
247 state = Engine::State::ready;
258 client_disconnected();
268 video_dimension_changed(dimensions);
273 buffering_changed(value);
280 orientation(
media::Player::Orientation::rotate0),
281 is_video_source(false),
282 is_audio_source(false),
283 about_to_finish_connection(
284 playbin.signals.about_to_finish.connect(
288 on_state_changed_connection(
289 playbin.signals.on_state_changed.connect(
291 &
Private::on_playbin_state_changed,
293 std::placeholders::_1))),
295 playbin.signals.on_error.connect(
299 std::placeholders::_1))),
300 on_warning_connection(
301 playbin.signals.on_warning.connect(
305 std::placeholders::_1))),
307 playbin.signals.on_info.connect(
311 std::placeholders::_1))),
312 on_tag_available_connection(
313 playbin.signals.on_tag_available.connect(
317 std::placeholders::_1))),
318 on_volume_changed_connection(
319 volume.changed().connect(
323 std::placeholders::_1))),
324 on_audio_stream_role_changed_connection(
325 audio_role.changed().connect(
327 &
Private::on_audio_stream_role_changed,
329 std::placeholders::_1))),
330 on_orientation_changed_connection(
331 playbin.signals.on_orientation_changed.connect(
333 &
Private::on_orientation_changed,
335 std::placeholders::_1))),
336 on_lifetime_changed_connection(
337 lifetime.changed().connect(
341 std::placeholders::_1))),
342 on_seeked_to_connection(
343 playbin.signals.on_seeked_to.connect(
347 std::placeholders::_1))),
348 client_disconnected_connection(
349 playbin.signals.client_disconnected.connect(
351 &
Private::on_client_disconnected,
353 on_end_of_stream_connection(
354 playbin.signals.on_end_of_stream.connect(
358 on_video_dimension_changed_connection(
359 playbin.signals.on_video_dimensions_changed.connect(
361 &
Private::on_video_dimension_changed,
363 std::placeholders::_1))),
364 on_buffering_changed_connection(
365 playbin.signals.on_buffering_changed.connect(
367 &
Private::on_buffering_changed,
369 std::placeholders::_1)))
378 core::Property<Engine::State>
state;
379 core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>>
track_meta_data;
382 core::Property<media::Engine::Volume>
volume;
411 core::Signal<media::Player::Error>
error;
418 d->state = media::Engine::State::no_media;
424 d->state = media::Engine::State::no_media;
427 const std::shared_ptr<media::Engine::MetaDataExtractor>&
430 return d->meta_data_extractor;
439 bool do_pipeline_reset)
448 d->playbin.set_uri(uri, headers);
454 d->playbin.create_video_sink(texture_id);
459 const auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING, use_main_thread);
463 d->state = media::Engine::State::playing;
464 MH_INFO(
"Engine: playing uri: %s", d->playbin.uri());
465 d->playback_status_changed(media::Player::PlaybackStatus::playing);
474 if (d->state == media::Engine::State::stopped)
476 MH_DEBUG(
"Current player state is already stopped - no need to change state to stopped");
480 const auto result = d->playbin.set_state_and_wait(GST_STATE_NULL, use_main_thread);
483 d->state = media::Engine::State::stopped;
485 d->playback_status_changed(media::Player::PlaybackStatus::stopped);
493 const auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
497 d->state = media::Engine::State::paused;
499 d->playback_status_changed(media::Player::PlaybackStatus::paused);
507 return d->playbin.seek(ts);
513 if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
514 d->is_video_source.set(
true);
516 d->is_video_source.set(
false);
518 return d->is_video_source;
524 if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
525 d->is_audio_source.set(
true);
527 d->is_audio_source.set(
false);
529 return d->is_audio_source;
534 d->position.set(d->playbin.position());
540 d->duration.set(d->playbin.duration());
556 return d->audio_role;
566 return d->audio_role;
571 return d->orientation;
579 const core::Property<std::tuple<media::Track::UriType, media::Track::MetaData>>&
582 return d->track_meta_data;
587 return d->about_to_finish;
597 return d->client_disconnected;
602 return d->end_of_stream;
607 return d->playback_status_changed;
612 return d->video_dimension_changed;
622 return d->buffering_changed;
void on_tag_available(const gstreamer::Bus::Message::Detail::Tag &tag)
core::ScopedConnection on_state_changed_connection
core::ScopedConnection on_video_dimension_changed_connection
core::Signal< core::ubuntu::media::video::Dimensions > video_dimension_changed
const core::Signal< void > & about_to_finish_signal() const
Private(const core::ubuntu::media::Player::PlayerKey key)
core::Property< bool > is_video_source
const core::Signal< void > & end_of_stream_signal() const
const core::Property< core::ubuntu::media::Player::Orientation > & orientation() const
core::ScopedConnection on_info_connection
core::Signal< void > end_of_stream
core::ScopedConnection on_buffering_changed_connection
core::ScopedConnection on_lifetime_changed_connection
void on_seeked_to(uint64_t value)
void on_playbin_warning(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
const core::Property< uint64_t > & position() const
bool stop(bool use_main_thread=false)
const core::Signal< core::ubuntu::media::Player::PlaybackStatus > & playback_status_changed_signal() const
void on_about_to_finish()
const core::Property< uint64_t > & duration() const
const core::Signal< void > & client_disconnected_signal() const
core::ScopedConnection on_seeked_to_connection
core::Signal< int > buffering_changed
const core::Signal< uint64_t > & seeked_to_signal() const
core::ScopedConnection on_end_of_stream_connection
void on_orientation_changed(const media::Player::Orientation &o)
core::Signal< media::Player::Error > error
const core::Property< State > & state() const
gstreamer::Playbin playbin
bool seek_to(const std::chrono::microseconds &ts)
core::ScopedConnection on_warning_connection
const core::Property< core::ubuntu::media::Engine::Volume > & volume() const
const core::Signal< core::ubuntu::media::video::Dimensions > & video_dimension_changed_signal() const
bool open_resource_for_uri(const core::ubuntu::media::Track::UriType &uri, bool do_pipeline_reset)
const core::Property< bool > & is_audio_source() const
struct gstreamer::Init init
void create_video_sink(uint32_t texture_id)
core::ScopedConnection client_disconnected_connection
void on_playbin_error(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
const core::Property< core::ubuntu::media::Player::Lifetime > & lifetime() const
media::Player::Error from_gst_errorwarning(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
void on_volume_changed(const media::Engine::Volume &new_volume)
core::ScopedConnection on_volume_changed_connection
core::Property< media::Player::Orientation > orientation
core::Property< media::Player::AudioStreamRole > audio_role
core::Signal< void > client_disconnected
core::Signal< uint64_t > seeked_to
bool play(bool use_main_thread=false)
const core::Property< std::tuple< core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData > > & track_meta_data() const
void on_playbin_info(const gstreamer::Bus::Message::Detail::ErrorWarningInfo &ewi)
const core::Signal< int > & on_buffering_changed_signal() const
core::ScopedConnection on_error_connection
core::Property< media::Player::Lifetime > lifetime
std::shared_ptr< Engine::MetaDataExtractor > meta_data_extractor
const std::shared_ptr< MetaDataExtractor > & meta_data_extractor() const
core::ScopedConnection on_tag_available_connection
void on_buffering_changed(int value)
core::Property< media::Engine::Volume > volume
void on_playbin_state_changed(const std::pair< gstreamer::Bus::Message::Detail::StateChanged, std::string > &p)
media::Player::PlaybackStatus gst_state_to_player_status(const gstreamer::Bus::Message::Detail::StateChanged &state)
const core::Property< bool > & is_video_source() const
core::ScopedConnection about_to_finish_connection
core::Property< Engine::State > state
core::Property< uint64_t > position
core::Property< std::tuple< media::Track::UriType, media::Track::MetaData > > track_meta_data
core::Signal< void > about_to_finish
const core::Property< core::ubuntu::media::Player::AudioStreamRole > & audio_stream_role() const
core::Signal< media::Player::PlaybackStatus > playback_status_changed
const core::Signal< core::ubuntu::media::Player::Error > & error_signal() const
core::ScopedConnection on_orientation_changed_connection
void on_client_disconnected()
Engine(const core::ubuntu::media::Player::PlayerKey key)
void on_audio_stream_role_changed(const media::Player::AudioStreamRole &new_audio_role)
void on_video_dimension_changed(const media::video::Dimensions &dimensions)
void on_lifetime_changed(const media::Player::Lifetime &lifetime)
core::Property< bool > is_audio_source
core::Property< uint64_t > duration
core::ScopedConnection on_audio_stream_role_changed_connection