X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Felements%2Fgstqueue2.c;h=51db8285ba4ba01976d2303c154310815e4ef247;hb=64a1d4ad0bcc79b09ac0d0636927597ed50943c7;hp=67e3f277f253389de3697b9fa916bee78d87f28c;hpb=555df9d614149fa0a094c14788b61e16a439b3f8;p=platform%2Fupstream%2Fgstreamer.git diff --git a/plugins/elements/gstqueue2.c b/plugins/elements/gstqueue2.c index 67e3f27..51db828 100644 --- a/plugins/elements/gstqueue2.c +++ b/plugins/elements/gstqueue2.c @@ -25,6 +25,7 @@ /** * SECTION:element-queue2 + * @title: queue2 * * Data is queued until one of the limits specified by the * #GstQueue2:max-size-buffers, #GstQueue2:max-size-bytes and/or @@ -117,6 +118,8 @@ enum #define DEFAULT_USE_RATE_ESTIMATE TRUE #define DEFAULT_LOW_PERCENT 10 #define DEFAULT_HIGH_PERCENT 99 +#define DEFAULT_LOW_WATERMARK 0.01 +#define DEFAULT_HIGH_WATERMARK 0.99 #define DEFAULT_TEMP_REMOVE TRUE #define DEFAULT_RING_BUFFER_MAX_SIZE 0 @@ -134,6 +137,8 @@ enum PROP_USE_RATE_ESTIMATE, PROP_LOW_PERCENT, PROP_HIGH_PERCENT, + PROP_LOW_WATERMARK, + PROP_HIGH_WATERMARK, PROP_TEMP_TEMPLATE, PROP_TEMP_LOCATION, PROP_TEMP_REMOVE, @@ -142,6 +147,32 @@ enum PROP_LAST }; +/* Explanation for buffer levels and percentages: + * + * The buffering_level functions here return a value in a normalized range + * that specifies the queue's current fill level. The range goes from 0 to + * MAX_BUFFERING_LEVEL. The low/high watermarks also use this same range. + * + * This is not to be confused with the buffering_percent value, which is + * a *relative* quantity - relative to the low/high watermarks. + * buffering_percent = 0% means buffering_level is at the low watermark. + * buffering_percent = 100% means buffering_level is at the high watermark. + * buffering_percent is used for determining if the fill level has reached + * the high watermark, and for producing BUFFERING messages. This value + * always uses a 0..100 range (since it is a percentage). + * + * To avoid future confusions, whenever "buffering level" is mentioned, it + * refers to the absolute level which is in the 0..MAX_BUFFERING_LEVEL + * range. Whenever "buffering_percent" is mentioned, it refers to the + * percentage value that is relative to the low/high watermark. */ + +/* Using a buffering level range of 0..1000000 to allow for a + * resolution in ppm (1 ppm = 0.0001%) */ +#define MAX_BUFFERING_LEVEL 1000000 + +/* How much 1% makes up in the buffer level range */ +#define BUF_LEVEL_PERCENT_FACTOR ((MAX_BUFFERING_LEVEL) / 100) + #define GST_QUEUE2_CLEAR_LEVEL(l) G_STMT_START { \ l.buffers = 0; \ l.bytes = 0; \ @@ -248,8 +279,8 @@ static GstFlowReturn gst_queue2_chain_list (GstPad * pad, GstObject * parent, static GstFlowReturn gst_queue2_push_one (GstQueue2 * queue); static void gst_queue2_loop (GstPad * pad); -static gboolean gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event); +static GstFlowReturn gst_queue2_handle_sink_event (GstPad * pad, + GstObject * parent, GstEvent * event); static gboolean gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent, GstQuery * query); @@ -274,7 +305,8 @@ static gboolean gst_queue2_is_empty (GstQueue2 * queue); static gboolean gst_queue2_is_filled (GstQueue2 * queue); static void update_cur_level (GstQueue2 * queue, GstQueue2Range * range); -static void update_in_rates (GstQueue2 * queue); +static void update_in_rates (GstQueue2 * queue, gboolean force); +static GstMessage *gst_queue2_get_buffering_message (GstQueue2 * queue); static void gst_queue2_post_buffering (GstQueue2 * queue); typedef enum @@ -353,13 +385,25 @@ gst_queue2_class_init (GstQueue2Class * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_LOW_PERCENT, g_param_spec_int ("low-percent", "Low percent", - "Low threshold for buffering to start. Only used if use-buffering is True", - 0, 100, DEFAULT_LOW_PERCENT, + "Low threshold for buffering to start. Only used if use-buffering is True " + "(Deprecated: use low-watermark instead)", + 0, 100, DEFAULT_LOW_WATERMARK * 100, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_HIGH_PERCENT, g_param_spec_int ("high-percent", "High percent", + "High threshold for buffering to finish. Only used if use-buffering is True " + "(Deprecated: use high-watermark instead)", + 0, 100, DEFAULT_HIGH_WATERMARK * 100, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_LOW_WATERMARK, + g_param_spec_double ("low-watermark", "Low watermark", + "Low threshold for buffering to start. Only used if use-buffering is True", + 0.0, 1.0, DEFAULT_LOW_WATERMARK, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HIGH_WATERMARK, + g_param_spec_double ("high-watermark", "High watermark", "High threshold for buffering to finish. Only used if use-buffering is True", - 0, 100, DEFAULT_HIGH_PERCENT, + 0.0, 1.0, DEFAULT_HIGH_WATERMARK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_TEMP_TEMPLATE, @@ -410,10 +454,8 @@ gst_queue2_class_init (GstQueue2Class * klass) /* set several parent class virtual functions */ gobject_class->finalize = gst_queue2_finalize; - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&srctemplate)); - gst_element_class_add_pad_template (gstelement_class, - gst_static_pad_template_get (&sinktemplate)); + gst_element_class_add_static_pad_template (gstelement_class, &srctemplate); + gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate); gst_element_class_set_static_metadata (gstelement_class, "Queue 2", "Generic", @@ -436,7 +478,7 @@ gst_queue2_init (GstQueue2 * queue) GST_DEBUG_FUNCPTR (gst_queue2_chain_list)); gst_pad_set_activatemode_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue2_sink_activate_mode)); - gst_pad_set_event_function (queue->sinkpad, + gst_pad_set_event_full_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_event)); gst_pad_set_query_function (queue->sinkpad, GST_DEBUG_FUNCPTR (gst_queue2_handle_sink_query)); @@ -464,8 +506,8 @@ gst_queue2_init (GstQueue2 * queue) queue->max_level.rate_time = DEFAULT_MAX_SIZE_TIME; queue->use_buffering = DEFAULT_USE_BUFFERING; queue->use_rate_estimate = DEFAULT_USE_RATE_ESTIMATE; - queue->low_percent = DEFAULT_LOW_PERCENT; - queue->high_percent = DEFAULT_HIGH_PERCENT; + queue->low_watermark = DEFAULT_LOW_WATERMARK * MAX_BUFFERING_LEVEL; + queue->high_watermark = DEFAULT_HIGH_WATERMARK * MAX_BUFFERING_LEVEL; gst_segment_init (&queue->sink_segment, GST_FORMAT_TIME); gst_segment_init (&queue->src_segment, GST_FORMAT_TIME); @@ -883,7 +925,8 @@ apply_buffer_list (GstQueue2 * queue, GstBufferList * buffer_list, } static inline gint -get_percent (guint64 cur_level, guint64 max_level, guint64 alt_max) +normalize_to_buffering_level (guint64 cur_level, guint64 max_level, + guint64 alt_max) { guint64 p; @@ -891,33 +934,34 @@ get_percent (guint64 cur_level, guint64 max_level, guint64 alt_max) return 0; if (alt_max > 0) - p = gst_util_uint64_scale (cur_level, 100, MIN (max_level, alt_max)); + p = gst_util_uint64_scale (cur_level, MAX_BUFFERING_LEVEL, + MIN (max_level, alt_max)); else - p = gst_util_uint64_scale (cur_level, 100, max_level); + p = gst_util_uint64_scale (cur_level, MAX_BUFFERING_LEVEL, max_level); - return MIN (p, 100); + return MIN (p, MAX_BUFFERING_LEVEL); } static gboolean -get_buffering_percent (GstQueue2 * queue, gboolean * is_buffering, - gint * percent) +get_buffering_level (GstQueue2 * queue, gboolean * is_buffering, + gint * buffering_level) { - gint perc, perc2; + gint buflevel, buflevel2; - if (queue->high_percent <= 0) { - if (percent) - *percent = 100; + if (queue->high_watermark <= 0) { + if (buffering_level) + *buffering_level = MAX_BUFFERING_LEVEL; if (is_buffering) *is_buffering = FALSE; return FALSE; } -#define GET_PERCENT(format,alt_max) \ - get_percent(queue->cur_level.format,queue->max_level.format,(alt_max)) +#define GET_BUFFER_LEVEL_FOR_QUANTITY(format,alt_max) \ + normalize_to_buffering_level (queue->cur_level.format,queue->max_level.format,(alt_max)) if (queue->is_eos) { /* on EOS we are always 100% full, we set the var here so that it we can * reuse the logic below to stop buffering */ - perc = 100; + buflevel = MAX_BUFFERING_LEVEL; GST_LOG_OBJECT (queue, "we are EOS"); } else { GST_LOG_OBJECT (queue, @@ -925,50 +969,59 @@ get_buffering_percent (GstQueue2 * queue, gboolean * is_buffering, queue->cur_level.bytes, GST_TIME_ARGS (queue->cur_level.time), queue->cur_level.buffers); - /* figure out the percent we are filled, we take the max of all formats. */ + /* figure out the buffering level we are filled, we take the max of all formats. */ if (!QUEUE_IS_USING_RING_BUFFER (queue)) { - perc = GET_PERCENT (bytes, 0); + buflevel = GET_BUFFER_LEVEL_FOR_QUANTITY (bytes, 0); } else { guint64 rb_size = queue->ring_buffer_max_size; - perc = GET_PERCENT (bytes, rb_size); + buflevel = GET_BUFFER_LEVEL_FOR_QUANTITY (bytes, rb_size); } - perc2 = GET_PERCENT (time, 0); - perc = MAX (perc, perc2); + buflevel2 = GET_BUFFER_LEVEL_FOR_QUANTITY (time, 0); + buflevel = MAX (buflevel, buflevel2); - perc2 = GET_PERCENT (buffers, 0); - perc = MAX (perc, perc2); + buflevel2 = GET_BUFFER_LEVEL_FOR_QUANTITY (buffers, 0); + buflevel = MAX (buflevel, buflevel2); /* also apply the rate estimate when we need to */ if (queue->use_rate_estimate) { - perc2 = GET_PERCENT (rate_time, 0); - perc = MAX (perc, perc2); + buflevel2 = GET_BUFFER_LEVEL_FOR_QUANTITY (rate_time, 0); + buflevel = MAX (buflevel, buflevel2); } /* Don't get to 0% unless we're really empty */ if (queue->cur_level.bytes > 0) - perc = MAX (1, perc); + buflevel = MAX (1, buflevel); } -#undef GET_PERCENT +#undef GET_BUFFER_LEVEL_FOR_QUANTITY if (is_buffering) *is_buffering = queue->is_buffering; - /* scale to high percent so that it becomes the 100% mark */ - perc = perc * 100 / queue->high_percent; - /* clip */ - if (perc > 100) - perc = 100; + if (buffering_level) + *buffering_level = buflevel; - if (percent) - *percent = perc; - - GST_DEBUG_OBJECT (queue, "buffering %d, percent %d", queue->is_buffering, - perc); + GST_DEBUG_OBJECT (queue, "buffering %d, level %d", queue->is_buffering, + buflevel); return TRUE; } +static gint +convert_to_buffering_percent (GstQueue2 * queue, gint buffering_level) +{ + int percent; + + /* scale so that if buffering_level equals the high watermark, + * the percentage is 100% */ + percent = buffering_level * 100 / queue->high_watermark; + /* clip */ + if (percent > 100) + percent = 100; + + return percent; +} + static void get_buffering_stats (GstQueue2 * queue, gint percent, GstBufferingMode * mode, gint * avg_in, gint * avg_out, gint64 * buffering_left) @@ -1004,13 +1057,12 @@ get_buffering_stats (GstQueue2 * queue, gint percent, GstBufferingMode * mode, } } -static void -gst_queue2_post_buffering (GstQueue2 * queue) +/* Called with the lock taken */ +static GstMessage * +gst_queue2_get_buffering_message (GstQueue2 * queue) { GstMessage *msg = NULL; - g_mutex_lock (&queue->buffering_post_lock); - GST_QUEUE2_MUTEX_LOCK (queue); if (queue->percent_changed) { gint percent = queue->buffering_percent; @@ -1022,6 +1074,18 @@ gst_queue2_post_buffering (GstQueue2 * queue) gst_message_set_buffering_stats (msg, queue->mode, queue->avg_in, queue->avg_out, queue->buffering_left); } + + return msg; +} + +static void +gst_queue2_post_buffering (GstQueue2 * queue) +{ + GstMessage *msg = NULL; + + g_mutex_lock (&queue->buffering_post_lock); + GST_QUEUE2_MUTEX_LOCK (queue); + msg = gst_queue2_get_buffering_message (queue); GST_QUEUE2_MUTEX_UNLOCK (queue); if (msg != NULL) @@ -1033,16 +1097,18 @@ gst_queue2_post_buffering (GstQueue2 * queue) static void update_buffering (GstQueue2 * queue) { - gint percent; + gint buffering_level, percent; /* Ensure the variables used to calculate buffering state are up-to-date. */ if (queue->current) update_cur_level (queue, queue->current); - update_in_rates (queue); + update_in_rates (queue, FALSE); - if (!get_buffering_percent (queue, NULL, &percent)) + if (!get_buffering_level (queue, NULL, &buffering_level)) return; + percent = convert_to_buffering_percent (queue, buffering_level); + if (queue->is_buffering) { /* if we were buffering see if we reached the high watermark */ if (percent >= 100) @@ -1052,7 +1118,7 @@ update_buffering (GstQueue2 * queue) } else { /* we were not buffering, check if we need to start buffering if we drop * below the low threshold */ - if (percent < queue->low_percent) { + if (buffering_level < queue->low_watermark) { queue->is_buffering = TRUE; SET_PERCENT (queue, percent); } @@ -1087,7 +1153,7 @@ reset_rate_timer (GstQueue2 * queue) #define AVG_OUT(avg,val) ((avg) * 3.0 + (val)) / 4.0 static void -update_in_rates (GstQueue2 * queue) +update_in_rates (GstQueue2 * queue, gboolean force) { gdouble elapsed, period; gdouble byte_in_rate; @@ -1102,7 +1168,7 @@ update_in_rates (GstQueue2 * queue) g_timer_elapsed (queue->in_timer, NULL); /* recalc after each interval. */ - if (queue->last_in_elapsed + RATE_INTERVAL < elapsed) { + if (force || queue->last_in_elapsed + RATE_INTERVAL < elapsed) { period = elapsed - queue->last_in_elapsed; GST_DEBUG_OBJECT (queue, @@ -1846,6 +1912,9 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer) guint64 range_data_start, range_data_end; GstQueue2Range *range_to_destroy = NULL; + if (range == queue->current) + goto next_range; + range_data_start = range->rb_offset; range_data_end = range->rb_writing_pos; @@ -2027,8 +2096,18 @@ gst_queue2_create_write (GstQueue2 * queue, GstBuffer * buffer) update_cur_level (queue, queue->current); /* update the buffering status */ - if (queue->use_buffering) + if (queue->use_buffering) { + GstMessage *msg; update_buffering (queue); + msg = gst_queue2_get_buffering_message (queue); + if (msg) { + GST_QUEUE2_MUTEX_UNLOCK (queue); + g_mutex_lock (&queue->buffering_post_lock); + gst_element_post_message (GST_ELEMENT_CAST (queue), msg); + g_mutex_unlock (&queue->buffering_post_lock); + GST_QUEUE2_MUTEX_LOCK (queue); + } + } GST_INFO_OBJECT (queue, "cur_level.bytes %u (max %" G_GUINT64_FORMAT ")", queue->cur_level.bytes, QUEUE_MAX_BYTES (queue)); @@ -2128,7 +2207,7 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, /* apply new buffer to segment stats */ apply_buffer (queue, buffer, &queue->sink_segment, size, TRUE); /* update the byterate stats */ - update_in_rates (queue); + update_in_rates (queue, FALSE); if (!QUEUE_IS_USING_QUEUE (queue)) { /* FIXME - check return value? */ @@ -2154,7 +2233,7 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, apply_buffer_list (queue, buffer_list, &queue->sink_segment, TRUE); /* update the byterate stats */ - update_in_rates (queue); + update_in_rates (queue, FALSE); if (!QUEUE_IS_USING_QUEUE (queue)) { gst_buffer_list_foreach (buffer_list, buffer_list_create_write, queue); @@ -2170,6 +2249,8 @@ gst_queue2_locked_enqueue (GstQueue2 * queue, gpointer item, * filled and we can read all data from the queue. */ GST_DEBUG_OBJECT (queue, "we have EOS"); queue->is_eos = TRUE; + /* Force updating the input bitrate */ + update_in_rates (queue, TRUE); break; case GST_EVENT_SEGMENT: apply_segment (queue, event, &queue->sink_segment, TRUE); @@ -2373,7 +2454,7 @@ no_item: } } -static gboolean +static GstFlowReturn gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { @@ -2397,14 +2478,17 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, /* unblock the loop and chain functions */ GST_QUEUE2_SIGNAL_ADD (queue); GST_QUEUE2_SIGNAL_DEL (queue); - queue->last_query = FALSE; - g_cond_signal (&queue->query_handled); GST_QUEUE2_MUTEX_UNLOCK (queue); /* make sure it pauses, this should happen since we sent * flush_start downstream. */ gst_pad_pause_task (queue->srcpad); GST_CAT_LOG_OBJECT (queue_dataflow, queue, "loop stopped"); + + GST_QUEUE2_MUTEX_LOCK (queue); + queue->last_query = FALSE; + g_cond_signal (&queue->query_handled); + GST_QUEUE2_MUTEX_UNLOCK (queue); } else { GST_QUEUE2_MUTEX_LOCK (queue); /* flush the sink pad */ @@ -2484,10 +2568,7 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, } else if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { if (queue->srcresult == GST_FLOW_NOT_LINKED || queue->srcresult < GST_FLOW_EOS) { - GST_ELEMENT_ERROR (queue, STREAM, FAILED, - (_("Internal data flow error.")), - ("streaming task paused, reason %s (%d)", - gst_flow_get_name (queue->srcresult), queue->srcresult)); + GST_ELEMENT_FLOW_ERROR (queue, queue->srcresult); } goto out_flow_error; } @@ -2504,7 +2585,9 @@ gst_queue2_handle_sink_event (GstPad * pad, GstObject * parent, } break; } - return ret; + if (ret == FALSE) + return GST_FLOW_ERROR; + return GST_FLOW_OK; /* ERRORS */ out_flushing: @@ -2512,14 +2595,14 @@ out_flushing: GST_DEBUG_OBJECT (queue, "refusing event, we are flushing"); GST_QUEUE2_MUTEX_UNLOCK (queue); gst_event_unref (event); - return FALSE; + return GST_FLOW_FLUSHING; } out_eos: { GST_DEBUG_OBJECT (queue, "refusing event, we are EOS"); GST_QUEUE2_MUTEX_UNLOCK (queue); gst_event_unref (event); - return FALSE; + return GST_FLOW_EOS; } out_flow_error: { @@ -2528,7 +2611,7 @@ out_flow_error: gst_flow_get_name (queue->srcresult)); GST_QUEUE2_MUTEX_UNLOCK (queue); gst_event_unref (event); - return FALSE; + return queue->srcresult; } } @@ -2560,7 +2643,10 @@ gst_queue2_handle_sink_query (GstPad * pad, GstObject * parent, GST_QUEUE2_ITEM_TYPE_QUERY); STATUS (queue, queue->sinkpad, "wait for QUERY"); - g_cond_wait (&queue->query_handled, &queue->qlock); + while (queue->sinkresult == GST_FLOW_OK && + queue->last_handled_query != query) + g_cond_wait (&queue->query_handled, &queue->qlock); + queue->last_handled_query = NULL; if (queue->sinkresult != GST_FLOW_OK) goto out_flushing; res = queue->last_query; @@ -2888,6 +2974,7 @@ next: GstQuery *query = GST_QUERY_CAST (data); GST_LOG_OBJECT (queue->srcpad, "Peering query %p", query); + queue->last_handled_query = query; queue->last_query = gst_pad_peer_query (queue->srcpad, query); GST_LOG_OBJECT (queue->srcpad, "Peered query"); GST_CAT_LOG_OBJECT (queue_dataflow, queue, @@ -2976,10 +3063,7 @@ out_flushing: /* let app know about us giving up if upstream is not expected to do so */ /* EOS is already taken care of elsewhere */ if (eos && (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS)) { - GST_ELEMENT_ERROR (queue, STREAM, FAILED, - (_("Internal data flow error.")), - ("streaming task paused, reason %s (%d)", - gst_flow_get_name (ret), ret)); + GST_ELEMENT_FLOW_ERROR (queue, ret); gst_pad_push_event (queue->srcpad, gst_event_new_eos ()); } return; @@ -3076,9 +3160,13 @@ gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query) switch (format) { case GST_FORMAT_BYTES: peer_pos -= queue->cur_level.bytes; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; break; case GST_FORMAT_TIME: peer_pos -= queue->cur_level.time; + if (peer_pos < 0) /* Clamp result to 0 */ + peer_pos = 0; break; default: GST_WARNING_OBJECT (queue, "dropping query in %s format, don't " @@ -3109,7 +3197,8 @@ gst_queue2_handle_src_query (GstPad * pad, GstObject * parent, GstQuery * query) GST_DEBUG_OBJECT (queue, "query buffering"); - get_buffering_percent (queue, &is_buffering, &percent); + get_buffering_level (queue, &is_buffering, &percent); + percent = convert_to_buffering_percent (queue, percent); gst_query_set_buffering_percent (query, is_buffering, percent); get_buffering_stats (queue, percent, &mode, &avg_in, &avg_out, @@ -3375,9 +3464,6 @@ gst_queue2_sink_activate_mode (GstPad * pad, GstObject * parent, queue->srcresult = GST_FLOW_FLUSHING; queue->sinkresult = GST_FLOW_FLUSHING; GST_QUEUE2_SIGNAL_DEL (queue); - /* Unblock query handler */ - queue->last_query = FALSE; - g_cond_signal (&queue->query_handled); GST_QUEUE2_MUTEX_UNLOCK (queue); /* wait until it is unblocked and clean up */ @@ -3428,6 +3514,10 @@ gst_queue2_src_activate_push (GstPad * pad, GstObject * parent, gboolean active) /* step 2, make sure streaming finishes */ result = gst_pad_stop_task (pad); + + GST_QUEUE2_MUTEX_LOCK (queue); + gst_queue2_locked_flush (queue, FALSE, FALSE); + GST_QUEUE2_MUTEX_UNLOCK (queue); } return result; @@ -3670,10 +3760,25 @@ gst_queue2_set_property (GObject * object, queue->use_rate_estimate = g_value_get_boolean (value); break; case PROP_LOW_PERCENT: - queue->low_percent = g_value_get_int (value); + queue->low_watermark = g_value_get_int (value) * BUF_LEVEL_PERCENT_FACTOR; + if (queue->is_buffering) + update_buffering (queue); break; case PROP_HIGH_PERCENT: - queue->high_percent = g_value_get_int (value); + queue->high_watermark = + g_value_get_int (value) * BUF_LEVEL_PERCENT_FACTOR; + if (queue->is_buffering) + update_buffering (queue); + break; + case PROP_LOW_WATERMARK: + queue->low_watermark = g_value_get_double (value) * MAX_BUFFERING_LEVEL; + if (queue->is_buffering) + update_buffering (queue); + break; + case PROP_HIGH_WATERMARK: + queue->high_watermark = g_value_get_double (value) * MAX_BUFFERING_LEVEL; + if (queue->is_buffering) + update_buffering (queue); break; case PROP_TEMP_TEMPLATE: gst_queue2_set_temp_template (queue, g_value_get_string (value)); @@ -3730,10 +3835,18 @@ gst_queue2_get_property (GObject * object, g_value_set_boolean (value, queue->use_rate_estimate); break; case PROP_LOW_PERCENT: - g_value_set_int (value, queue->low_percent); + g_value_set_int (value, queue->low_watermark / BUF_LEVEL_PERCENT_FACTOR); break; case PROP_HIGH_PERCENT: - g_value_set_int (value, queue->high_percent); + g_value_set_int (value, queue->high_watermark / BUF_LEVEL_PERCENT_FACTOR); + break; + case PROP_LOW_WATERMARK: + g_value_set_double (value, queue->low_watermark / + (gdouble) MAX_BUFFERING_LEVEL); + break; + case PROP_HIGH_WATERMARK: + g_value_set_double (value, queue->high_watermark / + (gdouble) MAX_BUFFERING_LEVEL); break; case PROP_TEMP_TEMPLATE: g_value_set_string (value, queue->temp_template);