19 #ifndef GSTREAMER_PLAYBIN_H_
20 #define GSTREAMER_PLAYBIN_H_
23 #include "../mpris/player.h"
25 #include <hybris/media/surface_texture_client_hybris.h>
26 #include <hybris/media/media_codec_layer.h>
62 static const std::string s{
"playbin"};
69 auto thiz =
static_cast<Playbin*
>(user_data);
77 if (user_data ==
nullptr)
95 std::placeholders::_1))),
100 throw std::runtime_error(
"Could not create pipeline for playbin.");
130 std::cout <<
"Client died, resetting pipeline" << std::endl;
146 std::cout << __PRETTY_FUNCTION__ << std::endl;
147 auto ret = gst_element_set_state(
pipeline, GST_STATE_NULL);
150 case GST_STATE_CHANGE_FAILURE:
151 std::cout <<
"Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl;
153 case GST_STATE_CHANGE_NO_PREROLL:
154 case GST_STATE_CHANGE_SUCCESS:
155 case GST_STATE_CHANGE_ASYNC:
158 std::cout <<
"Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl;
167 case GST_MESSAGE_ERROR:
170 case GST_MESSAGE_WARNING:
173 case GST_MESSAGE_INFO:
176 case GST_MESSAGE_TAG:
179 if (gst_tag_list_get_string(message.
detail.
tag.
tag_list,
"image-orientation", &orientation))
183 g_free (orientation);
189 case GST_MESSAGE_STATE_CHANGED:
192 case GST_MESSAGE_ASYNC_DONE:
200 case GST_MESSAGE_EOS:
215 g_object_get (
pipeline,
"flags", &flags,
nullptr);
219 g_object_set (
pipeline,
"flags", flags,
nullptr);
221 if (::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME") !=
nullptr)
223 auto audio_sink = gst_element_factory_make (
224 ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"),
227 std::cout <<
"audio_sink: " << ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME") << std::endl;
236 if (::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") !=
nullptr)
239 ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"),
242 std::cout <<
"video_sink: " << ::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl;
254 std::cout <<
"Creating video sink for texture_id: " << texture_id << std::endl;
256 if (::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") !=
nullptr)
262 IGBPWrapperHybris igbp = decoding_service_get_igraphicbufferproducer();
263 SurfaceTextureClientHybris stc = surface_texture_client_create_by_igbp(igbp);
265 surface_texture_client_set_hardware_rendering (stc, TRUE);
266 g_object_set (G_OBJECT (
video_sink),
"surface", static_cast<gpointer>(stc), static_cast<char*>(NULL));
272 g_object_set (
pipeline,
"volume", new_volume, NULL);
280 case media::Player::AudioStreamRole::alarm:
283 case media::Player::AudioStreamRole::alert:
286 case media::Player::AudioStreamRole::multimedia:
289 case media::Player::AudioStreamRole::phone:
300 if (g_strcmp0(orientation,
"rotate-0") == 0)
301 return media::Player::Orientation::rotate0;
302 else if (g_strcmp0(orientation,
"rotate-90") == 0)
303 return media::Player::Orientation::rotate90;
304 else if (g_strcmp0(orientation,
"rotate-180") == 0)
305 return media::Player::Orientation::rotate180;
306 else if (g_strcmp0(orientation,
"rotate-270") == 0)
307 return media::Player::Orientation::rotate270;
309 return media::Player::Orientation::rotate0;
315 GstElement *audio_sink = NULL;
316 g_object_get (
pipeline,
"audio-sink", &audio_sink, NULL);
319 std::cout <<
"Audio stream role: " << role_str << std::endl;
321 GstStructure *props = gst_structure_from_string (role_str.c_str(), NULL);
322 if (audio_sink !=
nullptr && props !=
nullptr)
323 g_object_set (audio_sink,
"stream-properties", props, NULL);
327 "Warning: couldn't set audio stream role - couldn't get audio_sink from pipeline" <<
331 gst_structure_free (props);
342 gst_element_query_position (
pipeline, GST_FORMAT_TIME, &pos);
345 return static_cast<uint64_t
>(pos);
351 gst_element_query_duration (
pipeline, GST_FORMAT_TIME, &dur);
354 return static_cast<uint64_t
>(dur);
362 g_object_set(
pipeline,
"uri", uri.c_str(), NULL);
377 if (g_object_class_find_property(G_OBJECT_GET_CLASS(source),
378 "cookies") != NULL) {
379 gchar ** cookies = g_strsplit(
request_headers[
"Cookie"].c_str(),
";", 0);
380 g_object_set(source,
"cookies", cookies, NULL);
386 if (g_object_class_find_property(G_OBJECT_GET_CLASS(source),
387 "user-agent") != NULL) {
388 g_object_set(source,
"user-agent",
request_headers[
"User-Agent"].c_str(), NULL);
395 gchar* data =
nullptr;
396 g_object_get(
pipeline,
"current-uri", &data,
nullptr);
398 std::string result((data ==
nullptr ?
"" : data));
406 static const std::chrono::nanoseconds state_change_timeout
411 std::chrono::milliseconds{5000}
414 auto ret = gst_element_set_state(
pipeline, new_state);
415 bool result =
false; GstState current, pending;
418 case GST_STATE_CHANGE_FAILURE:
419 result =
false;
break;
420 case GST_STATE_CHANGE_NO_PREROLL:
421 case GST_STATE_CHANGE_SUCCESS:
422 result =
true;
break;
423 case GST_STATE_CHANGE_ASYNC:
424 result = GST_STATE_CHANGE_SUCCESS == gst_element_get_state(
428 state_change_timeout.count());
430 if (new_state == GST_STATE_PLAYING)
434 #ifdef DEBUG_GST_PIPELINE
435 std::cout <<
"Dumping pipeline dot file" << std::endl;
436 GST_DEBUG_BIN_TO_DOT_FILE((GstBin*)
pipeline, GST_DEBUG_GRAPH_SHOW_ALL,
"pipeline");
445 bool seek(
const std::chrono::microseconds& ms)
448 return gst_element_seek_simple(
451 (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
457 if (
video_sink !=
nullptr && g_strcmp0(::getenv(
"CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"),
"mirsink") == 0)
465 std::cerr <<
"Could not get the height/width of each video frame" << std::endl;
481 return std::string();
483 std::string filename(uri);
484 std::cout <<
"filename: " << filename << std::endl;
485 size_t pos = uri.find(
"file://");
486 if (pos != std::string::npos)
487 filename = uri.substr(pos + 7, std::string::npos);
492 return std::string(
"audio/video/");
495 GError *error =
nullptr;
496 std::unique_ptr<GFile, void(*)(void *)> file(
497 g_file_new_for_path(filename.c_str()), g_object_unref);
498 std::unique_ptr<GFileInfo, void(*)(void *)> info(
500 file.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE
","
501 G_FILE_ATTRIBUTE_ETAG_VALUE, G_FILE_QUERY_INFO_NONE,
506 std::string error_str(error->message);
509 std::cout <<
"Failed to query the URI for the presence of video content: "
510 << error_str << std::endl;
511 return std::string();
514 std::string content_type(g_file_info_get_attribute_string(
515 info.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE));
527 std::cout <<
"Found audio content" << std::endl;
541 std::cout <<
"Found video content" << std::endl;
567 core::Signal<Bus::Message::Detail::ErrorWarningInfo>
on_error;
568 core::Signal<Bus::Message::Detail::ErrorWarningInfo>
on_warning;
569 core::Signal<Bus::Message::Detail::ErrorWarningInfo>
on_info;
582 #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)
void setup_source(GstElement *source)
void get_video_dimensions()
void set_audio_stream_role(media::Player::AudioStreamRole new_audio_role)
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
int get_video_width() const
core::Signal< Bus::Message::Detail::ErrorWarningInfo > on_warning
core::Connection on_new_message_connection
void set_uri(const std::string &uri, const core::ubuntu::media::Player::HeadersType &headers=core::ubuntu::media::Player::HeadersType())
int get_video_height() const
core::Signal< uint64_t > on_seeked_to
void on_new_message(const Bus::Message &message)
void set_lifetime(media::Player::Lifetime lifetime)
core::Signal< media::Player::Orientation > on_orientation_changed
media::Player::Orientation orientation_lut(const gchar *orientation)
SurfaceTextureClientHybris stc_hybris
MediaFileType media_file_type() const
void setup_pipeline_for_audio_video()
media::Player::Lifetime player_lifetime
union gstreamer::Bus::Message::Detail detail
static std::string get_audio_role_str(media::Player::AudioStreamRole audio_role)
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
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
core::Signal< uint32_t, uint32_t > on_add_frame_dimension
void set_volume(double new_volume)
core::Signal< Bus::Message::Detail::ErrorWarningInfo > on_error
void create_video_sink(uint32_t texture_id)
core::Signal< void > client_disconnected
core::ubuntu::media::Player::HeadersType request_headers
static void source_setup(GstElement *, GstElement *source, gpointer user_data)
uint64_t position() const
static const std::string & pipeline_name()
gstreamer::Bus & message_bus()
struct gstreamer::Bus::Message::Detail::StateChanged state_changed