static gboolean app_run (App * app, int argc, char *argv[]) { if (argc < 2) { g_message ("no bitstream file specified"); return FALSE; } app->file_name = g_strdup (argv[1]); if (!g_file_test (app->file_name, G_FILE_TEST_IS_REGULAR)) { g_message ("failed to find file '%s'", app->file_name); return FALSE; } app->codec = identify_codec (app->file_name); if (!app->codec) { app->codec = identify_codec_from_string (g_codec_str); if (!app->codec) { g_message ("failed to identify codec for '%s'", app->file_name); return FALSE; } } g_print ("Simple decoder (%s bitstream)\n", string_from_codec (app->codec)); app->display = video_output_create_display (NULL); if (!app->display) { g_message ("failed to create VA display"); return FALSE; } app->window = video_output_create_window (app->display, app->window_width, app->window_height); if (!app->window) { g_message ("failed to create window"); return FALSE; } gst_vaapi_window_show (app->window); if (!start_decoder (app)) { g_message ("failed to start decoder thread"); return FALSE; } if (!start_renderer (app)) { g_message ("failed to start renderer thread"); return FALSE; } app_check_events (app); stop_renderer (app); stop_decoder (app); g_print ("Decoded %u frames", app->num_frames); if (g_benchmark) { const gdouble elapsed = g_timer_elapsed (app->timer, NULL); g_print (" in %.2f sec (%.1f fps)\n", elapsed, (gdouble) app->num_frames / elapsed); } g_print ("\n"); return TRUE; }
GstStateChangeReturn gst_sandboxed_decodebin_change_state (GstElement *element, GstStateChange state_change) { GError *error = NULL; GstSandboxedDecodebinPrivate *priv; GstSandboxedDecodebin *self = GST_SANDBOXED_DECODEBIN (element); GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; priv = GST_SANDBOXED_DECODEBIN_GET_PRIVATE (self); switch (state_change) { case GST_STATE_CHANGE_NULL_TO_READY: /* TODO: set up file monitoring */ /* spawn subprocess */ priv->subprocess_stdin = start_decoder (priv->shm_audio_socket_path, priv->shm_video_socket_path, &error); if (priv->subprocess_stdin == -1) { GST_WARNING_OBJECT (element, "Could not spawn subprocess: %s", error->message); ret = GST_STATE_CHANGE_FAILURE; } /* set the right fd to fdsink */ g_object_set (priv->fdsink, "fd", priv->subprocess_stdin, NULL); GST_DEBUG_OBJECT (element, "Waiting for shm sockets to be available\n"); while (!self->priv->subprocess_ready) { /* does that count as acceptable code? The alternatives are another * thread to monitor file creation or sleep() */ g_main_context_iteration (NULL, TRUE); } GST_DEBUG_OBJECT (element, "Done waiting\n"); break; case GST_STATE_CHANGE_READY_TO_PAUSED: GST_DEBUG_OBJECT (element, "Going to PAUSED"); break; #if 0 case GST_STATE_CHANGE_READY_TO_PAUSED: /* TODO: check subprocess is ready with the help of file monitoring, if * not, do the change asynchronously */ { GstMessage *message; ret = GST_STATE_CHANGE_ASYNC; message = gst_message_new_async_start (GST_OBJECT_CAST (element), FALSE); parent_class->handle_message (GST_BIN (element), message); /* Yeah, this is a hack */ g_timeout_add (2000, do_async_done, self); } break; #endif case GST_STATE_CHANGE_PAUSED_TO_PLAYING: GST_DEBUG_OBJECT (element, "Going to PLAYING"); break; default: break; } if (ret != GST_STATE_CHANGE_FAILURE) { GstStateChangeReturn bret; bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, state_change); if (bret == GST_STATE_CHANGE_FAILURE) { GST_WARNING_OBJECT (element, "parent change_state failed!"); ret = bret; } } if (ret != GST_STATE_CHANGE_FAILURE) { GstStateChangeReturn fdret; gint fd; switch (state_change) { case GST_STATE_CHANGE_READY_TO_PAUSED: GST_DEBUG_OBJECT (element, "Trying to set fdsink to PLAYING"); fdret = gst_element_set_state (priv->fdsink, GST_STATE_PLAYING); GST_DEBUG_OBJECT (element, "Returned: %s", gst_element_state_change_return_get_name (fdret)); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: g_object_get (priv->audiosrc, "shm-area-name", &priv->audio_shm_area_name, NULL); g_object_get (priv->videosrc, "shm-area-name", &priv->video_shm_area_name, NULL); GST_DEBUG_OBJECT (element, "Name of audio/video shm areas: " "\"%s\" and \"%s\"\n", priv->audio_shm_area_name, priv->video_shm_area_name); break; case GST_STATE_CHANGE_READY_TO_NULL: /* Closing the fd sounds like a polite thing to do now*/ g_object_get (priv->fdsink, "fd", &fd, NULL); close (fd); /* Unlinking the stuff the decoder could not unlink because it doesn't * have the necessary privileges */ GST_DEBUG_OBJECT (element, "Trying to unlink %s and %s", priv->shm_video_socket_path, priv->shm_audio_socket_path); if (-1 == g_unlink (priv->shm_video_socket_path)) GST_WARNING_OBJECT (element, "Could not unlink %s: %m", priv->shm_video_socket_path); if (-1 == g_unlink (priv->shm_audio_socket_path)) GST_WARNING_OBJECT (element, "Could not unlink %s: %m", priv->shm_audio_socket_path); GST_DEBUG_OBJECT (element, "Trying to unlink audio/video shm areas: \"%s\" and \"%s\"\n", priv->audio_shm_area_name, priv->video_shm_area_name); if (-1 == shm_unlink (priv->audio_shm_area_name)) GST_WARNING_OBJECT (element, "Could not unlink shm area %s: %m", priv->audio_shm_area_name); if (-1 == shm_unlink (priv->video_shm_area_name)) GST_WARNING_OBJECT (element, "Could not unlink shm area %s: %m", priv->video_shm_area_name); /* FIXME: where do we free all these strings? */ break; default: break; } } return ret; }