gint current_text; /* the currently selected stream */
gchar *encoding; /* subtitle encoding */
+ guint64 buffer_duration; /* When buffering, the max buffer duration (ns) */
+ guint buffer_size; /* When buffering, the max buffer size (bytes) */
+
/* our play sink */
GstPlaySink *playsink;
#define DEFAULT_FRAME NULL
#define DEFAULT_FONT_DESC NULL
#define DEFAULT_CONNECTION_SPEED 0
+#define DEFAULT_BUFFER_DURATION -1
+#define DEFAULT_BUFFER_SIZE -1
enum
{
PROP_MUTE,
PROP_FRAME,
PROP_FONT_DESC,
- PROP_CONNECTION_SPEED
+ PROP_CONNECTION_SPEED,
+ PROP_BUFFER_SIZE,
+ PROP_BUFFER_DURATION
};
/* signals */
"Network connection speed in kbps (0 = unknown)",
0, G_MAXUINT, DEFAULT_CONNECTION_SPEED,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_klass, PROP_BUFFER_SIZE,
+ g_param_spec_int ("buffer-size", "Buffer size (bytes)",
+ "Buffer size when buffering network streams",
+ -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_klass, PROP_BUFFER_DURATION,
+ g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
+ "Buffer duration when buffering network streams",
+ -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
/**
* GstPlayBin2::about-to-finish
* @playbin: a #GstPlayBin2
playbin->current_video = DEFAULT_CURRENT_VIDEO;
playbin->current_audio = DEFAULT_CURRENT_AUDIO;
playbin->current_text = DEFAULT_CURRENT_TEXT;
+
+ playbin->buffer_duration = DEFAULT_BUFFER_DURATION;
+ playbin->buffer_size = DEFAULT_BUFFER_SIZE;
}
static void
return result;
}
+/* Returns current stream number, or -1 if none has been selected yet */
+static int
+get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels)
+{
+ /* Internal API cleanup would make this easier... */
+ int i;
+ GstPad *pad, *current;
+ GstObject *selector = NULL;
+ int ret = -1;
+
+ for (i = 0; i < channels->len; i++) {
+ pad = g_ptr_array_index (channels, i);
+ if ((selector = gst_pad_get_parent (pad))) {
+ g_object_get (selector, "active-pad", ¤t, NULL);
+
+ if (pad == current) {
+ ret = i;
+ break;
+ }
+ }
+ }
+
+ if (selector)
+ gst_object_unref (selector);
+
+ return ret;
+}
+
static gboolean
gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
{
playbin->connection_speed = g_value_get_uint (value) * 1000;
GST_PLAY_BIN_UNLOCK (playbin);
break;
+ case PROP_BUFFER_SIZE:
+ playbin->buffer_size = g_value_get_int (value);
+ break;
+ case PROP_BUFFER_DURATION:
+ playbin->buffer_duration = g_value_get_int64 (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_value_set_uint (value, playbin->connection_speed / 1000);
GST_PLAY_BIN_UNLOCK (playbin);
break;
+ case PROP_BUFFER_SIZE:
+ GST_OBJECT_LOCK (playbin);
+ g_value_set_int (value, playbin->buffer_size);
+ GST_OBJECT_UNLOCK (playbin);
+ break;
+ case PROP_BUFFER_DURATION:
+ GST_OBJECT_LOCK (playbin);
+ g_value_set_int64 (value, playbin->buffer_duration);
+ GST_OBJECT_UNLOCK (playbin);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
static void
+selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
+ GstPlayBin * playbin)
+{
+ gchar *property;
+ GstSourceGroup *group;
+ GstSourceSelect *select = NULL;
+ int i;
+
+ GST_PLAY_BIN_LOCK (playbin);
+ group = get_group (playbin);
+
+ for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
+ if (selector == G_OBJECT (group->selector[i].selector)) {
+ select = &group->selector[i];
+ }
+ }
+
+ switch (select->type) {
+ case GST_PLAY_SINK_TYPE_VIDEO:
+ case GST_PLAY_SINK_TYPE_VIDEO_RAW:
+ property = "current-video";
+ playbin->current_video = get_current_stream_number (playbin,
+ group->video_channels);
+ break;
+ case GST_PLAY_SINK_TYPE_AUDIO:
+ case GST_PLAY_SINK_TYPE_AUDIO_RAW:
+ property = "current-audio";
+ playbin->current_audio = get_current_stream_number (playbin,
+ group->audio_channels);
+ break;
+ case GST_PLAY_SINK_TYPE_TEXT:
+ property = "current-text";
+ playbin->current_text = get_current_stream_number (playbin,
+ group->text_channels);
+ break;
+ default:
+ property = NULL;
+ }
+ GST_PLAY_BIN_UNLOCK (playbin);
+
+ if (property)
+ g_object_notify (G_OBJECT (playbin), property);
+}
+
+static void
selector_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
{
/* no nothing */
}
/* this function is called when a new pad is added to decodebin. We check the
- * type of the pad and add it to the selecter element of the group.
+ * type of the pad and add it to the selector element of the group.
*/
static void
pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
GstPadLinkReturn res;
GstSourceSelect *select = NULL;
gint i;
+ gboolean changed = FALSE;
playbin = group->playbin;
if (select->selector == NULL)
goto no_selector;
+ g_signal_connect (select->selector, "notify::active-pad",
+ G_CALLBACK (selector_active_pad_changed), playbin);
+
GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
gst_bin_add (GST_BIN_CAST (playbin), select->selector);
gst_element_set_state (select->selector, GST_STATE_PAUSED);
/* store selector pad so we can release it */
g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
+
+ changed = TRUE;
}
GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
GST_DEBUG_PAD_NAME (pad), select->selector);
GST_SOURCE_GROUP_UNLOCK (group);
+ if (changed) {
+ int signal;
+ switch (select->type) {
+ case GST_PLAY_SINK_TYPE_VIDEO:
+ case GST_PLAY_SINK_TYPE_VIDEO_RAW:
+ signal = SIGNAL_VIDEO_CHANGED;
+ break;
+ case GST_PLAY_SINK_TYPE_AUDIO:
+ case GST_PLAY_SINK_TYPE_AUDIO_RAW:
+ signal = SIGNAL_AUDIO_CHANGED;
+ break;
+ case GST_PLAY_SINK_TYPE_TEXT:
+ signal = SIGNAL_TEXT_CHANGED;
+ break;
+ default:
+ signal = -1;
+ }
+
+ if (signal >= 0)
+ g_signal_emit (G_OBJECT (playbin), gst_play_bin_signals[signal], 0, NULL);
+ }
+
return;
/* ERRORS */
g_object_set (uridecodebin, "subtitle-encoding", playbin->encoding, NULL);
/* configure uri */
g_object_set (uridecodebin, "uri", group->uri, NULL);
+ g_object_set (uridecodebin, "buffer-time", playbin->buffer_duration, NULL);
+ g_object_set (uridecodebin, "buffer-size", playbin->buffer_size, NULL);
/* connect pads and other things */
g_signal_connect (uridecodebin, "pad-added", G_CALLBACK (pad_added_cb),
gchar *encoding;
gboolean is_stream;
+ guint64 buffer_duration; /* When streaming, buffer duration (ns) */
+ guint buffer_size; /* When streaming, buffer size (bytes) */
+
GstElement *source;
GstElement *typefind;
guint have_type_id; /* have-type signal id from typefind */
#define DEFAULT_CONNECTION_SPEED 0
#define DEFAULT_CAPS NULL
#define DEFAULT_SUBTITLE_ENCODING NULL
+#define DEFAULT_BUFFER_DURATION -1
+#define DEFAULT_BUFFER_SIZE -1
enum
{
PROP_CONNECTION_SPEED,
PROP_CAPS,
PROP_SUBTITLE_ENCODING,
+ PROP_BUFFER_SIZE,
+ PROP_BUFFER_DURATION,
PROP_LAST
};
"ISO-8859-15 will be assumed.", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
+ g_param_spec_int ("buffer-size", "Buffer size (bytes)",
+ "Buffer size when buffering network streams",
+ -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_BUFFER_DURATION,
+ g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
+ "Buffer duration when buffering network streams",
+ -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
/**
* GstURIDecodeBin::unknown-type:
* @pad: the new pad containing caps that cannot be resolved to a 'final'
dec->connection_speed = DEFAULT_CONNECTION_SPEED;
dec->caps = DEFAULT_CAPS;
dec->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
+
+ dec->buffer_duration = DEFAULT_BUFFER_DURATION;
+ dec->buffer_size = DEFAULT_BUFFER_SIZE;
}
static void
case PROP_SUBTITLE_ENCODING:
gst_uri_decode_bin_set_encoding (dec, g_value_get_string (value));
break;
+ case PROP_BUFFER_SIZE:
+ dec->buffer_size = g_value_get_int (value);
+ break;
+ case PROP_BUFFER_DURATION:
+ dec->buffer_duration = g_value_get_int64 (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_value_set_string (value, dec->encoding);
GST_OBJECT_UNLOCK (dec);
break;
+ case PROP_BUFFER_SIZE:
+ GST_OBJECT_LOCK (dec);
+ g_value_set_int (value, dec->buffer_size);
+ GST_OBJECT_UNLOCK (dec);
+ break;
+ case PROP_BUFFER_DURATION:
+ GST_OBJECT_LOCK (dec);
+ g_value_set_int64 (value, dec->buffer_duration);
+ GST_OBJECT_UNLOCK (dec);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL);
// g_object_set (G_OBJECT (queue), "temp-location", "temp", NULL);
+ /* Disable max-size-buffers */
+ g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL);
+
+ /* If buffer size or duration are set, set them on the queue2 element */
+ if (decoder->buffer_size != -1)
+ g_object_set (G_OBJECT (queue), "max-size-bytes",
+ decoder->buffer_size, NULL);
+ if (decoder->buffer_duration != -1)
+ g_object_set (G_OBJECT (queue), "max-size-time",
+ decoder->buffer_duration, NULL);
+
gst_bin_add (GST_BIN_CAST (decoder), queue);
if (!gst_element_link (typefind, queue))