<div dir="ltr"><br><div class="gmail_quote"><div dir="ltr"><div>Hi,<br></div><div>Following is my code for a very basic file player. It is using playbin.<br></div><div>Basically I am trying to understand the tric play functionalities of gstreamer pipelines.<br>
</div>
<div>I am very new to gstreamer world.<br></div><div>I noticed that every time I change the speed the pipline freezes for few seconds and then reflects the change. <br></div><div>I am using VAAPI enabled system. any way to debug specifically the cause of those frozen moments.<br>
</div><div>Thanks in advance. <br></div><div><br><br>#include <string.h><br>#include <gst/gst.h><br>#include <iostream><br>#include <stdio.h><br><br>typedef struct _CustomData {<br> GstElement *pipeline;<br>
GstElement *video_sink;<br> GMainLoop *loop;<br><br> gboolean playing; /* Playing or Paused */<br> gdouble rate; /* Current playback rate (can be negative) */<br>} CustomData;<br><br>/* Send seek event to change rate */<br>
static void send_seek_event (CustomData *data) {<br> gint64 position;<br> GstFormat format = GST_FORMAT_TIME;<br> GstEvent *seek_event;<br> <br> g_print(" SEEK EVENT RECEIVED. \n");<br><br> /* Obtain the current position, needed for the seek event */<br>
if (!gst_element_query_position (data->pipeline, format, &position)) {<br> g_printerr ("Unable to retrieve current position.\n");<br> return;<br> }<br><br> /* Create the seek event */<br>
if (data->rate > 0) {<br> seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, /*GST_SEEK_FLAG_FLUSH |*/ GST_SEEK_FLAG_ACCURATE,<br> GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE,0);<br>
} else {<br> seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, /*GST_SEEK_FLAG_FLUSH |*/ GST_SEEK_FLAG_ACCURATE,<br> GST_SEEK_TYPE_SET,0, GST_SEEK_TYPE_SET, position);<br> }<br>
<br> if (data->video_sink == NULL) {<br> /* If we have not done so, obtain the sink through which we will send the seek events */<br> g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL);<br>
}<br><br> /* Send the event */<br> gst_element_send_event (data->video_sink, seek_event);<br><br> g_print ("Current rate: %g\n", data->rate);<br>}<br><br>/* Process keyboard input */<br>static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) {<br>
gchar *str = NULL;<br><br> if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) {<br> return TRUE;<br> }<br><br> switch (g_ascii_tolower (str[0])) {<br> case 'p':<br>
data->playing = !data->playing;<br> gst_element_set_state (data->pipeline, data->playing ? GST_STATE_PLAYING : GST_STATE_PAUSED);<br> g_print ("Setting state to %s\n", data->playing ? "PLAYING" : "PAUSE");<br>
break;<br> case 's':<br> if (g_ascii_isupper (str[0])) <br> {<br> <br> data->rate *= 2.0;<br> } <br>
else <br>
{<br> data->rate /= 2.0;<br> }<br> send_seek_event (data);<br> break;<br> case 'd':<br> data->rate *= -1.0;<br> send_seek_event (data);<br>
break;<br> case 'n':<br> if (data->video_sink == NULL) {<br> /* If we have not done so, obtain the sink through which we will send the step events */<br> g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL);<br>
}<br><br> gst_element_send_event (data->video_sink,<br> gst_event_new_step (GST_FORMAT_BUFFERS, 1, data->rate, TRUE, FALSE));<br> g_print ("Stepping one frame\n");<br>
break;<br> case 'q':<br> g_main_loop_quit (data->loop);<br> break;<br> default:<br> break;<br> }<br><br> g_free (str);<br><br> return TRUE;<br>
}<br><br>int main(int argc, char *argv[]) {<br> CustomData data;<br> GstStateChangeReturn ret;<br> GIOChannel *io_stdin;<br><br> /* Initialize GStreamer */<br> gst_init (&argc, &argv);<br><br> /* Initialize our data structure */<br>
memset (&data, 0, sizeof (data));<br><br> /* Print usage map */<br> g_print (<br> "USAGE: Choose one of the following options, then press enter:\n"<br> " 'P' to toggle between PAUSE and PLAY\n"<br>
" 'S' to increase playback speed, 's' to decrease playback speed\n"<br> " 'D' to toggle playback direction\n"<br> " 'N' to move to next frame (in the current direction, better in PAUSE)\n"<br>
" 'Q' to quit\n");<br><br> /* Build the pipeline */<br>// data.pipeline = gst_parse_launch ("playbin2 uri=<a href="http://docs.gstreamer.com/media/sintel_trailer-480p.webm" target="_blank">http://docs.gstreamer.com/media/sintel_trailer-480p.webm</a>", NULL);<br>
data.pipeline = gst_parse_launch ("playbin uri=file:///home/ufouser/Tata_1080p24_H264.mp4", NULL);<br><br> /* Add a keyboard watch so we get notified of keystrokes */<br>#ifdef _WIN32<br> io_stdin = g_io_channel_win32_new_fd (fileno (stdin));<br>
#else<br> io_stdin = g_io_channel_unix_new (fileno (stdin));<br>#endif<br> g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);<br><br> /* Start playing */<br> ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);<br>
if (ret == GST_STATE_CHANGE_FAILURE) {<br> g_printerr ("Unable to set the pipeline to the playing state.\n");<br> gst_object_unref (data.pipeline);<br> return -1;<br> }<br> data.playing = TRUE;<br>
data.rate = 1.0;<br><br> /* Create a GLib Main Loop and set it to run */<br> data.loop = g_main_loop_new (NULL, FALSE);<br> g_main_loop_run (data.loop);<br><br> /* Free resources */<br> g_main_loop_unref (data.loop);<br>
g_io_channel_unref (io_stdin);<br> gst_element_set_state (data.pipeline, GST_STATE_NULL);<br> if (data.video_sink != NULL)<br> gst_object_unref (data.video_sink);<br> gst_object_unref (data.pipeline);<br>
return 0;<br>}<br></div></div></div><div><br></div>-- <br>Regards<br>Subodh
</div>