Codebase list kmscube / 86f0ab9
gst-decoder.c: add bus watch The bus watch is useful for logging state changes, printing out info/warning/error messages and handling common GStreamer activities like latency redistribution and state change requests (that are sent by elements since they are not allowed to directly change the state). State changes and error messages can also cause a dot graph of the pipeline to be generated if the GST_DEBUG_DUMP_DOT_DIR environment variable is set. See the GST_DEBUG_BIN_TO_DOT_FILE documentation for more. Signed-off-by: Carlos Rafael Giani <dv@pseudoterminal.org> Carlos Rafael Giani authored 7 years ago Rob Clark committed 7 years ago
1 changed file(s) with 103 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
135135 }
136136 }
137137
138 static gboolean
139 bus_watch_cb(GstBus *bus, GstMessage *msg, gpointer user_data)
140 {
141 struct decoder *dec = (struct decoder *)user_data;
142
143 (void)bus;
144
145 switch (GST_MESSAGE_TYPE(msg)) {
146 case GST_MESSAGE_STATE_CHANGED: {
147 gchar *dotfilename;
148 GstState old_gst_state, cur_gst_state, pending_gst_state;
149
150 /* Only consider state change messages coming from
151 * the toplevel element. */
152 if (GST_MESSAGE_SRC(msg) != GST_OBJECT(dec->pipeline))
153 break;
154
155 gst_message_parse_state_changed(msg, &old_gst_state, &cur_gst_state, &pending_gst_state);
156
157 printf(
158 "GStreamer state change: old: %s current: %s pending: %s\n",
159 gst_element_state_get_name(old_gst_state),
160 gst_element_state_get_name(cur_gst_state),
161 gst_element_state_get_name(pending_gst_state)
162 );
163
164 dotfilename = g_strdup_printf(
165 "statechange__old-%s__cur-%s__pending-%s",
166 gst_element_state_get_name(old_gst_state),
167 gst_element_state_get_name(cur_gst_state),
168 gst_element_state_get_name(pending_gst_state)
169 );
170 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(dec->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, dotfilename);
171 g_free(dotfilename);
172
173 break;
174 }
175 case GST_MESSAGE_REQUEST_STATE: {
176 GstState requested_state;
177 gst_message_parse_request_state(msg, &requested_state);
178 printf(
179 "state change to %s was requested by %s\n",
180 gst_element_state_get_name(requested_state),
181 GST_MESSAGE_SRC_NAME(msg)
182 );
183 gst_element_set_state(GST_ELEMENT(dec->pipeline), requested_state);
184 break;
185 }
186 case GST_MESSAGE_LATENCY: {
187 printf("redistributing latency\n");
188 gst_bin_recalculate_latency(GST_BIN(dec->pipeline));
189 break;
190 }
191 case GST_MESSAGE_INFO:
192 case GST_MESSAGE_WARNING:
193 case GST_MESSAGE_ERROR: {
194 GError *error = NULL;
195 gchar *debug_info = NULL;
196 gchar const *prefix;
197
198 switch (GST_MESSAGE_TYPE(msg)) {
199 case GST_MESSAGE_INFO:
200 gst_message_parse_info(msg, &error, &debug_info);
201 prefix = "INFO";
202 break;
203 case GST_MESSAGE_WARNING:
204 gst_message_parse_warning(msg, &error, &debug_info);
205 prefix = "WARNING";
206 break;
207 case GST_MESSAGE_ERROR:
208 gst_message_parse_error(msg, &error, &debug_info);
209 prefix = "ERROR";
210 break;
211 default:
212 g_assert_not_reached();
213 }
214 printf("GStreamer %s: %s; debug info: %s", prefix, error->message, debug_info);
215
216 g_clear_error(&error);
217 g_free(debug_info);
218
219 if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
220 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(dec->pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "error");
221 }
222
223 // TODO: stop mainloop in case of an error
224
225 break;
226 }
227 default:
228 break;
229 }
230
231 return TRUE;
232 }
233
138234 struct decoder *
139235 video_init(const struct egl *egl, const struct gbm *gbm, const char *filename)
140236 {
141237 struct decoder *dec;
142238 GstElement *src, *decodebin;
239 GstBus *bus;
143240
144241 dec = calloc(1, sizeof(*dec));
145242 dec->loop = g_main_loop_new(NULL, FALSE);
169266 /* hack to make sure we get dmabuf's from v4l2video0dec.. */
170267 decodebin = gst_bin_get_by_name(GST_BIN(dec->pipeline), "decode");
171268 g_signal_connect(decodebin, "element-added", G_CALLBACK(element_added_cb), dec);
269
270 /* add bus to be able to receive error message, handle latency
271 * requests, produce pipeline dumps, etc. */
272 bus = gst_pipeline_get_bus(GST_PIPELINE(dec->pipeline));
273 gst_bus_add_watch(bus, bus_watch_cb, dec);
274 gst_object_unref(GST_OBJECT(bus));
172275
173276 /* let 'er rip! */
174277 gst_element_set_state(dec->pipeline, GST_STATE_PLAYING);