} else if (MMPLAYER_IS_HTTP_STREAMING(player))
data_size = player->http_content_size;
- __mm_player_streaming_buffering(player->streamer,
- buffering_msg,
- data_size,
- player->last_position,
- player->duration);
-
+ __mm_player_streaming_buffering(player->streamer, buffering_msg, data_size, player->last_position, player->duration);
__mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
return;
target_state = MMPLAYER_TARGET_STATE(player);
pending_state = MMPLAYER_PENDING_STATE(player);
- LOGD("player state : prev %s, current %s, pending %s, target %s, buffering %d",
+ LOGD("player state : prev %s, current %s, pending %s, target %s, buffering state 0x%X",
MMPLAYER_STATE_GET_NAME(prev_state),
MMPLAYER_STATE_GET_NAME(current_state),
MMPLAYER_STATE_GET_NAME(pending_state),
MMPLAYER_STATE_GET_NAME(target_state),
- player->streamer->is_buffering);
+ player->streamer->buffering_state);
- if (!player->streamer->is_buffering) {
+ if (!(player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
/* NOTE : if buffering has done, player has to go to target state. */
switch (target_state) {
case MM_PLAYER_STATE_PAUSED:
int bRet = MM_ERROR_NONE;
if (!(player->pipeline && player->pipeline->mainbin)) {
- LOGE("player pipeline handle is null");
+ LOGE("Pipeline is not initialized");
break;
}
MMPLAYER_CMD_LOCK(player);
}
- /* ignore the prev buffering message */
- if ((player->streamer) && (player->streamer->is_buffering == FALSE)
- && (player->streamer->is_buffering_done == TRUE)) {
+ if (!player->streamer) {
+ LOGW("Pipeline is shutting down");
+ MMPLAYER_CMD_UNLOCK(player);
+ break;
+ }
+
+ /* ignore the remained buffering message till getting 100% msg */
+ if (player->streamer->buffering_state == MM_PLAYER_BUFFERING_COMPLETE) {
gint buffer_percent = 0;
gst_message_parse_buffering(msg, &buffer_percent);
if (buffer_percent == MAX_BUFFER_PERCENT) {
LOGD("Ignored all the previous buffering msg!(got %d%%)\n", buffer_percent);
- player->streamer->is_buffering_done = FALSE;
+ player->streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
}
MMPLAYER_CMD_UNLOCK(player);
break;
}
+ /* ignore the remained buffering message */
+ if (player->streamer->buffering_state == MM_PLAYER_BUFFERING_ABORT) {
+ gint buffer_percent = 0;
+
+ gst_message_parse_buffering(msg, &buffer_percent);
+
+ LOGD("force resume -last posted %d %%, new per %d %%",
+ player->streamer->buffering_percent, buffer_percent);
+
+ if (player->streamer->buffering_percent > buffer_percent) {
+ player->streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
+ player->streamer->buffering_req.is_pre_buffering = FALSE;
+
+ LOGD("force resume - need to enter the buffering mode again - %d %%", buffer_percent);
+ } else {
+ LOGD("force resume - ignored the remained buffering msg!");
+ MMPLAYER_CMD_UNLOCK(player);
+ break;
+ }
+ }
+
__mmplayer_update_buffer_setting(player, msg);
- bRet = __mmplayer_handle_buffering_message(player);
+ bRet = __mmplayer_handle_buffering_message(player); /* playback control */
if (bRet == MM_ERROR_NONE) {
msg_param.connection.buffering = player->streamer->buffering_percent;
if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
(player->streamer) &&
(player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
- (player->streamer->is_buffering == FALSE)) {
+ !(player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
GstQuery *query = NULL;
gboolean busy = FALSE;
gint percent = 0;
GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
}
- if (percent >= 100) {
- player->streamer->is_buffering = FALSE;
+ if (percent >= 100)
__mmplayer_handle_buffering_message(player);
- }
}
async_done = TRUE;
LOGD("data total size of http content: %"G_GINT64_FORMAT, bytes);
player->http_content_size = (bytes > 0) ? (bytes) : (0);
}
- } else
+ } else {
/* handling audio clip which has vbr. means duration is keep changing */
_mmplayer_update_content_attrs(player, ATTR_DURATION);
+ }
MMPLAYER_FLEAVE();
if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
LOGE("fail to get duration.\n");
- // enable use-buffering on queue2 instead of multiqueue(ex)audio only streaming
- // use file information was already set on Q2 when it was created.
+ /* there is no mq, enable use-buffering on queue2 (ex) wav streaming
+ * use file information was already set on Q2 when it was created. */
__mm_player_streaming_set_queue2(player->streamer,
player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
- TRUE, // use_buffering
+ TRUE, /* use_buffering */
buffer_bytes,
init_buffering_time,
- 1.0, // low percent
- player->ini.http_buffering_limit, // high percent
- MUXED_BUFFER_TYPE_MEM_QUEUE,
+ 1.0, /* low percent */
+ player->ini.http_buffering_limit, /* high percent */
+ MUXED_BUFFER_TYPE_MAX, /* use previous buffer type setting */
NULL,
((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
}
/* set size and timestamp */
dataBlock = gst_buffer_peek_memory(buffer, 0);
stream->length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
- stream->timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/GST_MSECOND); /* nano sec -> mili sec */
+ stream->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> mili sec */
/* check zero-copy */
if (player->set_mode.video_zc &&
/* check current state */
MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
+ if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
+ LOGD("force resume even during buffering");
+ player->streamer->buffering_state = MM_PLAYER_BUFFERING_ABORT;
+ }
+
ret = __gst_resume(player, async);
if (ret != MM_ERROR_NONE)
}
} else if (g_strrstr(player->type, "application/dash+xml")) {
player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
+ if (player->streamer) {
+ player->streamer->is_adaptive_streaming = TRUE;
+ player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
+ }
}
+ LOGD("uri type : %d", player->profile.uri_type);
MMPLAYER_FLEAVE();
}
LOGD("dur_bytes = %"G_GINT64_FORMAT, dur_bytes);
- muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
+ MuxedBufferType type = MUXED_BUFFER_TYPE_MEM_QUEUE;
if (dur_bytes > 0) {
if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
dur_bytes = 0;
}
- /* NOTE : we cannot get any duration info from ts container in case of streaming */
- // if (!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
+ /* NOTE : in case of ts streaming, player cannot get the correct duration info *
+ * skip the pull mode(file or ring buffering) setting. */
if (!g_strrstr(player->type, "video/mpegts")) {
max_buffer_size_bytes = (type == MUXED_BUFFER_TYPE_FILE) ? (player->ini.http_max_size_bytes) : (5*1024*1024);
LOGD("max_buffer_size_bytes = %d", max_buffer_size_bytes);
- /* FIXME : pass ini setting directly. is this ok? */
__mm_player_streaming_set_queue2(player->streamer,
queue2,
FALSE,
max_buffer_size_bytes,
player->ini.http_buffering_time,
- 1.0, // no meaning
- player->ini.http_buffering_limit, // no meaning
+ 1.0, /* no meaning */
+ player->ini.http_buffering_limit, /* no meaning */
type,
player->http_file_buffering_path,
(guint64)dur_bytes);
mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
/* set decodebin property about buffer in streaming playback. *
- * in case of HLS/DASH, it does not need to have big buffer *
+ * in case of HLS/DASH, it does not need to have big buffer *
* because it is kind of adaptive streaming. */
- if (!MMPLAYER_IS_HTTP_PD(player) && MMPLAYER_IS_HTTP_STREAMING(player)) {
- guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
- guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
+ if (!MMPLAYER_IS_HTTP_PD(player) &&
+ (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player) || MMPLAYER_IS_DASH_STREAMING(player))) {
+ gdouble high_percent = 0.0;
+
init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
+ high_percent = (gdouble)(init_buffering_time * 100) / GET_MAX_BUFFER_TIME(player->streamer);
- if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
- || MMPLAYER_IS_DASH_STREAMING(player)) {
- max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
- max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
- }
+ LOGD("decodebin setting - bytes: %d, time: %d ms, per: 1~%d",
+ GET_MAX_BUFFER_BYTES(player->streamer), GET_MAX_BUFFER_TIME(player->streamer), (gint)high_percent);
g_object_set(G_OBJECT(decodebin), "use-buffering", TRUE,
- "high-percent", (gint)player->ini.http_buffering_limit,
- "low-percent", 1, // 1%
- "max-size-bytes", max_size_bytes,
- "max-size-time", (guint64)(max_size_time * GST_SECOND),
+ "high-percent", (gint)high_percent,
+ "low-percent", (gint)DEFAULT_BUFFER_LOW_PERCENT,
+ "max-size-bytes", GET_MAX_BUFFER_BYTES(player->streamer),
+ "max-size-time", (guint64)(GET_MAX_BUFFER_TIME(player->streamer) * GST_MSECOND),
"max-size-buffers", 0, NULL); // disable or automatic
}
if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
(g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
- LOGD("plugged element is multiqueue. take it\n");
+ LOGD("plugged element is multiqueue. take it %s", GST_ELEMENT_NAME(element));
player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
if (!MMPLAYER_IS_HTTP_PD(player) &&
((MMPLAYER_IS_HTTP_STREAMING(player)) ||
- (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))) {
+ (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) ||
+ (MMPLAYER_IS_DASH_STREAMING(player)))) {
/* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
- __mm_player_streaming_set_multiqueue(player->streamer,
- element,
- TRUE,
- player->ini.http_buffering_time,
- 1.0,
- player->ini.http_buffering_limit);
-
+ __mm_player_streaming_set_multiqueue(player->streamer, element, player->ini.http_buffering_time, 1.0, player->ini.http_buffering_limit);
__mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
}
+
}
return;
static void streaming_check_buffer_percent(gdouble in_low, gdouble in_high, gdouble *out_low, gdouble *out_high);
static void streaming_set_buffer_percent(mm_player_streaming_t* streamer, BufferType type, gdouble low_percent, gdouble high_percent_byte, gdouble high_percent_time);
-static void streaming_set_queue2_queue_type(mm_player_streaming_t* streamer, muxed_buffer_type_e type, gchar * file_path, guint64 content_size);
+static void streaming_set_queue2_queue_type(mm_player_streaming_t* streamer, MuxedBufferType type, gchar * file_path, guint64 content_size);
static void streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gint buffering_time);
static void streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position);
static void streaming_get_current_bitrate_info(mm_player_streaming_t* streamer,
streamer->need_update = FALSE;
streamer->need_sync = FALSE;
- streamer->is_buffering = FALSE;
- streamer->is_buffering_done = FALSE;
+ streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
streamer->is_adaptive_streaming = FALSE;
streamer->is_pd_mode = FALSE;
streamer->need_update = FALSE;
streamer->need_sync = FALSE;
- streamer->is_buffering = FALSE;
- streamer->is_buffering_done = FALSE;
+ streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
streamer->is_adaptive_streaming = FALSE;
streamer->is_pd_mode = FALSE;
}
static void
-streaming_set_queue2_queue_type(mm_player_streaming_t* streamer, muxed_buffer_type_e type, gchar * file_path, guint64 content_size)
+streaming_set_queue2_queue_type(mm_player_streaming_t* streamer, MuxedBufferType type, gchar * file_path, guint64 content_size)
{
streaming_buffer_t* buffer_handle = NULL;
- guint64 storage_available_size = 0; //bytes
- guint64 buffer_size = 0; //bytes
+ guint64 storage_available_size = 0; /* bytes */
+ guint64 buffer_size = 0; /* bytes */
gchar file_buffer_name[MM_MAX_URL_LEN] = {0};
struct statfs buf = {0};
gchar* factory_name = NULL;
return;
}
- if ((type == MUXED_BUFFER_TYPE_MEM_QUEUE) || (!g_strrstr(factory_name, "queue2"))) {
+ if (type == MUXED_BUFFER_TYPE_MEM_QUEUE) {
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"
gint buffering_time,
gdouble low_percent,
gdouble high_percent,
- muxed_buffer_type_e type,
+ MuxedBufferType type,
gchar* file_path,
guint64 content_size)
{
g_object_set(G_OBJECT(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL);
}
+ /* initial setting */
streaming_set_buffer_size(streamer, BUFFER_TYPE_MUXED, buffering_bytes, buffering_time);
streaming_set_buffer_percent(streamer, BUFFER_TYPE_MUXED, low_percent, high_percent, 0);
- streaming_set_queue2_queue_type(streamer, type, file_path, content_size);
+ if (type < MUXED_BUFFER_TYPE_MAX)
+ streaming_set_queue2_queue_type(streamer, type, file_path, content_size);
MMPLAYER_FLEAVE();
return;
"max-size-time", (guint64)(buffer_handle->buffering_time * GST_MSECOND),
"low-percent", (gint)buffer_handle->buffer_low_percent,
"high-percent", (gint)buffer_handle->buffer_high_percent, NULL);
-
}
streamer->need_sync = FALSE;
void __mm_player_streaming_set_multiqueue(mm_player_streaming_t* streamer,
GstElement* buffer,
- gboolean use_buffering,
gint buffering_time,
gdouble low_percent,
gdouble high_percent)
{
streaming_buffer_t* buffer_handle = NULL;
- gint pre_buffering_time = 0;
MMPLAYER_FENTER();
- MMPLAYER_RETURN_IF_FAIL(streamer);
+ MMPLAYER_RETURN_IF_FAIL(streamer && buffer);
buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
- pre_buffering_time = streamer->buffering_req.prebuffer_time;
- if (buffer) {
- buffer_handle->buffer = buffer;
+ buffer_handle->buffer = buffer;
- if (use_buffering) {
- streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
+ streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
+ g_object_set(G_OBJECT(buffer_handle->buffer), "use-buffering", TRUE, NULL);
- // during prebuffering by requirement, buffer setting should not be changed.
- if (pre_buffering_time > 0)
- streamer->buffering_req.is_pre_buffering = TRUE;
- }
- g_object_set(G_OBJECT(buffer_handle->buffer), "use-buffering", use_buffering, NULL);
- }
+ LOGD("pre_buffering: %d ms, during playing: %d ms\n", streamer->buffering_req.prebuffer_time, buffering_time);
- LOGD("pre_buffering: %d ms, during playing: %d ms\n", pre_buffering_time, buffering_time);
-
- if (pre_buffering_time <= 0) {
- pre_buffering_time = GET_DEFAULT_PLAYING_TIME(streamer);
- streamer->buffering_req.prebuffer_time = buffering_time;
- }
+ if (streamer->buffering_req.prebuffer_time > 0)
+ streamer->buffering_req.is_pre_buffering = TRUE;
+ else
+ streamer->buffering_req.prebuffer_time = GET_DEFAULT_PLAYING_TIME(streamer);
- high_percent = (gdouble)(pre_buffering_time * 100) / GET_MAX_BUFFER_TIME(streamer);
+ high_percent = (gdouble)(streamer->buffering_req.prebuffer_time * 100) / GET_MAX_BUFFER_TIME(streamer);
LOGD("high_percent %2.3f %%\n", high_percent);
+ /* initial setting */
streaming_set_buffer_size(streamer, BUFFER_TYPE_DEMUXED, GET_MAX_BUFFER_BYTES(streamer), GET_MAX_BUFFER_TIME(streamer));
streaming_set_buffer_percent(streamer, BUFFER_TYPE_DEMUXED, low_percent, 0, high_percent);
if (streamer->buffering_req.rebuffer_time > 0)
expected_play_time = streamer->buffering_req.rebuffer_time;
- else if ((position == 0) && (streamer->is_buffering))
+ else if ((position == 0) && (streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS))
expected_play_time = streamer->buffering_req.prebuffer_time;
if (expected_play_time <= 0)
MMPLAYER_RETURN_IF_FAIL(buffering_msg);
/* update when buffering has started. */
- if (!streamer->is_buffering) {
- streamer->is_buffering = TRUE;
- streamer->is_buffering_done = FALSE;
+ if (!(streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
+ streamer->buffering_state = MM_PLAYER_BUFFERING_IN_PROGRESS;
streamer->buffering_percent = -1;
if (!streamer->buffering_req.is_pre_buffering) {
/* update buffer percent */
gst_message_parse_buffering(buffering_msg, &buffer_percent);
+ /* LOGD("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%%....\n",
+ LOGD("[%s] buffering %d%%....",
GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
streamer->buffering_percent = buffer_percent;
}
- if ((streamer->buffering_percent == MAX_BUFFER_PERCENT) || (streamer->is_buffering_done == TRUE)) {
- streamer->is_buffering = FALSE;
+ if (streamer->buffering_percent == MAX_BUFFER_PERCENT) {
+ streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
streamer->buffering_req.is_pre_buffering = FALSE;
- if (streamer->buffering_percent == MAX_BUFFER_PERCENT)
- streamer->is_buffering_done = FALSE;
- else
- streamer->buffering_percent = MAX_BUFFER_PERCENT;
+ } 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)");
}
}