Question for stream buffering.
HoonHee Lee
hoonh83.lee at gmail.com
Tue Apr 8 03:29:40 PDT 2014
I have a question for stream buffering with Q2 element via playbin.
And I want to measure buffered-size(undecoded-size) using current-level-byte
or current-level-time from Q2.
What I was intending is that showing up progressive bar such as youtube.
duration : ========== (1:00)
playtime : = (0:10)
buffered size : ==(0:13)
I have refered below docs for buffering.
=>
http://cgit.freedesktop.org/gstreamer/gstreamer/tree/docs/design/part-buffering.txt
Also, I have refered below code for buffering.
=> gst-launch.c (tools) & playback-test.c
(gst-plugins-base\tests\examples\playback)
I have just tested it with below url based on my sample test code with
latest gstreamer version.
=> http://media.w3.org/2010/05/sintel/trailer.mp4
------------------------------------------------------------------------------------------------
my sample test code
/*** block a from ../../../docs/manual/highlevel-playback.xml ***/
#include <gst/gst.h>
static GMainLoop *loop = NULL;
static GstElement *queue2 = NULL;
static gboolean buffering = FALSE;
static GstPadProbeReturn
_queue2_buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer udata)
{
GstElement *playbin = udata;
GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info);
GstState state;
state = GST_STATE (playbin);
GST_WARNING ("_queue2_buffer_probe : playbin state = %d, queue2 state =
%d", state, GST_STATE (queue2));
GST_WARNING ("_queue2_buffer_probe : ts: %" GST_TIME_FORMAT, GST_TIME_ARGS
(GST_BUFFER_TIMESTAMP (buffer)));
return GST_PAD_PROBE_OK;
}
static gboolean
bus_call (GstBus * bus, GstMessage * message, gpointer data)
{
GstElement *playbin = (GstElement *) data;
GstPad *src = NULL;
GstPad *peer = NULL;
GST_WARNING ("bus_call : message = %s", GST_MESSAGE_TYPE_NAME (message));
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ASYNC_DONE:
{
src = gst_element_get_static_pad (queue2, "src");
peer = gst_pad_get_peer (src);
gst_pad_add_probe (peer, GST_PAD_PROBE_TYPE_BUFFER,
_queue2_buffer_probe, playbin, NULL);
break;
}
case GST_MESSAGE_BUFFERING:
{
gint percent;
GstBufferingMode mode;
gint avg_in, avg_out;
gint64 buffering_left;
gst_message_parse_buffering (message, &percent);
gst_message_parse_buffering_stats (message, &mode, &avg_in, &avg_out,
&buffering_left);
GST_WARNING ("@@@@@@@@@@@@@ percent: %d", percent);
GST_WARNING ("@@@@@@@@@@@@@ mode:%d, rates: in: %d, out: %d", mode,
avg_in, avg_out);
GST_WARNING ("@@@@@@@@@@@@@ buffering_left %" G_GUINT64_FORMAT,
buffering_left);
if (percent == 100) {
buffering = FALSE;
gst_element_set_state (playbin, GST_STATE_PLAYING);
} else {
if (buffering == FALSE) {
gst_element_set_state (playbin, GST_STATE_PAUSED);
}
buffering = TRUE;
}
break;
}
case GST_MESSAGE_ERROR:
{
g_main_loop_quit (loop);
break;
}
case GST_MESSAGE_EOS:
g_message ("received EOS");
g_main_loop_quit (loop);
break;
default:
break;
}
return TRUE;
}
static void
playbin_element_added_cb (GstElement * playbin, GstElement * element,
gpointer u_data)
{
GstState state;
GstElementFactory *factory = NULL;
const gchar *klass = NULL;
gchar *elem_name = NULL;
factory = gst_element_get_factory (element);
klass = gst_element_factory_get_metadata (factory,
GST_ELEMENT_METADATA_KLASS);
elem_name = gst_element_get_name (element);
state = GST_STATE (element);
GST_WARNING ("added element = %s, state = %d", elem_name, state);
if (g_strrstr (klass, "Bin"))
g_signal_connect (element, "element-added", G_CALLBACK
(playbin_element_added_cb), playbin);
if (g_strrstr (elem_name, "queue2") && queue2 == NULL)
queue2 = element;
g_free (elem_name);
}
gint
main (gint argc, gchar * argv[])
{
GstElement *playbin;
GstBus *bus;
gchar *uri;
GstStateChangeReturn sret;
gst_init (&argc, &argv);
if (argc < 2) {
GST_ERROR ("usage: %s <media file or uri>\n", argv[0]);
return 1;
}
playbin = gst_element_factory_make ("playbin", NULL);
if (!playbin) {
GST_ERROR ("playbin plugin missing\n");
return 1;
}
if (gst_uri_is_valid (argv[1]))
uri = g_strdup (argv[1]);
else
uri = gst_filename_to_uri (argv[1], NULL);
g_object_set (playbin, "uri", uri, NULL);
g_free (uri);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_element_get_bus (playbin);
if (bus) {
gst_bus_add_signal_watch (bus);
g_signal_connect (bus, "message", G_CALLBACK (bus_call), playbin);
}
g_object_unref (bus);
g_signal_connect (playbin, "element-added", G_CALLBACK
(playbin_element_added_cb), loop);
if (gst_element_set_state (playbin,
GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
GST_DEBUG_OBJECT (playbin, "Failed to paused state");
goto done;
}
sret = gst_element_get_state (playbin, NULL, NULL, -1);
if (sret == GST_STATE_CHANGE_FAILURE) {
GST_DEBUG_OBJECT (playbin, "Failed to get lpbin state");
goto done;
}
g_main_loop_run (loop);
done:
gst_element_set_state (playbin, GST_STATE_NULL);
g_object_unref (playbin);
g_main_loop_unref (loop);
return 0;
}
------------------------------------------------------------------------------------------------
When I have received the buffering message from Q2, I have changed state of
pipeline from playing to paused.
After finished state change, a peer pad of srcpad in Q2 have received the
buffer data for a moment through the chain function. It means that although
buffer is flowing to peer pad when paused state in pipeline.
IMHO, we can not guarantee the accurate bufferd-size(undecoded-size) from Q2
in this situation.
Also, I think that speed of buffering can be slowed caused by repeatedly
buffering percentage is to go up and down.
When I reviewed the Q2's code, there is no explicit code for pausing task
about enquene and dequeue task when state is changed from playing to paused.
gst_queue2_loop() function of Q2 kept to run and gst_pad_push
(queue->srcpad, buffer) operated by gst_queue2_locked_dequeue()
continuously.
It means that gst_queue2_loop() depens on internal logic in GstPad with
GstTask??
But, I am lack of insight GstTask.....
Thus, What I am asking is that data of Q2 is flowing to peerpad is an normal
operating or not when paused state in pipeline?
Or my sample test code is wrong??
And Can I get some advise for this??
Please let me know, if you have any information or advise.
--
View this message in context: http://gstreamer-devel.966125.n4.nabble.com/Question-for-stream-buffering-tp4666355.html
Sent from the GStreamer-devel mailing list archive at Nabble.com.
More information about the gstreamer-devel
mailing list