*
* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
*
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
+ * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*/
-#include <sys/vfs.h>
+#include <dlog.h>
#include "mm_player_utils.h"
-
#include "mm_player_streaming.h"
-static void streaming_set_buffer_size(mm_player_streaming_t* streamer, guint buffer_size);
-static void streaming_set_buffer_percent(mm_player_streaming_t* streamer, gdouble low_percent, gdouble high_percent);
-static void streaming_set_buffer_type (mm_player_streaming_t* streamer, gboolean use_file, gchar * file_path, guint64 content_size);
-static void streaming_set_buffering_time(mm_player_streaming_t* streamer, gdouble buffering_time);
+#define ESTIMATED_BUFFER_UNIT (1 * 1024 * 1024) /* 1 MBytes */
+
+typedef struct {
+ gint byte_in_rate; // byte
+ gint byte_out_rate; // byte
+ gint time_rate; // ms
+} streaming_bitrate_info_t;
+
+typedef struct {
+ gint64 position; // ns
+ gint64 duration; // ns
+ guint64 content_size; // bytes
+} streaming_content_info_t;
+typedef struct {
+ guint buffering_bytes; // bytes
+ gint buffering_time; // ms
+ gdouble low_watermark;
+ gdouble high_watermark;
+} streaming_buffer_info_t;
+
+static void
+__streaming_update_buffer_setting(mmplayer_streaming_t *streamer,
+ GstMessage *buffering_msg,
+ guint64 content_size,
+ gint64 position,
+ gint64 duration);
-mm_player_streaming_t *
-__mm_player_streaming_create ()
+mmplayer_streaming_t *_mm_player_streaming_create(void)
{
- mm_player_streaming_t *streamer = NULL;
+ mmplayer_streaming_t *streamer = NULL;
- debug_fenter();
+ MMPLAYER_FENTER();
- streamer = (mm_player_streaming_t *) malloc (sizeof (mm_player_streaming_t));
- if (!streamer)
- {
- debug_error ("fail to create streaming player handle..\n");
+ streamer = (mmplayer_streaming_t *)g_try_malloc0(sizeof(mmplayer_streaming_t));
+ if (!streamer) {
+ LOGE("fail to create streaming player handle..");
return NULL;
}
- debug_fleave();
+ MMPLAYER_FLEAVE();
return streamer;
}
-void __mm_player_streaming_initialize (mm_player_streaming_t* streamer)
+static void __streaming_buffer_initialize(streaming_buffer_t *buffer_handle, gboolean buffer_init)
{
- debug_fenter();
+ if (buffer_init)
+ buffer_handle->buffer = NULL;
+
+ buffer_handle->buffering_bytes = DEFAULT_BUFFER_SIZE_BYTES;
+ buffer_handle->buffering_time = DEFAULT_BUFFERING_TIME;
+ buffer_handle->buffer_high_watermark = DEFAULT_BUFFER_HIGH_WATERMARK;
+ buffer_handle->buffer_low_watermark = DEFAULT_BUFFER_LOW_WATERMARK;
+ buffer_handle->is_live = FALSE;
+}
+
+void _mm_player_streaming_initialize(mmplayer_streaming_t *streamer, gboolean buffer_init)
+{
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+
+ streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT;
+
+ __streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), buffer_init);
+ __streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), buffer_init);
+
+ streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
+ streamer->buffering_req.is_pre_buffering = TRUE;
+ streamer->buffering_req.prebuffer_time = 0;
+ streamer->buffering_req.rebuffer_time = 0;
+
+ streamer->default_val.buffering_monitor = FALSE;
+ streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
- streamer->buffer = NULL;
- streamer->buffer_size = DEFAULT_BUFFER_SIZE;
- streamer->buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
- streamer->buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
streamer->buffer_avg_bitrate = 0;
streamer->buffer_max_bitrate = 0;
streamer->need_update = FALSE;
+ streamer->need_sync = FALSE;
+
+ streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
+ streamer->is_adaptive_streaming = FALSE;
- streamer->is_buffering = FALSE;
streamer->buffering_percent = -1;
- streamer->buffering_time = DEFAULT_BUFFERING_TIME;
+ streamer->ring_buffer_size = DEFAULT_RING_BUFFER_SIZE_BYTES;
+
+ MMPLAYER_FLEAVE();
+ return;
+}
+
+void _mm_player_streaming_destroy(mmplayer_streaming_t *streamer)
+{
+ MMPLAYER_FENTER();
- debug_fleave();
+ MMPLAYER_FREEIF(streamer);
+
+ MMPLAYER_FLEAVE();
return;
}
-void __mm_player_streaming_deinitialize (mm_player_streaming_t* streamer)
+void _mm_player_streaming_set_content_bitrate(
+ mmplayer_streaming_t *streamer, guint max_bitrate, guint avg_bitrate)
{
- debug_fenter();
+ gboolean is_update = FALSE;
- return_if_fail(streamer);
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer);
- streamer->buffer_size = DEFAULT_BUFFER_SIZE;
- streamer->buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
- streamer->buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
- streamer->buffer_avg_bitrate = 0;
- streamer->buffer_max_bitrate = 0;
- streamer->need_update = FALSE;
+ if (max_bitrate > 0 && max_bitrate != streamer->buffer_max_bitrate) {
+ is_update = TRUE;
+ streamer->buffer_max_bitrate = max_bitrate;
+ }
- streamer->is_buffering = FALSE;
- streamer->buffering_percent = -1;
- streamer->buffering_time = DEFAULT_BUFFERING_TIME;
+ if (avg_bitrate > 0 && avg_bitrate != streamer->buffer_avg_bitrate) {
+ is_update = TRUE;
+ streamer->buffer_avg_bitrate = avg_bitrate;
+ }
- debug_fleave();
+ if (is_update) {
+ if (streamer->buffering_req.is_pre_buffering) {
+ /* have to recalc queue2 size value after getting bitrate information */
+ if (IS_MUXED_BUFFERING_MODE(streamer))
+ __streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
+ } else {
+ streamer->need_update = TRUE;
+ }
+ }
+ MMPLAYER_FLEAVE();
return;
}
+static void __streaming_calc_watermark(mmplayer_streaming_t *streamer,
+ guint expected_play_bytes, gint expected_play_time, gdouble *low_wm, gdouble *high_wm)
+{
+#define PORTION_OF_HIGH_WM 1.1 /* need to compensate about low level */
+#define PORTION_OF_LOW_WM 0.1
+
+ streaming_buffer_t *buffer_handle = NULL;
+ gdouble wm_byte = 0.0, wm_time = 0.0;
+ gint current_buffering_size = 0;
+
+ MMPLAYER_RETURN_IF_FAIL(streamer && low_wm && high_wm);
+
+ buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
+
+ LOGD("type %d, bytes %d / %d, time %d / %d", streamer->streaming_buffer_type,
+ expected_play_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle),
+ expected_play_time, GET_CURRENT_BUFFERING_TIME(buffer_handle));
+
+ if (expected_play_bytes > 0) {
+ /* and buffer size will be increased */
+ current_buffering_size = MAX(GET_CURRENT_BUFFERING_BYTE(buffer_handle), (expected_play_bytes * PORTION_OF_HIGH_WM));
+ GET_WATERMARK((expected_play_bytes * PORTION_OF_HIGH_WM), current_buffering_size, buffer_handle->buffer_high_watermark, wm_byte);
+ wm_byte = MIN(wm_byte, DEFAULT_BUFFER_HIGH_WATERMARK);
+ }
+
+ if (IS_MUXED_BUFFERING_MODE(streamer)) {
+ *high_wm = wm_byte;
+ *low_wm = wm_byte * PORTION_OF_LOW_WM;
+
+ /* If user set the very low level buffering time,
+ buffer underrun could be occurred even if the min range is considered. */
+ GET_VALID_VALUE((*low_wm), LOW_WATERMARK_MIN_BYTE_LEVEL, DEFAULT_BUFFER_LOW_WATERMARK);
+ } else {
+ gdouble prev_low_wm_time = 0.0;
+ gdouble low_wm_time = 0.0, high_wm_time = 0.0;
+
+ expected_play_time = MAX(expected_play_time, LOW_WATERMARK_MIN_TIME_VALUE);
+ low_wm_time = expected_play_time * PORTION_OF_LOW_WM;
+ high_wm_time = expected_play_time * PORTION_OF_HIGH_WM;
+
+ /* 1. Get min watermark value */
+ /* 1-1. get max buffer size, expected time could be greater than current one */
+ LOGE("low wm time : %.3f ms", low_wm_time);
+ current_buffering_size = MAX(GET_CURRENT_BUFFERING_TIME(buffer_handle), high_wm_time);
+
+ /* 1-2. get previous low time value to keep the minimum watermark */
+ prev_low_wm_time = GET_CURRENT_BUFFERING_TIME(buffer_handle) * buffer_handle->buffer_low_watermark;
+ GET_VALID_VALUE(low_wm_time, LOW_WATERMARK_MIN_TIME_VALUE, prev_low_wm_time);
+
+ /* 1-3. get min watermark value based on the max buffer size */
+ GET_WATERMARK(low_wm_time, current_buffering_size, buffer_handle->buffer_low_watermark, *low_wm);
+ *low_wm = MIN(*low_wm, DEFAULT_BUFFER_LOW_WATERMARK);
+
+ /* 2. Get high watermark value.
+ If the expected time is greater than current one, the buffer size will be increased after */
+ GET_WATERMARK(high_wm_time, current_buffering_size, buffer_handle->buffer_high_watermark, wm_time);
+ *high_wm = MAX(wm_byte, wm_time);
+ *high_wm = MIN(*high_wm, DEFAULT_BUFFER_HIGH_WATERMARK);
+ }
+
+ if (*low_wm >= *high_wm) {
+ LOGW("invalid high wm value %1.3f", *high_wm);
+ *high_wm = DEFAULT_BUFFER_HIGH_WATERMARK;
+ }
+
+ LOGD("new watermark value [%f ~ %f]", *low_wm, *high_wm);
+}
-void __mm_player_streaming_destroy (mm_player_streaming_t* streamer)
+static void __streaming_set_buffer_watermark(mmplayer_streaming_t *streamer,
+ buffer_type_e type, gdouble low_watermark, gdouble high_watermark)
{
- debug_fenter();
+ streaming_buffer_t *buffer_handle = NULL;
+ gchar *factory_name = NULL;
- if(streamer)
- {
- free (streamer);
- streamer = NULL;
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
+
+ buffer_handle = &(streamer->buffer_handle[type]);
+ if (!(buffer_handle && buffer_handle->buffer)) {
+ LOGE("buffer_handle->buffer is NULL!");
+ return;
+ }
+
+ factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
+
+ if (!factory_name) {
+ LOGE("Fail to get factory name!");
+ return;
}
- debug_fleave();
+ if (high_watermark <= MIN_BUFFER_WATERMARK || high_watermark >= MAX_BUFFER_WATERMARK)
+ high_watermark = DEFAULT_BUFFER_HIGH_WATERMARK;
+
+ if (low_watermark <= MIN_BUFFER_WATERMARK || low_watermark >= MAX_BUFFER_WATERMARK)
+ low_watermark = DEFAULT_BUFFER_LOW_WATERMARK;
+
+ /* if use-buffering is disabled, this settings do not have any meaning. */
+ if ((high_watermark == DEFAULT_BUFFER_HIGH_WATERMARK) ||
+ (buffer_handle->buffer_high_watermark != high_watermark) ||
+ (buffer_handle->buffer_low_watermark != low_watermark))
+ g_object_set(G_OBJECT(buffer_handle->buffer), "high-watermark", high_watermark,
+ "low-watermark", low_watermark, NULL);
+
+ LOGD("update elem:%s, wm:%1.3f ~ %1.3f", GST_ELEMENT_NAME(buffer_handle->buffer), low_watermark, high_watermark);
+
+ buffer_handle->buffer_high_watermark = high_watermark;
+ buffer_handle->buffer_low_watermark = low_watermark;
+ MMPLAYER_FLEAVE();
return;
}
-
-void __mm_player_streaming_set_buffer(mm_player_streaming_t* streamer, GstElement * buffer,
- gboolean use_buffering, guint buffer_size, gdouble low_percent, gdouble high_percent, gdouble buffering_time,
- gboolean use_file, gchar * file_path, guint64 content_size)
+static void __streaming_set_queue2_queue_type(mmplayer_streaming_t *streamer, muxed_buffer_type_e type)
{
- debug_fenter();
-
- return_if_fail(streamer);
+ streaming_buffer_t *buffer_handle = NULL;
+ guint64 buffer_size = 0; /* bytes */
- if (buffer)
- {
- streamer->buffer = buffer;
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer);
- debug_log("buffer element is %s.", GST_ELEMENT_NAME(buffer));
+ buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_MUXED]);
- g_object_set ( G_OBJECT (streamer->buffer), "use-buffering", use_buffering, NULL );
+ if (type == MUXED_BUFFER_TYPE_MEM_QUEUE) { /* ts */
+ LOGD("use memory queue for buffering. streaming is played on push-based. \n"
+ "buffering position would not be updated.\n"
+ "buffered data would be flushed after played.\n"
+ "seeking and getting duration could be failed due to file format.");
+ return;
}
- streaming_set_buffer_size(streamer, buffer_size);
- streaming_set_buffer_percent(streamer, low_percent, high_percent);
- streaming_set_buffer_type (streamer, use_file, file_path, content_size);
- streaming_set_buffering_time(streamer, buffering_time);
+ /* @see ini->http_ring_buffer_size */
+ buffer_size = (guint64)((streamer->ring_buffer_size > 0) ? (streamer->ring_buffer_size) : DEFAULT_RING_BUFFER_SIZE_BYTES);
- debug_fleave();
+ LOGW("ring buffer size: %"G_GUINT64_FORMAT, buffer_size);
+ g_object_set(G_OBJECT(buffer_handle->buffer), "ring-buffer-max-size", buffer_size, NULL);
+ MMPLAYER_FLEAVE();
return;
}
+static void __streaming_set_buffer_size(mmplayer_streaming_t *streamer,
+ buffer_type_e type, guint buffering_bytes, gint buffering_time)
+{
+ streaming_buffer_t *buffer_handle = NULL;
+
+ MMPLAYER_FENTER();
+
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(buffering_bytes > 0);
+ MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
+
+ buffer_handle = &(streamer->buffer_handle[type]);
+
+ if (buffer_handle && buffer_handle->buffer) {
+ if (g_strrstr(GST_ELEMENT_NAME(buffer_handle->buffer), "multiqueue")) {
+ if (buffering_time <= 0)
+ buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
+
+ g_object_set(G_OBJECT(buffer_handle->buffer),
+ "max-size-bytes", MAX_BUFFER_SIZE_BYTES, /* mq size is fixed, control it with high/low watermark value*/
+ "max-size-time", (guint64)(buffering_time * GST_MSECOND),
+ "max-size-buffers", 0, /* disable */
+ "use-interleave", FALSE, NULL);
+
+ GET_CURRENT_BUFFERING_TIME(buffer_handle) = buffering_time;
+ GET_CURRENT_BUFFERING_BYTE(buffer_handle) = MAX_BUFFER_SIZE_BYTES;
+
+ LOGD("byte: %d, max-size-time : %d ms", buffering_bytes, buffering_time);
+ } else {
+ /* queue2 */
+ if (buffer_handle->is_live)
+ g_object_set(G_OBJECT(buffer_handle->buffer),
+ "max-size-bytes", buffering_bytes,
+ "max-size-time", (guint64)(buffering_time * GST_MSECOND),
+ "max-size-buffers", 0,
+ "use-rate-estimate", TRUE, NULL);
+ else
+ g_object_set(G_OBJECT(buffer_handle->buffer),
+ "max-size-bytes", buffering_bytes,
+ "max-size-time", (guint64)0,
+ "max-size-buffers", 0,
+ "use-rate-estimate", FALSE, NULL);
+
+ GET_CURRENT_BUFFERING_BYTE(buffer_handle) = buffering_bytes;
+ GET_CURRENT_BUFFERING_TIME(buffer_handle) = buffering_time;
+
+ LOGD("max-size-bytes : %d, time : %d", buffering_bytes, buffering_time);
+ }
+ }
+
+ MMPLAYER_FLEAVE();
+ return;
+}
-void __mm_player_streaming_set_content_bitrate(mm_player_streaming_t* streamer, guint max_bitrate, guint avg_bitrate)
+void _mm_player_streaming_set_queue2(mmplayer_streaming_t *streamer, GstElement *buffer,
+ gboolean use_buffering, muxed_buffer_type_e type, guint64 content_size)
{
- debug_fenter();
+ guint queue_size_bytes = 0;
+ guint queue_size_time = 0;
- return_if_fail(streamer);
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer && buffer);
- /* Note : Update buffering criterion bytes
- * 1. maximum bitrate is considered first.
- * 2. average bitrage * 3 is next.
- * 3. if there are no updated bitrate, use default buffering limit.
- */
- if (max_bitrate > 0 && streamer->buffer_max_bitrate != max_bitrate)
- {
- debug_log("set maximum bitrate(%dbps).\n", max_bitrate);
- streamer->buffer_max_bitrate = max_bitrate;
+ LOGD("use buffering %d, type %d, content_size %"G_GUINT64_FORMAT, use_buffering, type, content_size);
- streamer->need_update = TRUE;
- }
+ streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer = buffer;
- if (avg_bitrate > 0 && streamer->buffer_avg_bitrate != avg_bitrate)
- {
- debug_log("set averate bitrate(%dbps).\n", avg_bitrate);
- streamer->buffer_avg_bitrate = avg_bitrate;
+ if (use_buffering) { /* audio only content use queue2 for buffering */
+ streamer->streaming_buffer_type = BUFFER_TYPE_MUXED;
- streamer->need_update = TRUE;
+ if (streamer->buffering_req.prebuffer_time <= MIN_BUFFERING_TIME)
+ streamer->buffering_req.prebuffer_time = DEFAULT_PREBUFFERING_TIME;
+
+ if (content_size == 0) {
+ LOGD("live streaming without mq");
+ streamer->buffer_handle[BUFFER_TYPE_MUXED].is_live = TRUE;
+ }
+
+ /* keep estimated value till the pipeline share the bitrate information */
+ queue_size_bytes = (guint)(streamer->buffering_req.prebuffer_time / 1000) * ESTIMATED_BUFFER_UNIT; /* temp size */
+ queue_size_bytes = MAX(queue_size_bytes, DEFAULT_BUFFER_SIZE_BYTES);
+ queue_size_time = streamer->buffering_req.prebuffer_time;
+ } else {
+ if (type >= MUXED_BUFFER_TYPE_MAX) {
+ LOGE("invalid queue type");
+ return;
+ }
+
+ /* set the simple queue size */
+ queue_size_bytes = DEFAULT_BUFFER_SIZE_BYTES;
+ __streaming_set_queue2_queue_type(streamer, type);
+ queue_size_time = 0; /* set in case of use-buffering */
}
- debug_fleave();
+ g_object_set(G_OBJECT(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL);
+ LOGD("buffer time: %d ms, buffer bytes: %d", queue_size_time, queue_size_bytes);
+ __streaming_set_buffer_size(streamer, BUFFER_TYPE_MUXED, queue_size_bytes, queue_size_time);
+ __streaming_set_buffer_watermark(streamer, BUFFER_TYPE_MUXED, DEFAULT_BUFFER_LOW_WATERMARK, DEFAULT_BUFFER_HIGH_WATERMARK);
+
+ MMPLAYER_FLEAVE();
return;
}
-static void
-streaming_set_buffer_size(mm_player_streaming_t* streamer, guint buffer_size)
+void _mm_player_streaming_sync_property(mmplayer_streaming_t *streamer, GstElement *decodebin)
{
- debug_fenter();
+ streaming_buffer_t *buffer_handle = NULL;
- return_if_fail(streamer);
- return_if_fail(buffer_size>0);
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer && decodebin);
- debug_log("set buffer size to %d.", buffer_size);
+ if ((!streamer->need_sync) || (streamer->streaming_buffer_type != BUFFER_TYPE_DEMUXED)) {
+ streamer->need_sync = FALSE;
+ return;
+ }
- streamer->buffer_size = buffer_size;
+ buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
- if (streamer->buffer)
- g_object_set (G_OBJECT(streamer->buffer), "max-size-bytes", buffer_size, NULL);
+ LOGD("sync : %1.3f ~ %1.3f", buffer_handle->buffer_low_watermark, buffer_handle->buffer_high_watermark);
+ g_object_set(G_OBJECT(decodebin),
+ "max-size-bytes", GET_CURRENT_BUFFERING_BYTE(buffer_handle),
+ "max-size-time", (guint64)(GET_CURRENT_BUFFERING_TIME(buffer_handle) * GST_MSECOND),
+ "high-percent", (gint)(buffer_handle->buffer_high_watermark * 100),
+ "low-percent", (gint)(buffer_handle->buffer_low_watermark * 100), NULL);
- debug_fleave();
+ streamer->need_sync = FALSE;
+}
+
+void _mm_player_streaming_set_multiqueue(mmplayer_streaming_t *streamer, GstElement *buffer)
+{
+ streaming_buffer_t *buffer_handle = NULL;
+ gdouble high_wm = 0.0, low_wm = 0.0;
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer && buffer);
+
+ buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
+ buffer_handle->buffer = buffer;
+
+ LOGD("pre_buffering: %d ms", streamer->buffering_req.prebuffer_time);
+
+ streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
+ g_object_set(G_OBJECT(buffer_handle->buffer), "use-buffering", TRUE, NULL);
+
+ if (streamer->buffering_req.prebuffer_time <= MIN_BUFFERING_TIME)
+ streamer->buffering_req.prebuffer_time = DEFAULT_PREBUFFERING_TIME;
+
+ /* initial setting */
+ __streaming_set_buffer_size(streamer, BUFFER_TYPE_DEMUXED, MAX_BUFFER_SIZE_BYTES, MAX_BUFFER_SIZE_TIME);
+
+ __streaming_calc_watermark(streamer, 0, streamer->buffering_req.prebuffer_time, &low_wm, &high_wm);
+ __streaming_set_buffer_watermark(streamer, BUFFER_TYPE_DEMUXED, low_wm, high_wm);
+
+ streamer->need_sync = TRUE;
+
+ MMPLAYER_FLEAVE();
return;
}
-static void
-streaming_set_buffer_percent(mm_player_streaming_t* streamer, gdouble low_percent, gdouble high_percent)
+static void __streaming_get_current_bitrate_info(mmplayer_streaming_t *streamer,
+ GstMessage *buffering_msg, streaming_content_info_t content_info, streaming_bitrate_info_t *bitrate_info)
{
- gdouble buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
- gdouble buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
+ GstQuery *query = NULL;
+ GstBufferingMode mode = GST_BUFFERING_STREAM;
+ gint in_rate = 0;
+ gint out_rate = 0;
+ gint64 buffering_left = -1;
- debug_fenter();
+ guint estimated_content_bitrate = 0;
- return_if_fail(streamer);
+ gint buffer_buffering_time = DEFAULT_BUFFERING_TIME;
- if (low_percent <= MIN_BUFFER_PERCENT || low_percent >= MAX_BUFFER_PERCENT)
- {
- debug_warning("buffer low percent is out of range. use defaut value.");
- buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
- }
- else
- {
- buffer_low_percent = low_percent;
- }
+ MMPLAYER_FENTER();
- if (high_percent <= MIN_BUFFER_PERCENT || high_percent >= MAX_BUFFER_PERCENT)
- {
- debug_warning("buffer high percent is out of range. use defaut value.");
- buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
- }
- else
- {
- buffer_high_percent = high_percent;
- }
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(bitrate_info);
- if (buffer_high_percent <= buffer_low_percent)
- buffer_high_percent = buffer_low_percent + 1.0;
+ if ((buffering_msg == NULL) ||
+ ((streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer != NULL) &&
+ (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer != NULL) &&
+ (buffering_msg->src == (GstObject *)streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer))) {
+ query = gst_query_new_buffering(GST_FORMAT_PERCENT);
+
+ if (gst_element_query((streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), query))
+ gst_query_parse_buffering_stats(query, &mode, &in_rate, &out_rate, &buffering_left);
+ gst_query_unref(query);
+ } else {
+ gst_message_parse_buffering_stats(buffering_msg, &mode, &in_rate, &out_rate, &buffering_left);
+ }
- debug_log("set buffer percent to %2.3f ~ %2.3f.", streamer->buffer_low_percent, streamer->buffer_high_percent);
+ LOGD("Streaming Info : in %d, out %d, left %"G_GINT64_FORMAT, in_rate, out_rate, buffering_left);
- if (streamer->buffer)
- {
- if ( streamer->buffer_low_percent != buffer_low_percent )
- g_object_set (G_OBJECT(streamer->buffer), "low-percent", streamer->buffer_low_percent, NULL);
+ if ((content_info.content_size > 0) && (content_info.duration > 0) && ((content_info.duration / GST_SECOND) > 0))
+ estimated_content_bitrate = GET_BIT_FROM_BYTE((guint)(content_info.content_size / (content_info.duration / GST_SECOND)));
- if ( streamer->buffer_high_percent != buffer_high_percent )
- g_object_set (G_OBJECT(streamer->buffer), "high-percent", streamer->buffer_high_percent, NULL);
+ if (streamer->buffer_max_bitrate > 0) {
+ streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, streamer->buffer_avg_bitrate);
+ streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, estimated_content_bitrate);
}
- streamer->buffer_low_percent = buffer_low_percent;
- streamer->buffer_high_percent = buffer_high_percent;
+ if (streamer->buffer_avg_bitrate > 0)
+ out_rate = GET_BYTE_FROM_BIT(MAX(streamer->buffer_avg_bitrate, estimated_content_bitrate));
+ else if (estimated_content_bitrate > 0)
+ out_rate = GET_BYTE_FROM_BIT(estimated_content_bitrate);
+ else if (streamer->buffer_max_bitrate > 0)
+ out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate/3);
+ else
+ LOGW("There is no content information");
- debug_fleave();
+ LOGD("byte_out_rate %d", out_rate);
- return;
+ if ((in_rate > 0) && (out_rate > 0))
+ buffer_buffering_time = (gint)(out_rate / in_rate) * 1000;
+ else if ((in_rate <= 0) && (out_rate > 0))
+ buffer_buffering_time = MAX_BUFFERING_TIME;
+ else
+ buffer_buffering_time = DEFAULT_BUFFERING_TIME;
+
+ (*bitrate_info).byte_in_rate = in_rate;
+ (*bitrate_info).byte_out_rate = out_rate;
+ (*bitrate_info).time_rate = buffer_buffering_time;
}
-static void
-streaming_set_buffering_time(mm_player_streaming_t* streamer, gdouble buffering_time)
+static void __streaming_handle_fixed_buffering_mode(mmplayer_streaming_t *streamer,
+ gint byte_out_rate, gint expected_play_time, streaming_buffer_info_t *buffer_info)
{
- gdouble buffer_buffering_time = DEFAULT_BUFFERING_TIME;
+ streaming_buffer_t *buffer_handle = NULL;
- debug_fenter();
+ guint expected_play_bytes = 0;
+ gdouble high_wm = 0.0, low_wm = 0.0;
- return_if_fail(streamer);
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(buffer_info);
- if (buffering_time < MIN_BUFFERING_TIME)
- buffer_buffering_time = MIN_BUFFERING_TIME;
- else if (buffering_time > MAX_BUFFERING_TIME)
- buffer_buffering_time = MAX_BUFFERING_TIME;
- else
- buffer_buffering_time = buffering_time;
+ buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
- if (streamer->buffering_time != buffer_buffering_time)
- {
- debug_log("set buffer buffering time from %2.1f to %2.1f.", streamer->buffering_time, buffer_buffering_time);
+ LOGD("buffering time: %d ms, out rate: %d", expected_play_time, byte_out_rate);
- streamer->buffering_time = buffer_buffering_time;
+ if (byte_out_rate > 0) {
+ guint max_size_byte = GET_MAX_BUFFER_SIZE_BYTES(streamer->streaming_buffer_type);
+ expected_play_bytes = (guint)GET_NEW_BUFFERING_BYTE((gdouble)(byte_out_rate * expected_play_time) / 1000, max_size_byte);
+ } else {
+ LOGW("content bitrate is not updated yet.");
+ expected_play_bytes = GET_CURRENT_BUFFERING_BYTE(buffer_handle);
}
- debug_fleave();
+ __streaming_calc_watermark(streamer, expected_play_bytes, expected_play_time, &low_wm, &high_wm);
- return;
+ (*buffer_info).buffering_bytes = expected_play_bytes;
+ (*buffer_info).buffering_time = expected_play_time;
+ (*buffer_info).high_watermark = high_wm;
+ (*buffer_info).low_watermark = low_wm;
}
-static void
-streaming_set_buffer_type (mm_player_streaming_t* streamer, gboolean use_file, gchar * file_path, guint64 content_size)
+static void __streaming_handle_adaptive_buffering_mode(mmplayer_streaming_t *streamer,
+ streaming_content_info_t content_info, streaming_bitrate_info_t bitrate_info,
+ streaming_buffer_info_t *buffer_info, gint expected_play_time)
{
- guint64 storage_available_size = 0L; //bytes
- guint64 file_buffer_size = 0L; //bytes
- gchar file_buffer_name[MAX_FILE_BUFFER_NAME_LEN] = {0};
- struct statfs buf = {0};
+ gint buffering_bytes = 0;
+ gint adj_buffering_bytes = 0;
+ gint buffer_buffering_time = 0;
+ gdouble high_wm = 0.0, low_wm = 0.0;
+ gdouble portion = 0.0;
+ gint default_buffering_time = 0;
+
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(buffer_info);
+
+ LOGD("monitor %d, pos %"G_GINT64_FORMAT", dur %"G_GINT64_FORMAT", size %"G_GUINT64_FORMAT", in/out:%d/%d, time_rate:%d, need:%d ms",
+ streamer->default_val.buffering_monitor, content_info.position, content_info.duration, content_info.content_size,
+ bitrate_info.byte_in_rate, bitrate_info.byte_out_rate, bitrate_info.time_rate, expected_play_time);
+
+ if ((content_info.duration <= 0) ||
+ (content_info.content_size <= 0)) {
+ LOGW("keep previous setting.");
+ return;
+ }
+
+ if (bitrate_info.byte_out_rate <= 0) {
+ LOGW("keep previous setting.");
+ return;
+ }
- debug_fenter();
+ if (bitrate_info.byte_in_rate < bitrate_info.byte_out_rate) {
+ guint max_size_byte = GET_MAX_BUFFER_SIZE_BYTES(streamer->streaming_buffer_type);
+ portion = (double)(expected_play_time * GST_MSECOND) / (double)content_info.duration;
+ buffering_bytes = GET_NEW_BUFFERING_BYTE(
+ (((double)content_info.content_size * portion) *
+ (1 - (double)bitrate_info.byte_in_rate / (double)bitrate_info.byte_out_rate)), max_size_byte);
+ } else {
+ /* buffering_bytes will be set as streamer->default_val.buffering_time *
+ * receiving rate is bigger than avg content bitrate
+ * so there is no reason to buffering. if the buffering msg is posted
+ * in-rate or contents bitrate has wrong value. */
+ LOGW("don't need to do buffering.");
+ }
- return_if_fail(streamer && streamer->buffer);
+ if (buffering_bytes > 0)
+ buffer_buffering_time = (gint)(buffering_bytes / bitrate_info.byte_out_rate) * 1000;
- if (!use_file)
- {
- debug_log("use memory for buffering. streaming is played on push-based. \n"
- "buffering position would not be updated.\n"
- "buffered data would be flushed after played.\n"
- "seeking and getting duration could be failed due to file format.");
- return;
+ if (content_info.position <= 0) {
+ /* if the buffer is filled under 50%, MSL use the original default buffering time.
+ if not, MSL use just 2 sec as a default buffering time. (to reduce initial buffering time) */
+ default_buffering_time = streamer->default_val.buffering_time - ((gdouble)streamer->buffering_percent / 50) * 1000;
+ } else {
+ default_buffering_time = streamer->default_val.buffering_time;
}
- debug_log("use file for buffering. streaming is played on pull-based. \n");
+ if (buffer_buffering_time < default_buffering_time) {
+ guint max_size_byte = GET_MAX_BUFFER_SIZE_BYTES(streamer->streaming_buffer_type);
- if (!file_path || strlen(file_path) <= 0)
- file_path = g_strdup(DEFAULT_FILE_BUFFER_PATH);
+ LOGD("adjusted time: %d -> %d ms", buffer_buffering_time, default_buffering_time);
+ LOGD("adjusted bytes : %d or %d", buffering_bytes,
+ (gint)(bitrate_info.byte_out_rate * buffer_buffering_time / 1000));
- sprintf( file_buffer_name, "%s/XXXXXX", file_path );
- debug_log("the buffering file name is %s.\n", file_buffer_name);
+ /* start monitoring the abnormal state */
+ if (content_info.position > 0)
+ streamer->default_val.buffering_monitor = TRUE;
- if (statfs((const char *)file_path, &buf) < 0)
- {
- debug_warning ("fail to get availabe storage capacity. just use file buffer.\n");
- file_buffer_size = 0L;
+ buffer_buffering_time = default_buffering_time;
+ adj_buffering_bytes = GET_NEW_BUFFERING_BYTE(
+ (bitrate_info.byte_out_rate * (gint)ceil((gdouble)buffer_buffering_time / 1000)), max_size_byte);
+ buffering_bytes = MAX(buffering_bytes, adj_buffering_bytes);
}
- else
- {
- storage_available_size = (guint64)buf.f_bavail * (guint64)buf.f_bsize; //bytes
- debug_log ("the number of available blocks : %"G_GUINT64_FORMAT", the block size is %"G_GUINT64_FORMAT".\n",
- (guint64)buf.f_bavail, (guint64)buf.f_bsize);
- debug_log ("calculated availabe storage size is %"G_GUINT64_FORMAT" Bytes.\n", storage_available_size);
+ __streaming_calc_watermark(streamer, buffering_bytes, buffer_buffering_time, &low_wm, &high_wm);
+
+ (*buffer_info).buffering_bytes = buffering_bytes;
+ (*buffer_info).buffering_time = buffer_buffering_time;
+ (*buffer_info).high_watermark = high_wm;
+ (*buffer_info).low_watermark = low_wm;
+}
- if (content_size <= 0 || content_size >= storage_available_size)
- file_buffer_size = storage_available_size;
+static void __streaming_update_buffer_setting(mmplayer_streaming_t *streamer,
+ GstMessage *buffering_msg, guint64 content_size, gint64 position, gint64 duration)
+{
+ streaming_buffer_t *buffer_handle = NULL;
+ mmplayer_buffering_mode_e buffering_mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
+ gint expected_play_time = DEFAULT_REBUFFERING_TIME;
+
+ streaming_buffer_info_t buffer_info = {0,};
+ streaming_content_info_t content_info = {0,};
+ streaming_bitrate_info_t bitrate_info = {0,};
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+
+ buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
+
+ if (streamer->buffering_req.is_pre_buffering == TRUE) {
+ buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
+ expected_play_time = streamer->buffering_req.prebuffer_time;
+ } else {
+ if (content_size == 0 || duration == 0) /* can not support adaptive mode */
+ buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
else
- file_buffer_size = 0L;
+ buffering_mode = streamer->buffering_req.mode;
+
+ if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED) {
+ if (streamer->buffering_req.rebuffer_time > 0)
+ expected_play_time = streamer->buffering_req.rebuffer_time;
+ else
+ expected_play_time = DEFAULT_LIVE_REBUFFER_TIME;
+ }
}
- if (file_buffer_size>0)
- debug_log("use file ring buffer for buffering.");
+ LOGD("buffering mode: %d, time: %d", buffering_mode, expected_play_time);
- g_object_set (G_OBJECT(streamer->buffer), "temp-template", file_buffer_name, NULL);
- g_object_set (G_OBJECT(streamer->buffer), "file-buffer-max-size", file_buffer_size, NULL);
+ content_info.position = position;
+ content_info.duration = duration;
+ content_info.content_size = content_size;
- debug_fleave();
+ __streaming_get_current_bitrate_info(streamer, buffering_msg, content_info, &bitrate_info);
- return;
+ LOGD("in_r:%d, out_r:%d", bitrate_info.byte_in_rate, bitrate_info.byte_out_rate);
+
+ if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED) {
+ __streaming_handle_fixed_buffering_mode(streamer, bitrate_info.byte_out_rate, expected_play_time, &buffer_info);
+ } else {
+ __streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, expected_play_time);
+
+ /* even if new byte size is smaller than the previous one, time need to be updated. */
+ if (IS_MUXED_BUFFERING_MODE(streamer))
+ GET_CURRENT_BUFFERING_TIME(buffer_handle) = buffer_info.buffering_time;
+ }
+
+ LOGD("adj buffer(%d) %d->%d bytes/%d->%d ms",
+ streamer->streaming_buffer_type,
+ GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_info.buffering_bytes,
+ GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_info.buffering_time);
+
+ /* queue2 : bytes, multiqueue : time */
+ if (((GET_CURRENT_BUFFERING_BYTE(buffer_handle) < buffer_info.buffering_bytes) && IS_MUXED_BUFFERING_MODE(streamer)) ||
+ ((GET_CURRENT_BUFFERING_TIME(buffer_handle) < buffer_info.buffering_time) && IS_DEMUXED_BUFFERING_MODE(streamer))) {
+ if (duration > 0 && position > 0) {
+ gint buffering_time_limit = (gint)(duration - position) / GST_MSECOND;
+
+ if (buffer_info.buffering_time > buffering_time_limit)
+ buffer_info.buffering_time = buffering_time_limit;
+ }
+ __streaming_set_buffer_size(streamer, streamer->streaming_buffer_type, buffer_info.buffering_bytes, buffer_info.buffering_time);
+ }
+
+ __streaming_set_buffer_watermark(streamer, streamer->streaming_buffer_type, buffer_info.low_watermark, buffer_info.high_watermark);
+
+ LOGD("buffer setting: size %d, time %d, watermark %f", GET_CURRENT_BUFFERING_BYTE(buffer_handle),
+ GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_watermark);
+
+ streamer->need_sync = TRUE;
}
-#define GET_BYTE_FROM_BIT(bit) (bit/8)
-void __mm_player_streaming_buffering(mm_player_streaming_t* streamer, GstMessage *buffering_msg)
+static void __streaming_adjust_min_threshold(mmplayer_streaming_t *streamer, gint64 position)
{
- GstBufferingMode mode = GST_BUFFERING_STREAM;
- gint byte_in_rate = 0;
- gint byte_out_rate = 0;
- gint64 buffering_left = -1;
- gdouble buffering_time = DEFAULT_BUFFERING_TIME;
- gdouble low_percent = 0.0;
- gdouble high_percent = 0.0;
- guint high_percent_byte = 0;
- gint buffer_percent = 0;
- guint buffer_criteria = 0;
+#define DEFAULT_TIME_PAD 1000 /* ms */
+ gint playing_time = 0;
- return_if_fail ( streamer );
- return_if_fail ( buffering_msg );
- return_if_fail ( GST_IS_MESSAGE ( buffering_msg ) );
- return_if_fail ( GST_MESSAGE_TYPE ( buffering_msg ) == GST_MESSAGE_BUFFERING );
+ MMPLAYER_FENTER();
- /* update when buffering has started. */
- if ( !streamer->is_buffering )
- {
- debug_log ( "buffering has started.\n" );
+ MMPLAYER_RETURN_IF_FAIL(streamer);
- streamer->is_buffering = TRUE;
- streamer->buffering_percent = -1;
- streamer->need_update = TRUE;
- }
+ playing_time = (gint)((position - streamer->default_val.prev_pos) / GST_MSECOND);
- /* update buffer percent */
- gst_message_parse_buffering ( buffering_msg, &buffer_percent );
+ LOGD("buffering monitor = %s", (streamer->default_val.buffering_monitor) ? "ON" : "OFF");
+ LOGD("playing_time (%d ms) = %"G_GINT64_FORMAT" - %"G_GINT64_FORMAT, playing_time, position, streamer->default_val.prev_pos);
+ LOGD("default time : %d, prev buffering t : %d",
+ streamer->default_val.buffering_time, streamer->buffer_handle[streamer->streaming_buffer_type].buffering_time);
- if ( streamer->buffering_percent < buffer_percent )
- {
- debug_log ( "buffering %d%%....\n", buffer_percent );
- streamer->buffering_percent = buffer_percent;
- }
+ if ((streamer->default_val.buffering_monitor) && (playing_time <= streamer->default_val.buffering_time)) {
+ gint time_gap = 0;
+ time_gap = streamer->default_val.buffering_time - DEFAULT_BUFFERING_TIME;
+ if (time_gap <= 0)
+ time_gap = DEFAULT_TIME_PAD;
- if ( streamer->buffering_percent == MAX_BUFFER_PERCENT )
- {
- debug_log ( "buffering had done.\n" );
- streamer->is_buffering = FALSE;
+ streamer->default_val.buffering_time += time_gap * 2;
+ streamer->default_val.buffering_time = MIN(streamer->default_val.buffering_time, MAX_BUFFERING_TIME);
+ } else {
+ streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
}
- if (!streamer->need_update)
- {
- debug_log ( "don't need to update buffering stats during buffering.\n" );
- return;
- }
+ LOGD("new default min value %d", streamer->default_val.buffering_time);
- /* Note : Parse the buffering message to get the in/out throughput.
- * avg_in is the network throughput and avg_out is the consumed throughtput by the linkded element.
- */
- gst_message_parse_buffering_stats ( buffering_msg, &mode, &byte_in_rate, &byte_out_rate, &buffering_left );
+ streamer->default_val.buffering_monitor = FALSE;
+ streamer->default_val.prev_pos = position;
+}
- if (streamer->buffer_max_bitrate > 0)
- {
- buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate);
- byte_out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate /3);
- }
- else if (streamer->buffer_avg_bitrate > 0)
- {
- buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3);
- byte_out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate);
- }
+static void __streaming_update_buffering_status(mmplayer_streaming_t *streamer, GstMessage *buffering_msg, gint64 position)
+{
+ gint buffer_percent = 0;
- debug_log ( "in rate is %d, out rate is %d (bytes/sec).\n", byte_in_rate, byte_out_rate );
+ MMPLAYER_FENTER();
- if ( byte_in_rate > 0 && byte_out_rate > 0)
- buffering_time = byte_out_rate / byte_in_rate;
- else if (byte_in_rate <= 0 && byte_out_rate > 0)
- buffering_time = MAX_BUFFERING_TIME;
- else
- buffering_time = DEFAULT_BUFFERING_TIME;
+ MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(buffering_msg);
+ MMPLAYER_RETURN_IF_FAIL(GST_IS_MESSAGE(buffering_msg));
+ MMPLAYER_RETURN_IF_FAIL((GST_MESSAGE_TYPE(buffering_msg) == GST_MESSAGE_BUFFERING));
+
+ /* update when buffering has started. */
+ if (!(streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
+ streamer->buffering_state = MM_PLAYER_BUFFERING_IN_PROGRESS;
+ streamer->buffering_percent = -1;
- streaming_set_buffering_time(streamer, buffering_time);
+ if (!streamer->buffering_req.is_pre_buffering && !streamer->is_adaptive_streaming) {
+ streamer->need_update = TRUE;
+ __streaming_adjust_min_threshold(streamer, position);
+ }
+ }
- /* calculate buffer low/high percent */
- low_percent = DEFAULT_BUFFER_LOW_PERCENT;
+ /* update buffer percent */
+ gst_message_parse_buffering(buffering_msg, &buffer_percent);
- if ( buffer_criteria > 0 )
- {
- high_percent_byte = buffer_criteria * streamer->buffering_time;
- high_percent = ( (gdouble)high_percent_byte * 100.0 ) / (gdouble)streamer->buffer_size;
+ /* LOGD("[%s] buffering per %d%% -> %d%%, state 0x%X", streamer->buffering_percent, buffer_percent, streamer->buffering_state); */
+
+ if (streamer->buffering_percent < buffer_percent) {
+ LOGD("[%s] buffering %d%%....",
+ GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
+ streamer->buffering_percent = buffer_percent;
}
- else
- {
- high_percent_byte = streamer->buffer_high_percent * streamer->buffer_size / 100;
- high_percent= streamer->buffer_high_percent;
+
+ if (streamer->buffering_percent == MAX_BUFFER_PERCENT) {
+ streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
+ streamer->buffering_req.is_pre_buffering = FALSE;
+ streamer->need_update = TRUE;
+ } else if (streamer->buffering_state & MM_PLAYER_BUFFERING_COMPLETE) {
+ streamer->buffering_state = MM_PLAYER_BUFFERING_COMPLETE; /* have to keep state to ignore remained msg till get 100% msg */
+ streamer->buffering_req.is_pre_buffering = FALSE;
+ streamer->buffering_percent = MAX_BUFFER_PERCENT;
+ LOGD("updated to the buffering 100%%.... (by force)");
}
+}
- if ( streamer->buffer_size < high_percent_byte )
- {
- debug_log ( "buffer size[%d bytes] is smaller than high threshold[%d bytes]. update it. \n",
- streamer->buffer_size, high_percent_byte );
+void _mm_player_streaming_buffering(mmplayer_streaming_t *streamer, GstMessage *buffering_msg,
+ guint64 content_size, gint64 position, gint64 duration)
+{
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_IF_FAIL(streamer);
- streaming_set_buffer_size(streamer, high_percent_byte * 1.1);
- }
+ if (buffering_msg) {
+ if (position > (gint64)(streamer->buffering_req.prebuffer_time * GST_MSECOND))
+ streamer->buffering_req.is_pre_buffering = FALSE;
+
+ __streaming_update_buffering_status(streamer, buffering_msg, position);
- streaming_set_buffer_percent(streamer, low_percent, high_percent);
+ if (!streamer->need_update)
+ return;
+ }
streamer->need_update = FALSE;
+ if (!streamer->is_adaptive_streaming)
+ __streaming_update_buffer_setting(streamer, buffering_msg, content_size, position, duration);
return;
}
-