4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
7 * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
25 #include "mm_player_utils.h"
26 #include "mm_player_streaming.h"
31 gint byte_in_rate; // byte
32 gint byte_out_rate; // byte
33 gdouble time_rate; // second
34 guint buffer_criteria; // byte
35 }streaming_bitrate_info_t;
38 gint64 position; // ns
39 gint64 duration; // ns
40 guint64 content_size; // bytes
41 }streaming_content_info_t;
44 guint buffering_bytes; // bytes
45 gdouble buffering_time; // second
48 }streaming_buffer_info_t;
50 static void streaming_check_buffer_percent(gdouble in_low, gdouble in_high, gdouble *out_low, gdouble *out_high);
51 static void streaming_set_buffer_percent(mm_player_streaming_t* streamer, BufferType type, gdouble low_percent, gdouble high_percent_byte, gdouble high_percent_time);
52 static void streaming_set_queue2_queue_type (mm_player_streaming_t* streamer, muxed_buffer_type_e type, gchar * file_path, guint64 content_size);
53 static void streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gdouble buffering_time);
54 static void streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position);
55 static void streaming_get_current_bitrate_info( mm_player_streaming_t* streamer,
56 GstMessage *buffering_msg,
57 streaming_content_info_t content_info,
58 streaming_bitrate_info_t* bitrate_info);
60 streaming_handle_fixed_buffering_mode( mm_player_streaming_t* streamer,
62 gdouble fixed_buffering_time,
63 streaming_buffer_info_t* buffer_info);
65 streaming_handle_adaptive_buffering_mode( mm_player_streaming_t* streamer,
66 streaming_content_info_t content_info,
67 streaming_bitrate_info_t bitrate_info,
68 streaming_buffer_info_t* buffer_info,
69 gint expected_play_time);
71 streaming_update_buffer_setting ( mm_player_streaming_t* streamer,
72 GstMessage *buffering_msg,
77 mm_player_streaming_t *
78 __mm_player_streaming_create (void)
80 mm_player_streaming_t *streamer = NULL;
84 streamer = (mm_player_streaming_t *) malloc (sizeof (mm_player_streaming_t));
87 LOGE ("fail to create streaming player handle..\n");
91 memset(streamer, 0, sizeof(mm_player_streaming_t));
99 streaming_buffer_initialize (streaming_buffer_t* buffer_handle, gboolean buffer_init)
102 buffer_handle->buffer = NULL;
104 buffer_handle->buffering_bytes = DEFAULT_BUFFER_SIZE_BYTES;
105 buffer_handle->buffering_time = DEFAULT_BUFFERING_TIME;
106 buffer_handle->buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
107 buffer_handle->buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
108 buffer_handle->is_live = FALSE;
112 void __mm_player_streaming_initialize (mm_player_streaming_t* streamer)
116 streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT; // multi-queue
118 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), TRUE);
119 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), TRUE);
121 streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
122 streamer->buffering_req.is_pre_buffering = FALSE;
123 streamer->buffering_req.initial_second = 0;
124 streamer->buffering_req.runtime_second = 0;
126 streamer->default_val.buffering_monitor = FALSE;
127 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
129 streamer->buffer_avg_bitrate = 0;
130 streamer->buffer_max_bitrate = 0;
131 streamer->need_update = FALSE;
132 streamer->need_sync = FALSE;
134 streamer->is_buffering = FALSE;
135 streamer->is_buffering_done = FALSE;
136 streamer->is_adaptive_streaming = FALSE;
137 streamer->buffering_percent = -1;
139 streamer->ring_buffer_size = DEFAULT_RING_BUFFER_SIZE;
144 void __mm_player_streaming_deinitialize (mm_player_streaming_t* streamer)
147 MMPLAYER_RETURN_IF_FAIL(streamer);
149 streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT; // multi-queue
151 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), FALSE);
152 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), FALSE);
154 streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
155 streamer->buffering_req.is_pre_buffering = FALSE;
156 streamer->buffering_req.initial_second = 0;
157 streamer->buffering_req.runtime_second = 0;
159 streamer->default_val.buffering_monitor = FALSE;
160 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
162 streamer->buffer_avg_bitrate = 0;
163 streamer->buffer_max_bitrate = 0;
164 streamer->need_update = FALSE;
165 streamer->need_sync = FALSE;
167 streamer->is_buffering = FALSE;
168 streamer->is_buffering_done = FALSE;
169 streamer->is_adaptive_streaming = FALSE;
171 streamer->buffering_percent = -1;
172 streamer->ring_buffer_size = DEFAULT_RING_BUFFER_SIZE;
178 void __mm_player_streaming_destroy (mm_player_streaming_t* streamer)
193 void __mm_player_streaming_set_content_bitrate(mm_player_streaming_t* streamer, guint max_bitrate, guint avg_bitrate)
197 MMPLAYER_RETURN_IF_FAIL(streamer);
199 /* Note : Update buffering criterion bytes
200 * 1. maximum bitrate is considered first.
201 * 2. average bitrage * 3 is next.
202 * 3. if there are no updated bitrate, use default buffering limit.
204 if (max_bitrate > 0 && streamer->buffer_max_bitrate != max_bitrate)
206 LOGD("set maximum bitrate(%dbps).\n", max_bitrate);
207 streamer->buffer_max_bitrate = max_bitrate;
208 if (streamer->buffering_req.is_pre_buffering == FALSE)
210 streamer->need_update = TRUE;
214 LOGD("pre-buffering...\n");
216 if (IS_MUXED_BUFFERING_MODE(streamer))
217 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
221 if (avg_bitrate > 0 && streamer->buffer_avg_bitrate != avg_bitrate)
223 LOGD("set averate bitrate(%dbps).\n", avg_bitrate);
224 streamer->buffer_avg_bitrate = avg_bitrate;
226 if (streamer->buffering_req.is_pre_buffering == FALSE)
228 streamer->need_update = TRUE;
232 LOGD("pre-buffering...\n");
234 if (IS_MUXED_BUFFERING_MODE(streamer))
235 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
244 streaming_check_buffer_percent(gdouble in_low, gdouble in_high, gdouble *out_low, gdouble *out_high)
246 gdouble buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
247 gdouble buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
251 MMPLAYER_RETURN_IF_FAIL(out_low && out_high);
253 if (in_low <= MIN_BUFFER_PERCENT || in_low >= MAX_BUFFER_PERCENT)
255 LOGW("buffer low percent is out of range. use defaut value.");
259 buffer_low_percent = in_low;
262 if (in_high <= MIN_BUFFER_PERCENT || in_high >= MAX_BUFFER_PERCENT)
264 LOGW("buffer high percent is out of range. use defaut value.");
268 buffer_high_percent = in_high;
271 if (buffer_high_percent <= buffer_low_percent)
272 buffer_high_percent = buffer_low_percent + 1.0;
274 LOGD("set buffer percent to %2.3f ~ %2.3f.", buffer_low_percent, buffer_high_percent);
276 *out_low = buffer_low_percent;
277 *out_high = buffer_high_percent;
281 streaming_set_buffer_percent( mm_player_streaming_t* streamer,
284 gdouble high_percent_byte,
285 gdouble high_percent_time)
287 gdouble confirmed_low = DEFAULT_BUFFER_LOW_PERCENT;
288 gdouble confirmed_high = DEFAULT_BUFFER_HIGH_PERCENT;
289 gdouble high_percent = 0.0;
291 streaming_buffer_t* buffer_handle = NULL;
292 gchar* factory_name = NULL;
295 MMPLAYER_RETURN_IF_FAIL(streamer);
296 MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
298 buffer_handle = &(streamer->buffer_handle[type]);
299 if (!(buffer_handle && buffer_handle->buffer))
301 LOGE("buffer_handle->buffer is NULL!");
305 factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
309 LOGE("Fail to get factory name!");
313 if (type == BUFFER_TYPE_MUXED)
314 high_percent = high_percent_byte;
316 high_percent = MAX(high_percent_time, high_percent_byte);
318 streaming_check_buffer_percent(low_percent, high_percent, &confirmed_low, &confirmed_high);
320 /* if use-buffering is disabled, this settings do not have any meaning. */
321 LOGD("target buffer elem : %s (%2.3f ~ %2.3f)",
322 GST_ELEMENT_NAME(buffer_handle->buffer), confirmed_low, confirmed_high);
324 if ((confirmed_low == DEFAULT_BUFFER_LOW_PERCENT) ||
325 (buffer_handle->buffer_low_percent != confirmed_low))
327 g_object_set (G_OBJECT(buffer_handle->buffer), "low-percent", (gint)confirmed_low, NULL);
330 if ((confirmed_high == DEFAULT_BUFFER_HIGH_PERCENT) ||
331 (buffer_handle->buffer_high_percent != confirmed_high))
333 g_object_set (G_OBJECT(buffer_handle->buffer), "high-percent", (gint)confirmed_high, NULL);
336 buffer_handle->buffer_low_percent = confirmed_low;
337 buffer_handle->buffer_high_percent = confirmed_high;
344 streaming_set_queue2_queue_type (mm_player_streaming_t* streamer, muxed_buffer_type_e type, gchar * file_path, guint64 content_size)
346 streaming_buffer_t* buffer_handle = NULL;
347 guint64 storage_available_size = 0L; //bytes
348 guint64 buffer_size = 0L; //bytes
349 gchar file_buffer_name[MM_MAX_URL_LEN] = {0};
350 struct statfs buf = {0};
351 gchar* factory_name = NULL;
354 MMPLAYER_RETURN_IF_FAIL(streamer);
355 MMPLAYER_RETURN_IF_FAIL(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer);
357 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_MUXED]);
359 if (!(buffer_handle && buffer_handle->buffer))
361 LOGE("buffer_handle->buffer is NULL!");
365 factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
369 LOGE("Fail to get factory name!");
373 LOGD("target buffer elem : %s", GST_ELEMENT_NAME(buffer_handle->buffer));
375 if (!g_strrstr(factory_name, "queue2"))
377 LOGD("only queue2 can use file buffer. not decodebin2 or multiQ\n");
381 if ((type == MUXED_BUFFER_TYPE_MEM_QUEUE) || (!g_strrstr(factory_name, "queue2")))
383 LOGD("use memory queue for buffering. streaming is played on push-based. \n"
384 "buffering position would not be updated.\n"
385 "buffered data would be flushed after played.\n"
386 "seeking and getting duration could be failed due to file format.");
390 LOGD("[Queue2] buffering type : %d. streaming is played on pull-based. \n", type);
391 if (type == MUXED_BUFFER_TYPE_FILE && file_path && strlen(file_path)>0) {
392 if (statfs((const char *)file_path, &buf) < 0)
394 LOGW ("[Queue2] fail to get available storage capacity. set mem ring buffer instead of file buffer.\n");
395 buffer_size = (guint64)((streamer->ring_buffer_size>0)?(streamer->ring_buffer_size):DEFAULT_RING_BUFFER_SIZE);
399 storage_available_size = (guint64)buf.f_bavail * (guint64)buf.f_bsize; //bytes
401 LOGD ("[Queue2] the number of available blocks : %"G_GUINT64_FORMAT
402 ", the block size is %"G_GUINT64_FORMAT".\n",
403 (guint64)buf.f_bavail, (guint64)buf.f_bsize);
405 LOGD ("[Queue2] calculated available storage size is %"
406 G_GUINT64_FORMAT" Bytes.\n", storage_available_size);
408 if (content_size <= 0 || content_size >= storage_available_size)
409 buffer_size = storage_available_size;
413 g_snprintf(file_buffer_name, MM_MAX_URL_LEN, "%sXXXXXX", file_path);
414 SECURE_LOGD("[Queue2] the buffering file name is %s.\n", file_buffer_name);
416 g_object_set (G_OBJECT(buffer_handle->buffer), "temp-template", file_buffer_name, NULL);
419 buffer_size = (guint64)((streamer->ring_buffer_size>0)?(streamer->ring_buffer_size):DEFAULT_RING_BUFFER_SIZE);
422 LOGW ("[Queue2] set ring buffer size: %lld\n", buffer_size);
423 g_object_set (G_OBJECT(buffer_handle->buffer), "ring-buffer-max-size", buffer_size, NULL);
430 streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gdouble buffering_time)
432 streaming_buffer_t* buffer_handle = NULL;
436 MMPLAYER_RETURN_IF_FAIL(streamer);
437 MMPLAYER_RETURN_IF_FAIL(buffering_bytes > 0);
438 MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
440 buffer_handle = &(streamer->buffer_handle[type]);
442 if (buffer_handle && buffer_handle->buffer)
444 if (g_strrstr(GST_ELEMENT_NAME(buffer_handle->buffer), "multiqueue"))
446 if (buffering_time <= 0)
447 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
449 g_object_set (G_OBJECT(buffer_handle->buffer),
450 "max-size-bytes", GET_MAX_BUFFER_BYTES(streamer), /* mq size is fixed, control it with high/low percent value*/
451 "max-size-time", ((guint)ceil(buffering_time) * GST_SECOND),
452 "max-size-buffers", 0, NULL); /* disable */
454 buffer_handle->buffering_time = buffering_time;
455 buffer_handle->buffering_bytes = GET_MAX_BUFFER_BYTES(streamer);
457 LOGD("max-size-time : %f", buffering_time);
461 if (buffer_handle->is_live)
463 g_object_set (G_OBJECT(buffer_handle->buffer),
464 "max-size-bytes", buffering_bytes,
465 "max-size-time", (guint64)(buffering_time*GST_SECOND),
466 "max-size-buffers", 0,
467 "use-rate-estimate", TRUE, NULL);
471 g_object_set (G_OBJECT(buffer_handle->buffer),
472 "max-size-bytes", buffering_bytes,
473 "max-size-time", (guint64)0,
474 "max-size-buffers", 0,
475 "use-rate-estimate", FALSE, NULL);
478 buffer_handle->buffering_bytes = buffering_bytes;
479 buffer_handle->buffering_time = buffering_time;
481 LOGD("max-size-bytes : %d", buffering_bytes);
489 void __mm_player_streaming_set_queue2( mm_player_streaming_t* streamer,
491 gboolean use_buffering,
492 guint buffering_bytes,
493 gdouble buffering_time,
495 gdouble high_percent,
496 muxed_buffer_type_e type,
498 guint64 content_size)
501 MMPLAYER_RETURN_IF_FAIL(streamer);
505 LOGD("USE-BUFFERING : %s", (use_buffering)?"OOO":"XXX");
507 streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer = buffer;
511 streamer->streaming_buffer_type = BUFFER_TYPE_MUXED;
513 if (content_size > 0)
515 if (streamer->buffering_req.initial_second > 0)
516 streamer->buffering_req.is_pre_buffering = TRUE;
518 streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
522 LOGD("live streaming without mq");
524 streamer->buffer_handle[BUFFER_TYPE_MUXED].is_live = TRUE;
525 streamer->buffering_req.initial_second = buffering_time = DEFAULT_BUFFERING_TIME;
529 g_object_set ( G_OBJECT (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL );
532 streaming_set_buffer_size (streamer, BUFFER_TYPE_MUXED, buffering_bytes, buffering_time);
533 streaming_set_buffer_percent (streamer, BUFFER_TYPE_MUXED, low_percent, high_percent, 0);
534 streaming_set_queue2_queue_type (streamer, type, file_path, content_size);
540 void __mm_player_streaming_sync_property(mm_player_streaming_t* streamer, GstElement* decodebin)
542 streaming_buffer_t* buffer_handle = NULL;
546 MMPLAYER_RETURN_IF_FAIL ( streamer && decodebin );
548 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
550 if ((streamer->need_sync) && (streamer->streaming_buffer_type == BUFFER_TYPE_DEMUXED))
552 g_object_set (G_OBJECT(decodebin),
553 "max-size-bytes", buffer_handle->buffering_bytes,
554 "max-size-time", (guint64)(ceil(buffer_handle->buffering_time) * GST_SECOND),
555 "low-percent", (gint)buffer_handle->buffer_low_percent,
556 "high-percent", (gint)buffer_handle->buffer_high_percent, NULL);
560 streamer->need_sync = FALSE;
563 void __mm_player_streaming_set_multiqueue( mm_player_streaming_t* streamer,
565 gboolean use_buffering,
566 gdouble buffering_time,
568 gdouble high_percent)
570 streaming_buffer_t* buffer_handle = NULL;
571 gdouble pre_buffering_time = 0.0;
574 MMPLAYER_RETURN_IF_FAIL(streamer);
576 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
577 pre_buffering_time = (gdouble)streamer->buffering_req.initial_second;
581 buffer_handle->buffer = buffer;
585 streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
587 // during prebuffering by requirement, buffer setting should not be changed.
588 if (pre_buffering_time > 0)
589 streamer->buffering_req.is_pre_buffering = TRUE;
592 g_object_set ( G_OBJECT (buffer_handle->buffer), "use-buffering", use_buffering, NULL );
595 LOGD ("pre_buffering: %2.2f, during playing: %2.2f\n", pre_buffering_time, buffering_time);
597 if (pre_buffering_time <= 0.0)
599 pre_buffering_time = GET_DEFAULT_PLAYING_TIME(streamer);
600 streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
603 high_percent = (pre_buffering_time * 100) / GET_MAX_BUFFER_TIME(streamer);
604 LOGD ("high_percent %2.3f %%\n", high_percent);
606 streaming_set_buffer_size (streamer, BUFFER_TYPE_DEMUXED, GET_MAX_BUFFER_BYTES(streamer), GET_MAX_BUFFER_TIME(streamer));
607 streaming_set_buffer_percent (streamer, BUFFER_TYPE_DEMUXED, low_percent, 0, high_percent);
609 streamer->need_sync = TRUE;
616 streaming_get_current_bitrate_info( mm_player_streaming_t* streamer,
617 GstMessage *buffering_msg,
618 streaming_content_info_t content_info,
619 streaming_bitrate_info_t* bitrate_info)
622 GstQuery *query = NULL;
623 GstBufferingMode mode = GST_BUFFERING_STREAM;
626 gint64 buffering_left = -1;
628 guint buffer_criteria = 0;
629 guint estimated_content_bitrate = 0;
631 gdouble buffer_buffering_time = DEFAULT_BUFFERING_TIME;
635 MMPLAYER_RETURN_IF_FAIL(streamer);
636 MMPLAYER_RETURN_IF_FAIL(bitrate_info);
638 if ((buffering_msg == NULL) ||
639 ((streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer != NULL) &&
640 (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer != NULL) &&
641 (buffering_msg->src == (GstObject *)streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer)))
643 query = gst_query_new_buffering (GST_FORMAT_PERCENT);
645 if (gst_element_query ((streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), query))
647 gst_query_parse_buffering_stats (query, &mode, &in_rate, &out_rate, &buffering_left);
650 gst_query_unref (query);
654 gst_message_parse_buffering_stats (buffering_msg, &mode, &in_rate, &out_rate, &buffering_left);
657 LOGD ("Streaming Info : in %d, out %d, left %lld\n", in_rate, out_rate, buffering_left);
659 if ((content_info.content_size > 0) && (content_info.duration > 0) && ((content_info.duration/GST_SECOND) > 0))
660 estimated_content_bitrate = GET_BIT_FROM_BYTE((guint)(content_info.content_size / (content_info.duration/GST_SECOND)));
662 if (streamer->buffer_max_bitrate > 0)
664 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, streamer->buffer_avg_bitrate);
665 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, estimated_content_bitrate);
667 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate);
669 if (streamer->buffer_avg_bitrate > estimated_content_bitrate)
670 out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate);
671 else if (estimated_content_bitrate != 0)
672 out_rate = GET_BYTE_FROM_BIT(estimated_content_bitrate);
674 out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate/3);
676 LOGD ("(max)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
678 else if (streamer->buffer_avg_bitrate > 0)
680 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3);
681 out_rate = GET_BYTE_FROM_BIT(MAX(streamer->buffer_avg_bitrate,estimated_content_bitrate));
683 LOGD ("(avg)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
687 LOGW ("There is no content bitrate information\n");
690 if ((in_rate > 0) && (out_rate > 0))
691 buffer_buffering_time = (gdouble)out_rate / (gdouble)in_rate;
692 else if ((in_rate <= 0) && (out_rate > 0))
693 buffer_buffering_time = MAX_BUFFERING_TIME;
695 buffer_buffering_time = DEFAULT_BUFFERING_TIME;
697 (*bitrate_info).byte_in_rate = in_rate;
698 (*bitrate_info).byte_out_rate = out_rate;
699 (*bitrate_info).time_rate = buffer_buffering_time;
700 (*bitrate_info).buffer_criteria = buffer_criteria;
704 streaming_handle_fixed_buffering_mode( mm_player_streaming_t* streamer,
706 gdouble fixed_buffering_time,
707 streaming_buffer_info_t* buffer_info)
709 streaming_buffer_t* buffer_handle = NULL;
711 guint buffering_bytes = 0;
712 gdouble buffering_time = 0.0;
713 gdouble per_byte = 0.0;
714 gdouble per_time = 0.0;
716 MMPLAYER_RETURN_IF_FAIL(streamer);
717 MMPLAYER_RETURN_IF_FAIL(buffer_info);
719 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
720 buffering_time = fixed_buffering_time;
722 LOGD ("buffering time: %2.2f sec, out rate: %d\n", buffering_time, byte_out_rate);
724 if ((buffering_time > 0) && (byte_out_rate > 0))
726 buffering_bytes = GET_NEW_BUFFERING_BYTE(byte_out_rate * buffering_time);
730 if (buffering_time <= 0)
731 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
733 LOGW ("content bitrate is not updated yet.\n");
734 buffering_bytes = GET_CURRENT_BUFFERING_BYTE(buffer_handle);
737 GET_PERCENT(buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
738 GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
740 LOGD ("bytes %d, time %f, per_byte %f, per_time %f\n",
741 buffering_bytes, buffering_time, per_byte, per_time);
743 (*buffer_info).buffering_bytes = buffering_bytes;
744 (*buffer_info).buffering_time = buffering_time;
745 (*buffer_info).percent_byte = per_byte;
746 (*buffer_info).percent_time = per_time;
750 streaming_handle_adaptive_buffering_mode( mm_player_streaming_t* streamer,
751 streaming_content_info_t content_info,
752 streaming_bitrate_info_t bitrate_info,
753 streaming_buffer_info_t* buffer_info,
754 gint expected_play_time)
756 streaming_buffer_t* buffer_handle = NULL;
758 gint buffering_bytes = 0;
759 gint adj_buffering_bytes = 0;
760 gdouble buffer_buffering_time = 0.0;
761 gdouble per_byte = 0.0;
762 gdouble per_time = 0.0;
763 gdouble portion = 0.0;
764 gdouble default_buffering_time = 0.0;
766 MMPLAYER_RETURN_IF_FAIL(streamer);
767 MMPLAYER_RETURN_IF_FAIL(buffer_info);
769 LOGD ("pos %lld, dur %lld, size %lld, in/out:%d/%d, buffer_criteria:%d, time_rate:%f, need:%d sec\n",
770 content_info.position, content_info.duration, content_info.content_size,
771 bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
772 bitrate_info.buffer_criteria, bitrate_info.time_rate, expected_play_time);
774 if (((expected_play_time == TO_THE_END) && (content_info.position <= 0)) ||
775 (content_info.duration <= 0) ||
776 (content_info.content_size <= 0))
778 LOGW ("keep previous setting.\n");
782 if ((bitrate_info.byte_out_rate <= 0) || (bitrate_info.buffer_criteria == 0))
784 LOGW ("keep previous setting.\n");
788 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
790 if (bitrate_info.byte_in_rate < bitrate_info.byte_out_rate)
792 if (expected_play_time != TO_THE_END)
793 portion = (double)(expected_play_time * GST_SECOND) / (double)content_info.duration;
795 portion = (1 - (double)content_info.position/(double)content_info.duration);
797 buffering_bytes = GET_NEW_BUFFERING_BYTE(((double)content_info.content_size * portion) \
798 * (1 - (double)bitrate_info.byte_in_rate/(double)bitrate_info.byte_out_rate));
802 /* buffering_bytes will be set as streamer->default_val.buffering_time *
803 * receiving rate is bigger than avg content bitrate
804 * so there is no reason to buffering. if the buffering msg is posted
805 * in-rate or contents bitrate has wrong value. */
806 LOGW ("don't need to do buffering.\n");
809 if (buffering_bytes > 0)
810 buffer_buffering_time = (gdouble)buffering_bytes / (gdouble)bitrate_info.byte_out_rate;
812 if (content_info.position <= 0)
814 /* if the buffer is filled under 50%, MSL use the original default buffering time.
815 if not, MSL use just 2 sec as a default buffering time. (to reduce initial buffering time) */
816 default_buffering_time = streamer->default_val.buffering_time - ((gdouble)streamer->buffering_percent/50);
820 default_buffering_time = streamer->default_val.buffering_time;
823 if (buffer_buffering_time < default_buffering_time)
825 LOGD ("adjusted time: %2.2f -> %2.2f\n", buffer_buffering_time, default_buffering_time);
826 LOGD ("adjusted bytes : %d or %d or %d\n",
828 (gint)(bitrate_info.byte_out_rate * buffer_buffering_time),
829 (gint)(bitrate_info.buffer_criteria * buffer_buffering_time));
831 if (content_info.position > 0)
833 /* start monitoring the abmormal state */
834 streamer->default_val.buffering_monitor = TRUE;
837 buffer_buffering_time = default_buffering_time;
838 adj_buffering_bytes = GET_NEW_BUFFERING_BYTE(bitrate_info.byte_out_rate * (gint)ceil(buffer_buffering_time));
839 buffering_bytes = MAX(buffering_bytes, adj_buffering_bytes);
842 GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
843 GET_PERCENT(buffer_buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
845 LOGD ("monitor %d, bytes %d, time %f, per_byte %f, per_time %f\n",
846 streamer->default_val.buffering_monitor,
847 buffering_bytes, buffer_buffering_time, per_byte, per_time);
849 (*buffer_info).buffering_bytes = buffering_bytes;
850 (*buffer_info).buffering_time = buffer_buffering_time;
851 (*buffer_info).percent_byte = per_byte;
852 (*buffer_info).percent_time = per_time;
857 streaming_update_buffer_setting ( mm_player_streaming_t* streamer,
858 GstMessage *buffering_msg, // can be null
859 guint64 content_size,
863 streaming_buffer_t* buffer_handle = NULL;
864 MMPlayerBufferingMode buffering_mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
866 streaming_buffer_info_t buffer_info;
867 streaming_content_info_t content_info;
868 streaming_bitrate_info_t bitrate_info;
870 gdouble low_percent = 0.0;
874 MMPLAYER_RETURN_IF_FAIL ( streamer );
876 memset(&buffer_info, 0x00, sizeof(streaming_buffer_info_t));
877 memset(&content_info, 0x00, sizeof(streaming_content_info_t));
878 memset(&bitrate_info, 0x00, sizeof(streaming_bitrate_info_t));
880 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
882 if (streamer->buffering_req.is_pre_buffering == TRUE)
883 buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
885 buffering_mode = streamer->buffering_req.mode;
887 buffer_info.buffering_bytes = buffer_handle->buffering_bytes;
888 buffer_info.buffering_time = buffer_handle->buffering_time;
889 buffer_info.percent_byte = buffer_handle->buffer_high_percent;
890 buffer_info.percent_time = buffer_handle->buffer_high_percent;
892 content_info.position = position;
893 content_info.duration = duration;
894 content_info.content_size = content_size;
896 streaming_get_current_bitrate_info(streamer, buffering_msg, content_info, &bitrate_info);
898 LOGD ("buffering mode %d, new info in_r:%d, out_r:%d, cb:%d, bt:%f\n",
899 buffering_mode, bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
900 bitrate_info.buffer_criteria, bitrate_info.time_rate);
902 /* calculate buffer low/high percent */
903 low_percent = DEFAULT_BUFFER_LOW_PERCENT;
905 /********************
907 ********************/
909 if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED)
911 gdouble buffering_time = 0.0;
913 if (streamer->buffering_req.is_pre_buffering == TRUE)
914 buffering_time = (gdouble)streamer->buffering_req.initial_second;
916 buffering_time = (gdouble)streamer->buffering_req.runtime_second;
918 streaming_handle_fixed_buffering_mode(streamer, bitrate_info.byte_out_rate, buffering_time, &buffer_info);
921 /***********************************
922 * (2) once mode for samsung link *
923 ***********************************/
924 else if (buffering_mode == MM_PLAYER_BUFFERING_MODE_SLINK)
926 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, TO_THE_END);
929 /*********************************
930 * (3) adaptive mode (default) *
931 *********************************/
934 gint expected_play_time = DEFAULT_PLAYING_TIME;
936 if (streamer->buffering_req.runtime_second > 0)
938 expected_play_time = streamer->buffering_req.runtime_second;
940 else if ((position == 0) && (streamer->is_buffering))
942 expected_play_time = streamer->buffering_req.initial_second;
945 if (expected_play_time <= 0)
946 expected_play_time = DEFAULT_PLAYING_TIME;
948 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, expected_play_time);
950 if (IS_MUXED_BUFFERING_MODE(streamer)) // even if new byte size is smaller than the previous one, time need to be updated.
951 buffer_handle->buffering_time = buffer_info.buffering_time;
954 LOGD ("adj buffer(%d) %d->%d bytes/%2.2f->%2.2f sec\n",
955 streamer->streaming_buffer_type,
956 GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_info.buffering_bytes,
957 GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_info.buffering_time);
959 /* queue2 : bytes, multiqueue : time */
960 if (((GET_CURRENT_BUFFERING_BYTE(buffer_handle) < buffer_info.buffering_bytes) && IS_MUXED_BUFFERING_MODE(streamer)) ||
961 ((GET_CURRENT_BUFFERING_TIME(buffer_handle) < buffer_info.buffering_time) && IS_DEMUXED_BUFFERING_MODE(streamer)))
963 if (duration > 0 && position > 0)
965 gdouble buffering_time_limit = (gdouble)(duration - position)/GST_SECOND;
967 if (buffer_info.buffering_time > buffering_time_limit)
968 buffer_info.buffering_time = buffering_time_limit;
971 streaming_set_buffer_size(streamer, streamer->streaming_buffer_type, buffer_info.buffering_bytes, buffer_info.buffering_time);
974 streaming_set_buffer_percent(streamer, streamer->streaming_buffer_type, low_percent, buffer_info.percent_byte, buffer_info.percent_time);
976 LOGD("buffer setting: size %d, time %f, per %f\n",
977 GET_CURRENT_BUFFERING_BYTE(buffer_handle),
978 GET_CURRENT_BUFFERING_TIME(buffer_handle),
979 buffer_handle->buffer_high_percent);
981 streamer->need_sync = TRUE;
985 streaming_adjust_min_threshold(mm_player_streaming_t* streamer, gint64 position)
987 #define DEFAULT_TIME_PAD 1 /* sec */
988 gint playing_time = 0;
992 MMPLAYER_RETURN_IF_FAIL(streamer);
994 playing_time = (gint)((position - streamer->default_val.prev_pos) / GST_SECOND);
996 LOGD ("buffering monitor = %s\n", (streamer->default_val.buffering_monitor)?"ON":"OFF");
997 LOGD ("playing_time ( %d sec) = %lld - %lld \n", playing_time, position, streamer->default_val.prev_pos);
998 LOGD ("default time : %2.3f, prev buffering t : %2.3f\n",
999 streamer->default_val.buffering_time, streamer->buffer_handle[streamer->streaming_buffer_type].buffering_time);
1001 if ((streamer->default_val.buffering_monitor) && (playing_time <= (gint)streamer->default_val.buffering_time))
1004 time_gap = (gint)(streamer->default_val.buffering_time - DEFAULT_BUFFERING_TIME);
1006 time_gap = DEFAULT_TIME_PAD;
1008 streamer->default_val.buffering_time += time_gap*2;
1009 streamer->default_val.buffering_time = MIN(streamer->default_val.buffering_time, MAX_BUFFERING_TIME);
1013 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
1016 LOGD ("new default min value %2.3f \n", streamer->default_val.buffering_time);
1018 streamer->default_val.buffering_monitor = FALSE;
1019 streamer->default_val.prev_pos = position;
1023 streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position)
1025 gint buffer_percent = 0;
1026 gboolean increased_per = TRUE;
1030 MMPLAYER_RETURN_IF_FAIL(streamer);
1031 MMPLAYER_RETURN_IF_FAIL(buffering_msg);
1033 /* update when buffering has started. */
1034 if ( !streamer->is_buffering )
1036 streamer->is_buffering = TRUE;
1037 streamer->is_buffering_done = FALSE;
1038 streamer->buffering_percent = -1;
1040 if (!streamer->buffering_req.is_pre_buffering)
1042 streamer->need_update = TRUE;
1043 streaming_adjust_min_threshold(streamer, position);
1047 /* update buffer percent */
1048 gst_message_parse_buffering (buffering_msg, &buffer_percent);
1050 if (streamer->buffering_percent < buffer_percent)
1052 LOGD ("[%s] buffering %d%%....\n",
1053 GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
1054 streamer->buffering_percent = buffer_percent;
1058 increased_per = FALSE;
1061 if ((streamer->buffering_percent == MAX_BUFFER_PERCENT) || (streamer->is_buffering_done == TRUE))
1063 streamer->is_buffering = FALSE;
1064 streamer->buffering_req.is_pre_buffering = FALSE;
1065 if (streamer->buffering_percent == MAX_BUFFER_PERCENT)
1066 streamer->is_buffering_done = FALSE;
1068 streamer->buffering_percent = MAX_BUFFER_PERCENT;
1072 /* need to update periodically in case of slink mode */
1073 if ((increased_per == TRUE) &&
1074 (buffer_percent%10 == 0) &&
1075 (streamer->buffering_req.mode == MM_PLAYER_BUFFERING_MODE_SLINK) &&
1076 (streamer->buffering_req.is_pre_buffering == FALSE))
1078 /* Update buffer setting to reflect data receiving rate for slink mode */
1079 streamer->need_update = TRUE;
1084 void __mm_player_streaming_buffering( mm_player_streaming_t* streamer,
1085 GstMessage *buffering_msg,
1086 guint64 content_size,
1092 MMPLAYER_RETURN_IF_FAIL ( streamer );
1093 MMPLAYER_RETURN_IF_FAIL ( buffering_msg );
1094 MMPLAYER_RETURN_IF_FAIL ( GST_IS_MESSAGE ( buffering_msg ) );
1095 MMPLAYER_RETURN_IF_FAIL ( (GST_MESSAGE_TYPE ( buffering_msg ) == GST_MESSAGE_BUFFERING) );
1099 if (position > (gint64)(streamer->buffering_req.initial_second * GST_SECOND))
1100 streamer->buffering_req.is_pre_buffering = FALSE;
1102 streaming_update_buffering_status(streamer, buffering_msg, position);
1104 if (!streamer->need_update)
1106 //LOGD ("don't need to update buffering stats during buffering.\n");
1110 streamer->need_update = FALSE;
1113 streaming_update_buffer_setting (streamer, buffering_msg, content_size, position, duration);