19 #ifndef GSTREAMER_PLAYBIN_H_
20 #define GSTREAMER_PLAYBIN_H_
23 #include "../mpris/player.h"
25 #include <hybris/media/media_codec_layer.h>
26 #include <hybris/media/surface_texture_client_hybris.h>
34 namespace media = core::ubuntu::media;
56 static const std::string s{
"playbin"};
63 auto thiz =
static_cast<Playbin*
>(user_data);
76 std::placeholders::_1))),
80 throw std::runtime_error(
"Could not create pipeline for playbin.");
114 std::cout <<
"Client died, resetting pipeline" << std::endl;
123 std::cout << __PRETTY_FUNCTION__ << std::endl;
124 auto ret = gst_element_set_state(
pipeline, GST_STATE_NULL);
127 case GST_STATE_CHANGE_FAILURE:
128 std::cout <<
"Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl;
130 case GST_STATE_CHANGE_NO_PREROLL:
131 case GST_STATE_CHANGE_SUCCESS:
132 case GST_STATE_CHANGE_ASYNC:
135 std::cout <<
"Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl;
144 case GST_MESSAGE_ERROR:
147 case GST_MESSAGE_WARNING:
150 case GST_MESSAGE_INFO:
153 case GST_MESSAGE_TAG:
156 case GST_MESSAGE_STATE_CHANGED:
159 case GST_MESSAGE_ASYNC_DONE:
167 case GST_MESSAGE_EOS:
182 g_object_get (
pipeline,
"flags", &flags,
nullptr);
186 g_object_set (
pipeline,
"flags", flags,
nullptr);
188 if (::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME") !=
nullptr)
190 auto audio_sink = gst_element_factory_make (
191 ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"),
194 std::cout <<
"audio_sink: " << ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME") << std::endl;
203 if (::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") !=
nullptr)
205 auto video_sink = gst_element_factory_make (
206 ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"),
209 std::cout <<
"video_sink: " << ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl;
221 std::cout <<
"Creating video sink for texture_id: " << texture_id << std::endl;
223 if (::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") !=
nullptr)
225 GstElement *video_sink = NULL;
226 g_object_get (
pipeline,
"video_sink", &video_sink, NULL);
230 IGBPWrapperHybris igbp = decoding_service_get_igraphicbufferproducer();
231 SurfaceTextureClientHybris stc = surface_texture_client_create_by_igbp(igbp);
233 surface_texture_client_set_hardware_rendering (stc, TRUE);
234 g_object_set (G_OBJECT (video_sink),
"surface", static_cast<gpointer>(stc), static_cast<char*>(NULL));
240 g_object_set(
pipeline,
"volume", new_volume, NULL);
246 gst_element_query_position (
pipeline, GST_FORMAT_TIME, &pos);
249 return static_cast<uint64_t
>(pos);
255 gst_element_query_duration (
pipeline, GST_FORMAT_TIME, &dur);
258 return static_cast<uint64_t
>(dur);
263 g_object_set(
pipeline,
"uri", uri.c_str(), NULL);
272 gchar* data =
nullptr;
273 g_object_get(
pipeline,
"current-uri", &data,
nullptr);
275 std::string result((data ==
nullptr ?
"" : data));
283 static const std::chrono::nanoseconds state_change_timeout
288 std::chrono::milliseconds{5000}
291 auto ret = gst_element_set_state(
pipeline, new_state);
292 bool result =
false; GstState current, pending;
295 case GST_STATE_CHANGE_FAILURE:
296 result =
false;
break;
297 case GST_STATE_CHANGE_NO_PREROLL:
298 case GST_STATE_CHANGE_SUCCESS:
299 result =
true;
break;
300 case GST_STATE_CHANGE_ASYNC:
301 result = GST_STATE_CHANGE_SUCCESS == gst_element_get_state(
305 state_change_timeout.count());
312 bool seek(
const std::chrono::microseconds& ms)
315 return gst_element_seek_simple(
318 (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
325 return std::string();
327 std::string filename(uri);
328 std::cout <<
"filename: " << filename << std::endl;
329 size_t pos = uri.find(
"file://");
330 if (pos != std::string::npos)
331 filename = uri.substr(pos + 7, std::string::npos);
336 return std::string(
"audio/video/");
339 GError *error =
nullptr;
340 std::unique_ptr<GFile, void(*)(void *)> file(
341 g_file_new_for_path(filename.c_str()), g_object_unref);
342 std::unique_ptr<GFileInfo, void(*)(void *)> info(
344 file.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE
","
345 G_FILE_ATTRIBUTE_ETAG_VALUE, G_FILE_QUERY_INFO_NONE,
350 std::string error_str(error->message);
353 std::cout <<
"Failed to query the URI for the presence of video content: "
354 << error_str << std::endl;
355 return std::string();
358 std::string content_type(g_file_info_get_attribute_string(
359 info.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE));
371 std::cout <<
"Found audio content" << std::endl;
385 std::cout <<
"Found video content" << std::endl;
406 core::Signal<Bus::Message::Detail::ErrorWarningInfo>
on_error;
407 core::Signal<Bus::Message::Detail::ErrorWarningInfo>
on_warning;
408 core::Signal<Bus::Message::Detail::ErrorWarningInfo>
on_info;
418 #endif // GSTREAMER_PLAYBIN_H_
core::Signal< Bus::Message::Detail::StateChanged > on_state_changed
core::Signal< Message > on_new_message
core::Signal< Bus::Message::Detail::Tag > on_tag_available
bool set_state_and_wait(GstState new_state)
bool seek(const std::chrono::microseconds &ms)
static void about_to_finish(GstElement *, gpointer user_data)
uint64_t duration() const
core::Signal< void > about_to_finish
core::Signal< Bus::Message::Detail::ErrorWarningInfo > on_warning
core::Connection on_new_message_connection
core::Signal< uint64_t > on_seeked_to
void on_new_message(const Bus::Message &message)
SurfaceTextureClientHybris stc_hybris
MediaFileType media_file_type() const
void setup_pipeline_for_audio_video()
union gstreamer::Bus::Message::Detail detail
core::Signal< Bus::Message::Detail::ErrorWarningInfo > on_info
core::Signal< media::Player::PlaybackStatus > on_playback_status_changed
core::Signal< void > on_end_of_stream
std::string get_file_content_type(const std::string &uri) const
struct gstreamer::Playbin::@11 signals
void set_uri(const std::string &uri)
struct gstreamer::Bus::Message::Detail::Tag tag
bool is_audio_file(const std::string &uri) const
bool is_video_file(const std::string &uri) const
struct gstreamer::Bus::Message::Detail::ErrorWarningInfo error_warning_info
void set_volume(double new_volume)
core::Signal< Bus::Message::Detail::ErrorWarningInfo > on_error
void create_video_sink(uint32_t texture_id)
uint64_t position() const
static const std::string & pipeline_name()
static void on_client_died_cb(void *context)
gstreamer::Bus & message_bus()
struct gstreamer::Bus::Message::Detail::StateChanged state_changed