Merge lp:~alfonsosanchezbeato/media-hub/get-streams into lp:media-hub

Proposed by Alfonso Sanchez-Beato
Status: Merged
Approved by: Alfonso Sanchez-Beato
Approved revision: 156
Merged at revision: 156
Proposed branch: lp:~alfonsosanchezbeato/media-hub/get-streams
Merge into: lp:media-hub
Diff against target: 229 lines (+104/-7)
5 files modified
debian/control (+1/-0)
src/core/media/CMakeLists.txt (+2/-0)
src/core/media/gstreamer/engine.cpp (+22/-5)
src/core/media/gstreamer/playbin.cpp (+72/-2)
src/core/media/gstreamer/playbin.h (+7/-0)
To merge this branch: bzr merge lp:~alfonsosanchezbeato/media-hub/get-streams
Reviewer Review Type Date Requested Status
Alfonso Sanchez-Beato Approve
Review via email: mp+270286@code.launchpad.net

Commit message

Gather information about missing codecs and selected streams from gstreamer so we have more information on whether we should play the video or not.

Description of the change

Gather information about missing codecs and selected streams from gstreamer so we have more information on whether we should play the video or not.

To post a comment you must log in.
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2015-09-01 08:30:08 +0000
3+++ debian/control 2015-09-07 10:28:21 +0000
4@@ -21,6 +21,7 @@
5 libprocess-cpp-dev,
6 libproperties-cpp-dev,
7 libgstreamer1.0-dev,
8+ libgstreamer-plugins-base1.0-dev,
9 pkg-config,
10 libpulse-dev,
11 qtbase5-dev,
12
13=== modified file 'src/core/media/CMakeLists.txt'
14--- src/core/media/CMakeLists.txt 2015-07-02 12:30:09 +0000
15+++ src/core/media/CMakeLists.txt 2015-09-07 10:28:21 +0000
16@@ -1,4 +1,5 @@
17 pkg_check_modules(PC_GSTREAMER_1_0 REQUIRED gstreamer-1.0)
18+pkg_check_modules(PC_GSTREAMER_PBUTILS_1_0 REQUIRED gstreamer-pbutils-1.0)
19 pkg_check_modules(PC_PULSE_AUDIO REQUIRED libpulse)
20 include_directories(${PC_GSTREAMER_1_0_INCLUDE_DIRS} ${HYBRIS_MEDIA_CFLAGS} ${PC_PULSE_AUDIO_INCLUDE_DIRS})
21
22@@ -126,6 +127,7 @@
23 ${DBUS_CPP_LDFLAGS}
24 ${GLog_LIBRARY}
25 ${PC_GSTREAMER_1_0_LIBRARIES}
26+ ${PC_GSTREAMER_PBUTILS_1_0_LIBRARIES}
27 ${PROCESS_CPP_LDFLAGS}
28 ${GIO_LIBRARIES}
29 ${HYBRIS_MEDIA_LIBRARIES}
30
31=== modified file 'src/core/media/gstreamer/engine.cpp'
32--- src/core/media/gstreamer/engine.cpp 2015-08-11 15:25:50 +0000
33+++ src/core/media/gstreamer/engine.cpp 2015-09-07 10:28:21 +0000
34@@ -67,8 +67,22 @@
35 {
36 if (p.second == "playbin")
37 {
38- std::cout << "State changed on playbin: " << p.first.new_state << std::endl;
39- playback_status_changed(gst_state_to_player_status(p.first));
40+ std::cout << "State changed on playbin: "
41+ << gst_element_state_get_name(p.first.new_state) << std::endl;
42+ const auto status = gst_state_to_player_status(p.first);
43+ /*
44+ * When state moves to "paused" the pipeline is already set. We check that we
45+ * have streams to play.
46+ */
47+ if (status == media::Player::PlaybackStatus::paused &&
48+ !playbin.can_play_streams()) {
49+ std::cerr << "** Cannot play: some codecs are missing" << std::endl;
50+ playbin.reset();
51+ const media::Player::Error e = media::Player::Error::format_error;
52+ error(e);
53+ } else {
54+ playback_status_changed(status);
55+ }
56 }
57 }
58
59@@ -149,7 +163,8 @@
60 break;
61 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
62 std::cerr << "** Encountered a GST_STREAM_ERROR_CODEC_NOT_FOUND" << std::endl;
63- ret_error = media::Player::Error::format_error;
64+ // Missing codecs are handled later, when state switches to "paused"
65+ ret_error = media::Player::Error::no_error;
66 break;
67 case GST_STREAM_ERROR_DECODE:
68 std::cerr << "** Encountered a GST_STREAM_ERROR_DECODE" << std::endl;
69@@ -163,8 +178,10 @@
70 }
71 }
72
73- std::cout << "Resetting playbin pipeline after unrecoverable error" << std::endl;
74- playbin.reset();
75+ if (ret_error != media::Player::Error::no_error) {
76+ std::cerr << "Resetting playbin pipeline after unrecoverable error" << std::endl;
77+ playbin.reset();
78+ }
79 return ret_error;
80 }
81
82
83=== modified file 'src/core/media/gstreamer/playbin.cpp'
84--- src/core/media/gstreamer/playbin.cpp 2015-07-24 14:54:19 +0000
85+++ src/core/media/gstreamer/playbin.cpp 2015-09-07 10:28:21 +0000
86@@ -1,5 +1,5 @@
87 /*
88- * Copyright © 2013 Canonical Ltd.
89+ * Copyright © 2013-2015 Canonical Ltd.
90 *
91 * This program is free software: you can redistribute it and/or modify it
92 * under the terms of the GNU Lesser General Public License version 3,
93@@ -20,6 +20,8 @@
94
95 #include <core/media/gstreamer/engine.h>
96
97+#include <gst/pbutils/missing-plugins.h>
98+
99 #if defined(MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
100 #include <hybris/media/surface_texture_client_hybris.h>
101 #include <hybris/media/media_codec_layer.h>
102@@ -112,7 +114,11 @@
103 core::ubuntu::media::video::Width{0}},
104 player_lifetime(media::Player::Lifetime::normal),
105 about_to_finish_handler_id(0),
106- source_setup_handler_id(0)
107+ source_setup_handler_id(0),
108+ is_missing_audio_codec(false),
109+ is_missing_video_codec(false),
110+ audio_stream_id(-1),
111+ video_stream_id(-1)
112 {
113 if (!pipeline)
114 throw std::runtime_error("Could not create pipeline for playbin.");
115@@ -177,6 +183,44 @@
116 std::cout << "Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl;
117 }
118 file_type = MEDIA_FILE_TYPE_NONE;
119+ is_missing_audio_codec = false;
120+ is_missing_video_codec = false;
121+ audio_stream_id = -1;
122+ video_stream_id = -1;
123+}
124+
125+void gstreamer::Playbin::process_message_element(GstMessage *message)
126+{
127+ if (!gst_is_missing_plugin_message(message))
128+ return;
129+
130+ gchar *desc = gst_missing_plugin_message_get_description(message);
131+ std::cerr << "Missing plugin: " << desc << std::endl;
132+ g_free(desc);
133+
134+ const GstStructure *msg_data = gst_message_get_structure(message);
135+ if (g_strcmp0("decoder", gst_structure_get_string(msg_data, "type")) != 0)
136+ return;
137+
138+ GstCaps *caps;
139+ if (!gst_structure_get(msg_data, "detail", GST_TYPE_CAPS, &caps, NULL)) {
140+ std::cerr << __PRETTY_FUNCTION__ << ": No detail" << std::endl;
141+ return;
142+ }
143+
144+ GstStructure *caps_data = gst_caps_get_structure(caps, 0);
145+ if (!caps_data) {
146+ std::cerr << __PRETTY_FUNCTION__ << ": No caps data" << std::endl;
147+ return;
148+ }
149+
150+ const gchar *mime = gst_structure_get_name(caps_data);
151+ if (strstr(mime, "audio"))
152+ is_missing_audio_codec = true;
153+ else if (strstr(mime, "video"))
154+ is_missing_video_codec = true;
155+
156+ std::cerr << "Missing decoder for " << mime << std::endl;
157 }
158
159 void gstreamer::Playbin::on_new_message_async(const Bus::Message& message)
160@@ -193,8 +237,15 @@
161 signals.on_info(message.detail.error_warning_info);
162 break;
163 case GST_MESSAGE_STATE_CHANGED:
164+ if (message.source == "playbin") {
165+ g_object_get(G_OBJECT(pipeline), "current-audio", &audio_stream_id, NULL);
166+ g_object_get(G_OBJECT(pipeline), "current-video", &video_stream_id, NULL);
167+ }
168 signals.on_state_changed(std::make_pair(message.detail.state_changed, message.source));
169 break;
170+ case GST_MESSAGE_ELEMENT:
171+ process_message_element(message.message);
172+ break;
173 case GST_MESSAGE_TAG:
174 {
175 gchar *orientation;
176@@ -598,3 +649,22 @@
177 {
178 return file_type;
179 }
180+
181+bool gstreamer::Playbin::can_play_streams() const
182+{
183+ /*
184+ * We do not consider that we can play the video when
185+ * 1. No audio stream selected due to missing decoder
186+ * 2. No video stream selected due to missing decoder
187+ * 3. No stream selected at all
188+ * Note that if there are several, say, audio streams, we will play the file
189+ * provided that we can decode just one of them, even if there are missing
190+ * audio codecs. We will also play files with only one type of stream.
191+ */
192+ if ((is_missing_audio_codec && audio_stream_id == -1) ||
193+ (is_missing_video_codec && video_stream_id == -1) ||
194+ (audio_stream_id == -1 && video_stream_id == -1))
195+ return false;
196+ else
197+ return true;
198+}
199
200=== modified file 'src/core/media/gstreamer/playbin.h'
201--- src/core/media/gstreamer/playbin.h 2015-06-12 18:14:05 +0000
202+++ src/core/media/gstreamer/playbin.h 2015-09-07 10:28:21 +0000
203@@ -72,6 +72,7 @@
204
205 void on_new_message(const Bus::Message& message);
206 void on_new_message_async(const Bus::Message& message);
207+ void process_message_element(GstMessage *message);
208
209 gstreamer::Bus& message_bus();
210
211@@ -110,6 +111,8 @@
212
213 MediaFileType media_file_type() const;
214
215+ bool can_play_streams() const;
216+
217 GstElement* pipeline;
218 gstreamer::Bus bus;
219 MediaFileType file_type;
220@@ -137,6 +140,10 @@
221 core::Signal<core::ubuntu::media::video::Dimensions> on_video_dimensions_changed;
222 core::Signal<void> client_disconnected;
223 } signals;
224+ bool is_missing_audio_codec;
225+ bool is_missing_video_codec;
226+ gint audio_stream_id;
227+ gint video_stream_id;
228 };
229 }
230

Subscribers

People subscribed via source and target branches