+ GST_DEBUG_OBJECT (mq, "Going to post buffering: %d%%", percent);
+ msg = gst_message_new_buffering (GST_OBJECT_CAST (mq), percent);
+ }
+ GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+
+ if (msg != NULL)
+ gst_element_post_message (GST_ELEMENT_CAST (mq), msg);
+
+ g_mutex_unlock (&mq->buffering_post_lock);
+}
+
+static void
+recheck_buffering_status (GstMultiQueue * mq)
+{
+ if (!mq->use_buffering && mq->buffering) {
+ GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+ mq->buffering = FALSE;
+ GST_DEBUG_OBJECT (mq,
+ "Buffering property disabled, but queue was still buffering; "
+ "setting buffering percentage to 100%%");
+ SET_PERCENT (mq, 100);
+ GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+ }
+
+ if (mq->use_buffering) {
+ GList *tmp;
+ gint old_perc;
+
+ GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+
+ /* force buffering percentage to be recalculated */
+ old_perc = mq->buffering_percent;
+ mq->buffering_percent = 0;
+
+ tmp = mq->queues;
+ while (tmp) {
+ GstSingleQueue *q = (GstSingleQueue *) tmp->data;
+ update_buffering (mq, q);
+ gst_data_queue_limits_changed (q->queue);
+ tmp = g_list_next (tmp);
+ }
+
+ GST_DEBUG_OBJECT (mq,
+ "Recalculated buffering percentage: old: %d%% new: %d%%",
+ old_perc, mq->buffering_percent);
+
+ GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+ }
+
+ gst_multi_queue_post_buffering (mq);
+}
+
+static void
+calculate_interleave (GstMultiQueue * mq, GstSingleQueue * sq)
+{
+ GstClockTimeDiff low, high;
+ GstClockTime interleave, other_interleave = 0;
+ GList *tmp;
+
+ low = high = GST_CLOCK_STIME_NONE;
+ interleave = mq->interleave;
+ /* Go over all single queues and calculate lowest/highest value */
+ for (tmp = mq->queues; tmp; tmp = tmp->next) {
+ GstSingleQueue *oq = (GstSingleQueue *) tmp->data;
+ /* Ignore sparse streams for interleave calculation */
+ if (oq->is_sparse)
+ continue;
+ /* If a stream is not active yet (hasn't received any buffers), set
+ * a maximum interleave to allow it to receive more data */
+ if (!oq->active) {
+ GST_LOG_OBJECT (mq,
+ "queue %d is not active yet, forcing interleave to 5s", oq->id);
+ mq->interleave = 5 * GST_SECOND;
+ /* Update max-size time */
+ mq->max_size.time = mq->interleave;
+ SET_CHILD_PROPERTY (mq, time);
+ goto beach;
+ }
+
+ /* Calculate within each streaming thread */
+ if (sq && sq->thread != oq->thread) {
+ if (oq->interleave > other_interleave)
+ other_interleave = oq->interleave;
+ continue;
+ }
+
+ if (GST_CLOCK_STIME_IS_VALID (oq->cached_sinktime)) {
+ if (low == GST_CLOCK_STIME_NONE || oq->cached_sinktime < low)
+ low = oq->cached_sinktime;
+ if (high == GST_CLOCK_STIME_NONE || oq->cached_sinktime > high)
+ high = oq->cached_sinktime;
+ }
+ GST_LOG_OBJECT (mq,
+ "queue %d , sinktime:%" GST_STIME_FORMAT " low:%" GST_STIME_FORMAT
+ " high:%" GST_STIME_FORMAT, oq->id,
+ GST_STIME_ARGS (oq->cached_sinktime), GST_STIME_ARGS (low),
+ GST_STIME_ARGS (high));
+ }
+
+ if (GST_CLOCK_STIME_IS_VALID (low) && GST_CLOCK_STIME_IS_VALID (high)) {
+ interleave = high - low;
+ /* Padding of interleave and minimum value */
+ interleave = (150 * interleave / 100) + mq->min_interleave_time;
+ if (sq)
+ sq->interleave = interleave;
+
+ interleave = MAX (interleave, other_interleave);
+
+ /* Update the stored interleave if:
+ * * No data has arrived yet (high == low)
+ * * Or it went higher
+ * * Or it went lower and we've gone past the previous interleave needed */
+ if (high == low || interleave > mq->interleave ||
+ ((mq->last_interleave_update + (2 * MIN (GST_SECOND,
+ mq->interleave)) < low)
+ && interleave < (mq->interleave * 3 / 4))) {
+ /* Update the interleave */
+ mq->interleave = interleave;
+ mq->last_interleave_update = high;
+ /* Update max-size time */
+ mq->max_size.time = mq->interleave;
+ SET_CHILD_PROPERTY (mq, time);
+ }