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.
24 #include "mm_player_utils.h"
25 #include "mm_player_streaming.h"
30 gint byte_in_rate; // byte
31 gint byte_out_rate; // byte
32 gdouble time_rate; // second
33 guint buffer_criteria; // byte
34 }streaming_bitrate_info_t;
37 gint64 position; // ns
38 gint64 duration; // ns
39 guint64 content_size; // bytes
40 }streaming_content_info_t;
43 guint buffering_bytes; // bytes
44 gdouble buffering_time; // second
47 }streaming_buffer_info_t;
49 static void streaming_check_buffer_percent(gdouble in_low, gdouble in_high, gdouble *out_low, gdouble *out_high);
50 static void streaming_set_buffer_percent(mm_player_streaming_t* streamer, BufferType type, gdouble low_percent, gdouble high_percent_byte, gdouble high_percent_time);
51 static void streaming_set_queue2_queue_type (mm_player_streaming_t* streamer, gboolean use_file, gchar * file_path, guint64 content_size);
52 static void streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gdouble buffering_time);
53 static void streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position);
54 static void streaming_get_current_bitrate_info( mm_player_streaming_t* streamer,
55 GstMessage *buffering_msg,
56 streaming_content_info_t content_info,
57 streaming_bitrate_info_t* bitrate_info);
59 streaming_handle_fixed_buffering_mode( mm_player_streaming_t* streamer,
61 gdouble fixed_buffering_time,
62 streaming_buffer_info_t* buffer_info);
64 streaming_handle_adaptive_buffering_mode( mm_player_streaming_t* streamer,
65 streaming_content_info_t content_info,
66 streaming_bitrate_info_t bitrate_info,
67 streaming_buffer_info_t* buffer_info,
68 gint expected_play_time);
70 streaming_update_buffer_setting ( mm_player_streaming_t* streamer,
71 GstMessage *buffering_msg,
76 mm_player_streaming_t *
77 __mm_player_streaming_create (void)
79 mm_player_streaming_t *streamer = NULL;
83 streamer = (mm_player_streaming_t *) malloc (sizeof (mm_player_streaming_t));
86 debug_error ("fail to create streaming player handle..\n");
90 memset(streamer, 0, sizeof(mm_player_streaming_t));
98 streaming_buffer_initialize (streaming_buffer_t* buffer_handle, gboolean buffer_init)
101 buffer_handle->buffer = NULL;
103 buffer_handle->buffering_bytes = DEFAULT_BUFFER_SIZE_BYTES;
104 buffer_handle->buffering_time = DEFAULT_BUFFERING_TIME;
105 buffer_handle->buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
106 buffer_handle->buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
107 buffer_handle->is_live = FALSE;
111 void __mm_player_streaming_initialize (mm_player_streaming_t* streamer)
115 streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT; // multi-queue
117 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), TRUE);
118 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), TRUE);
120 streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
121 streamer->buffering_req.is_pre_buffering = FALSE;
122 streamer->buffering_req.initial_second = 0;
123 streamer->buffering_req.runtime_second = 0;
125 streamer->default_val.buffering_monitor = FALSE;
126 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
128 streamer->buffer_avg_bitrate = 0;
129 streamer->buffer_max_bitrate = 0;
130 streamer->need_update = FALSE;
131 streamer->need_sync = FALSE;
133 streamer->is_buffering = FALSE;
134 streamer->is_buffering_done = FALSE;
135 streamer->buffering_percent = -1;
141 void __mm_player_streaming_deinitialize (mm_player_streaming_t* streamer)
144 return_if_fail(streamer);
146 streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT; // multi-queue
148 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), FALSE);
149 streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), FALSE);
151 streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
152 streamer->buffering_req.is_pre_buffering = FALSE;
153 streamer->buffering_req.initial_second = 0;
154 streamer->buffering_req.runtime_second = 0;
156 streamer->default_val.buffering_monitor = FALSE;
157 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
159 streamer->buffer_avg_bitrate = 0;
160 streamer->buffer_max_bitrate = 0;
161 streamer->need_update = FALSE;
162 streamer->need_sync = FALSE;
164 streamer->is_buffering = FALSE;
165 streamer->is_buffering_done = FALSE;
166 streamer->buffering_percent = -1;
172 void __mm_player_streaming_destroy (mm_player_streaming_t* streamer)
187 void __mm_player_streaming_set_content_bitrate(mm_player_streaming_t* streamer, guint max_bitrate, guint avg_bitrate)
191 return_if_fail(streamer);
193 /* Note : Update buffering criterion bytes
194 * 1. maximum bitrate is considered first.
195 * 2. average bitrage * 3 is next.
196 * 3. if there are no updated bitrate, use default buffering limit.
198 if (max_bitrate > 0 && streamer->buffer_max_bitrate != max_bitrate)
200 debug_log("set maximum bitrate(%dbps).\n", max_bitrate);
201 streamer->buffer_max_bitrate = max_bitrate;
202 if (streamer->buffering_req.is_pre_buffering == FALSE)
204 streamer->need_update = TRUE;
208 debug_log("pre-buffering...\n");
210 if (IS_MUXED_BUFFERING_MODE(streamer))
211 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
215 if (avg_bitrate > 0 && streamer->buffer_avg_bitrate != avg_bitrate)
217 debug_log("set averate bitrate(%dbps).\n", avg_bitrate);
218 streamer->buffer_avg_bitrate = avg_bitrate;
220 if (streamer->buffering_req.is_pre_buffering == FALSE)
222 streamer->need_update = TRUE;
226 debug_log("pre-buffering...\n");
228 if (IS_MUXED_BUFFERING_MODE(streamer))
229 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
238 streaming_check_buffer_percent(gdouble in_low, gdouble in_high, gdouble *out_low, gdouble *out_high)
240 gdouble buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
241 gdouble buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
245 return_if_fail(out_low && out_high);
247 if (in_low <= MIN_BUFFER_PERCENT || in_low >= MAX_BUFFER_PERCENT)
249 debug_warning("buffer low percent is out of range. use defaut value.");
253 buffer_low_percent = in_low;
256 if (in_high <= MIN_BUFFER_PERCENT || in_high >= MAX_BUFFER_PERCENT)
258 debug_warning("buffer high percent is out of range. use defaut value.");
262 buffer_high_percent = in_high;
265 if (buffer_high_percent <= buffer_low_percent)
266 buffer_high_percent = buffer_low_percent + 1.0;
268 debug_log("set buffer percent to %2.3f ~ %2.3f.", buffer_low_percent, buffer_high_percent);
270 *out_low = buffer_low_percent;
271 *out_high = buffer_high_percent;
275 streaming_set_buffer_percent( mm_player_streaming_t* streamer,
278 gdouble high_percent_byte,
279 gdouble high_percent_time)
281 gdouble confirmed_low = DEFAULT_BUFFER_LOW_PERCENT;
282 gdouble confirmed_high = DEFAULT_BUFFER_HIGH_PERCENT;
283 gdouble high_percent = 0.0;
285 streaming_buffer_t* buffer_handle = NULL;
286 gchar* factory_name = NULL;
289 return_if_fail(streamer);
290 return_if_fail(type < BUFFER_TYPE_MAX);
292 buffer_handle = &(streamer->buffer_handle[type]);
293 if (!(buffer_handle && buffer_handle->buffer))
295 debug_error("buffer_handle->buffer is NULL!");
299 factory_name = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(buffer_handle->buffer));
303 debug_error("Fail to get factory name!");
307 if (type == BUFFER_TYPE_MUXED)
308 high_percent = high_percent_byte;
310 high_percent = MAX(high_percent_time, high_percent_byte);
312 streaming_check_buffer_percent(low_percent, high_percent, &confirmed_low, &confirmed_high);
314 // if use-buffering is disabled, this settings do not have any meaning.
315 debug_log("target buffer elem : %s (%2.3f ~ %2.3f)",
316 GST_ELEMENT_NAME(buffer_handle->buffer), confirmed_low, confirmed_high);
318 if ((confirmed_low == DEFAULT_BUFFER_LOW_PERCENT) ||
319 (buffer_handle->buffer_low_percent != confirmed_low))
321 if (g_strrstr(factory_name, "queue2"))
322 g_object_set (G_OBJECT(buffer_handle->buffer), "low-percent", confirmed_low, NULL);
324 g_object_set (G_OBJECT(buffer_handle->buffer), "low-percent", (gint)confirmed_low, NULL);
327 if ((confirmed_high == DEFAULT_BUFFER_HIGH_PERCENT) ||
328 (buffer_handle->buffer_high_percent != confirmed_high))
330 if (g_strrstr(factory_name, "queue2"))
331 g_object_set (G_OBJECT(buffer_handle->buffer), "high-percent", confirmed_high, NULL);
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, gboolean use_file, gchar * file_path, guint64 content_size)
346 streaming_buffer_t* buffer_handle = NULL;
347 guint64 storage_available_size = 0L; //bytes
348 guint64 file_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 return_if_fail(streamer);
355 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 debug_error("buffer_handle->buffer is NULL!");
365 factory_name = GST_PLUGIN_FEATURE_NAME(gst_element_get_factory(buffer_handle->buffer));
369 debug_error("Fail to get factory name!");
373 debug_log("target buffer elem : %s", GST_ELEMENT_NAME(buffer_handle->buffer));
375 if (!g_strrstr(factory_name, "queue2"))
377 debug_log("only queue2 can use file buffer. not decodebin2 or multiQ\n");
381 if ((!use_file) || (!g_strrstr(factory_name, "queue2")))
383 debug_log("use memory 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 debug_log("[Queue2] use file for buffering. streaming is played on pull-based. \n");
392 if (!file_path || strlen(file_path) <= 0)
393 file_path = g_strdup(DEFAULT_FILE_BUFFER_PATH);
395 g_snprintf(file_buffer_name, MM_MAX_URL_LEN, "%s/XXXXXX", file_path);
396 secure_debug_log("[Queue2] the buffering file name is %s.\n", file_buffer_name);
398 if (statfs((const char *)file_path, &buf) < 0)
400 debug_warning ("[Queue2] fail to get availabe storage capacity. just use file buffer.\n");
401 file_buffer_size = 0L;
405 storage_available_size = (guint64)buf.f_bavail * (guint64)buf.f_bsize; //bytes
407 debug_log ("[Queue2] the number of available blocks : %"G_GUINT64_FORMAT
408 ", the block size is %"G_GUINT64_FORMAT".\n",
409 (guint64)buf.f_bavail, (guint64)buf.f_bsize);
411 debug_log ("[Queue2] calculated availabe storage size is %"
412 G_GUINT64_FORMAT" Bytes.\n", storage_available_size);
414 if (content_size <= 0 || content_size >= storage_available_size)
415 file_buffer_size = storage_available_size;
417 file_buffer_size = 0L;
420 if (file_buffer_size>0)
421 debug_log("[Queue2] use file ring buffer for buffering.");
423 g_object_set (G_OBJECT(buffer_handle->buffer), "temp-template", file_buffer_name, NULL);
424 g_object_set (G_OBJECT(buffer_handle->buffer), "file-buffer-max-size", file_buffer_size, NULL);
431 streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gdouble buffering_time)
433 streaming_buffer_t* buffer_handle = NULL;
437 return_if_fail(streamer);
438 return_if_fail(buffering_bytes > 0);
439 return_if_fail(type < BUFFER_TYPE_MAX);
441 buffer_handle = &(streamer->buffer_handle[type]);
443 if (buffer_handle && buffer_handle->buffer)
445 if (g_strrstr(GST_ELEMENT_NAME(buffer_handle->buffer), "multiqueue"))
447 if (buffering_time <= 0)
448 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
450 g_object_set (G_OBJECT(buffer_handle->buffer),
451 "max-size-bytes", MAX_DECODEBIN_BUFFER_BYTES, // fixed
452 "max-size-time", ((guint)ceil(buffering_time) * GST_SECOND),
453 "max-size-buffers", 0, NULL); // disable
455 buffer_handle->buffering_time = buffering_time;
456 buffer_handle->buffering_bytes = MAX_DECODEBIN_BUFFER_BYTES;
458 debug_log("[New][MQ] max-size-time : %f", buffering_time);
462 if (buffer_handle->is_live)
464 g_object_set (G_OBJECT(buffer_handle->buffer),
465 "max-size-bytes", buffering_bytes,
466 "max-size-time", (guint64)(buffering_time*GST_SECOND),
467 "max-size-buffers", 0,
468 "use-rate-estimate", TRUE, NULL);
472 g_object_set (G_OBJECT(buffer_handle->buffer),
473 "max-size-bytes", buffering_bytes,
474 "max-size-time", (guint64)0,
475 "max-size-buffers", 0,
476 "use-rate-estimate", FALSE, NULL);
479 buffer_handle->buffering_bytes = buffering_bytes;
480 buffer_handle->buffering_time = buffering_time;
482 debug_log("[New][Q2] max-size-bytes : %d", buffering_bytes);
490 void __mm_player_streaming_set_queue2( mm_player_streaming_t* streamer,
492 gboolean use_buffering,
493 guint buffering_bytes,
494 gdouble buffering_time,
496 gdouble high_percent,
499 guint64 content_size)
502 return_if_fail(streamer);
506 debug_log("USE-BUFFERING : %s", (use_buffering)?"OOO":"XXX");
508 streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer = buffer;
512 streamer->streaming_buffer_type = BUFFER_TYPE_MUXED;
514 if (content_size > 0)
516 if (streamer->buffering_req.initial_second > 0)
517 streamer->buffering_req.is_pre_buffering = TRUE;
519 streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
523 debug_log("live streaming without mq");
525 streamer->buffer_handle[BUFFER_TYPE_MUXED].is_live = TRUE;
526 streamer->buffering_req.initial_second = buffering_time = DEFAULT_BUFFERING_TIME;
530 g_object_set ( G_OBJECT (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL );
533 streaming_set_buffer_size (streamer, BUFFER_TYPE_MUXED, buffering_bytes, buffering_time);
534 streaming_set_buffer_percent (streamer, BUFFER_TYPE_MUXED, low_percent, high_percent, 0);
535 streaming_set_queue2_queue_type (streamer, use_file, file_path, content_size);
541 void __mm_player_streaming_sync_property(mm_player_streaming_t* streamer, GstElement* decodebin)
543 streaming_buffer_t* buffer_handle = NULL;
547 return_if_fail ( streamer && decodebin );
549 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
551 if ((streamer->need_sync) && (streamer->streaming_buffer_type == BUFFER_TYPE_DEMUXED))
553 g_object_set (G_OBJECT(decodebin),
554 "max-size-bytes", buffer_handle->buffering_bytes,
555 "max-size-time", (guint64)(ceil(buffer_handle->buffering_time) * GST_SECOND),
556 "low-percent", (gint)buffer_handle->buffer_low_percent,
557 "high-percent", (gint)buffer_handle->buffer_high_percent, NULL);
561 streamer->need_sync = FALSE;
564 void __mm_player_streaming_set_multiqueue( mm_player_streaming_t* streamer,
566 gboolean use_buffering,
567 guint buffering_bytes,
568 gdouble buffering_time,
570 gdouble high_percent)
572 streaming_buffer_t* buffer_handle = NULL;
573 gdouble pre_buffering_time = 0.0;
576 return_if_fail(streamer);
578 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
579 pre_buffering_time = (gdouble)streamer->buffering_req.initial_second;
583 debug_log("USE-BUFFERING : %s", (use_buffering)?"OOO":"XXX");
585 buffer_handle->buffer = buffer;
589 streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
591 // during prebuffering by requirement, buffer setting should not be changed.
592 if (pre_buffering_time > 0)
593 streamer->buffering_req.is_pre_buffering = TRUE;
596 g_object_set ( G_OBJECT (buffer_handle->buffer), "use-buffering", use_buffering, NULL );
599 debug_log ("time req: %2.2f, default: %2.2f\n", pre_buffering_time, buffering_time);
601 if (pre_buffering_time <= 0.0)
603 pre_buffering_time = DEFAULT_PLAYING_TIME;
604 streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
607 high_percent = (pre_buffering_time * 100) / MAX_DECODEBIN_BUFFER_TIME;
608 debug_log ("high_percent : per %2.3f %%\n", high_percent);
610 streaming_set_buffer_size (streamer, BUFFER_TYPE_DEMUXED, MAX_DECODEBIN_BUFFER_BYTES, MAX_DECODEBIN_BUFFER_TIME);
611 streaming_set_buffer_percent (streamer, BUFFER_TYPE_DEMUXED, low_percent, 0, high_percent);
613 streamer->need_sync = TRUE;
620 streaming_get_current_bitrate_info( mm_player_streaming_t* streamer,
621 GstMessage *buffering_msg,
622 streaming_content_info_t content_info,
623 streaming_bitrate_info_t* bitrate_info)
626 GstQuery *query = NULL;
627 GstBufferingMode mode = GST_BUFFERING_STREAM;
630 gint64 buffering_left = -1;
632 guint buffer_criteria = 0;
633 guint estimated_content_bitrate = 0;
635 gdouble buffer_buffering_time = DEFAULT_BUFFERING_TIME;
639 return_if_fail(streamer);
640 return_if_fail(bitrate_info);
642 if ((buffering_msg == NULL) ||
643 ((streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer != NULL) &&
644 (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer != NULL) &&
645 (buffering_msg->src == (GstObject *)streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer)))
647 query = gst_query_new_buffering (GST_FORMAT_PERCENT);
649 if (gst_element_query ((streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), query))
651 gst_query_parse_buffering_stats (query, &mode, &in_rate, &out_rate, &buffering_left);
654 gst_query_unref (query);
658 gst_message_parse_buffering_stats (buffering_msg, &mode, &in_rate, &out_rate, &buffering_left);
661 debug_log ("Streaming Info : in %d, out %d, left %lld\n", in_rate, out_rate, buffering_left);
663 if ((content_info.content_size > 0) && (content_info.duration > 0) && ((content_info.duration/GST_SECOND) > 0))
664 estimated_content_bitrate = GET_BIT_FROM_BYTE((guint)(content_info.content_size / (content_info.duration/GST_SECOND)));
666 if (streamer->buffer_max_bitrate > 0)
668 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, streamer->buffer_avg_bitrate);
669 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, estimated_content_bitrate);
671 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate);
673 if (streamer->buffer_avg_bitrate > estimated_content_bitrate)
674 out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate);
675 else if (estimated_content_bitrate != 0)
676 out_rate = GET_BYTE_FROM_BIT(estimated_content_bitrate);
678 out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate/3);
680 debug_log ("(max)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
682 else if (streamer->buffer_avg_bitrate > 0)
684 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3);
685 out_rate = GET_BYTE_FROM_BIT(MAX(streamer->buffer_avg_bitrate,estimated_content_bitrate));
687 debug_log ("(avg)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
691 debug_warning ("There is no content bitrate information\n");
694 if ((in_rate > 0) && (out_rate > 0))
695 buffer_buffering_time = (gdouble)out_rate / (gdouble)in_rate;
696 else if ((in_rate <= 0) && (out_rate > 0))
697 buffer_buffering_time = MAX_BUFFERING_TIME;
699 buffer_buffering_time = DEFAULT_BUFFERING_TIME;
701 (*bitrate_info).byte_in_rate = in_rate;
702 (*bitrate_info).byte_out_rate = out_rate;
703 (*bitrate_info).time_rate = buffer_buffering_time;
704 (*bitrate_info).buffer_criteria = buffer_criteria;
708 streaming_handle_fixed_buffering_mode( mm_player_streaming_t* streamer,
710 gdouble fixed_buffering_time,
711 streaming_buffer_info_t* buffer_info)
713 streaming_buffer_t* buffer_handle = NULL;
715 guint buffering_bytes = 0;
716 gdouble buffering_time = 0.0;
717 gdouble per_byte = 0.0;
718 gdouble per_time = 0.0;
720 return_if_fail(streamer);
721 return_if_fail(buffer_info);
723 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
724 buffering_time = fixed_buffering_time;
726 debug_log ("[IN] MM_PLAYER_BUFFERING_MODE_FIXED (%2.2f sec), out:%d\n", buffering_time, byte_out_rate);
728 if ((buffering_time > 0) && (byte_out_rate > 0))
730 buffering_bytes = GET_NEW_BUFFERING_BYTE(byte_out_rate * buffering_time);
734 if (buffering_time <= 0)
735 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
737 debug_warning ("content bitrate is not updated yet.\n");
738 buffering_bytes = GET_CURRENT_BUFFERING_BYTE(buffer_handle);
741 GET_PERCENT(buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
742 GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
744 debug_log ("[NEW] bytes %d, time %f, per_byte %f, per_time %f\n",
745 buffering_bytes, buffering_time, per_byte, per_time);
747 (*buffer_info).buffering_bytes = buffering_bytes;
748 (*buffer_info).buffering_time = buffering_time;
749 (*buffer_info).percent_byte = per_byte;
750 (*buffer_info).percent_time = per_time;
754 streaming_handle_adaptive_buffering_mode( mm_player_streaming_t* streamer,
755 streaming_content_info_t content_info,
756 streaming_bitrate_info_t bitrate_info,
757 streaming_buffer_info_t* buffer_info,
758 gint expected_play_time)
760 streaming_buffer_t* buffer_handle = NULL;
762 gint buffering_bytes = 0;
763 gint adj_buffering_bytes = 0;
764 gdouble buffer_buffering_time = 0.0;
765 gdouble per_byte = 0.0;
766 gdouble per_time = 0.0;
767 gdouble portion = 0.0;
768 gdouble default_buffering_time = 0.0;
770 return_if_fail(streamer);
771 return_if_fail(buffer_info);
773 debug_log ("[IN] MM_PLAYER_BUFFERING_MODE_SLINK (pos %lld, dur %lld, size %lld), in/out:%d/%d, buffer_criteria:%d, time_rate:%f, need:%d sec\n",
774 content_info.position, content_info.duration, content_info.content_size,
775 bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
776 bitrate_info.buffer_criteria, bitrate_info.time_rate, expected_play_time);
778 if (((expected_play_time == TO_THE_END) && (content_info.position <= 0)) ||
779 (content_info.duration <= 0) ||
780 (content_info.content_size <= 0))
782 debug_warning ("Impossible to update buffer setting!! keep previous setting!\n");
786 if ((bitrate_info.byte_out_rate <= 0) || (bitrate_info.buffer_criteria == 0))
788 debug_warning ("Don't need to change buffer setting(or impossible)!! keep previous setting!\n");
792 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
794 if (bitrate_info.byte_in_rate < bitrate_info.byte_out_rate)
796 if (expected_play_time != TO_THE_END)
797 portion = (double)(expected_play_time * GST_SECOND) / (double)content_info.duration;
799 portion = (1 - (double)content_info.position/(double)content_info.duration);
801 buffering_bytes = GET_NEW_BUFFERING_BYTE(((double)content_info.content_size * portion) \
802 * (1 - (double)bitrate_info.byte_in_rate/(double)bitrate_info.byte_out_rate));
806 // buffering_bytes will be set as streamer->default_val.buffering_time
807 debug_warning ("*Warning : receiving rate(%d) > avg content bitrate(%d)!\n", bitrate_info.byte_in_rate, bitrate_info.byte_out_rate);
808 debug_warning ("*Warning : There is no reason to buffering.!\n");
809 debug_warning ("*Warning : in-rate or content bitrate has reported wrong value.!\n");
812 if (buffering_bytes > 0)
813 buffer_buffering_time = (gdouble)buffering_bytes / (gdouble)bitrate_info.byte_out_rate;
815 if (content_info.position <= 0)
817 /* if the buffer is filled under 50%, MSL use the original default buffering time.
818 if not, MSL use just 2 sec as a default buffering time. (to reduce initial buffering time) */
819 default_buffering_time = streamer->default_val.buffering_time - (streamer->buffering_percent/50);
823 default_buffering_time = streamer->default_val.buffering_time;
826 if (buffer_buffering_time < default_buffering_time)
828 debug_log ("[NEW- adj] buffering time : %2.2f --> %2.2f\n", buffer_buffering_time, default_buffering_time);
829 debug_log ("[NEW- adj] buffering bytes : %d or %d or %d\n",
831 (gint)(bitrate_info.byte_out_rate * buffer_buffering_time),
832 (gint)(bitrate_info.buffer_criteria * buffer_buffering_time));
834 if (content_info.position > 0)
836 // start monitoring the abmormal state
837 streamer->default_val.buffering_monitor = TRUE;
840 buffer_buffering_time = default_buffering_time;
841 adj_buffering_bytes = GET_NEW_BUFFERING_BYTE(bitrate_info.byte_out_rate * (gint)ceil(buffer_buffering_time));
842 buffering_bytes = MAX(buffering_bytes, adj_buffering_bytes);
845 GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
846 GET_PERCENT(buffer_buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
848 debug_log ("[NEW- last][buffering_monitor == %s] bytes %d, time %f, per_byte %f, per_time %f\n",
849 (streamer->default_val.buffering_monitor)?"OO":"XX",
850 buffering_bytes, buffer_buffering_time, per_byte, per_time);
852 (*buffer_info).buffering_bytes = buffering_bytes;
853 (*buffer_info).buffering_time = buffer_buffering_time;
854 (*buffer_info).percent_byte = per_byte;
855 (*buffer_info).percent_time = per_time;
860 streaming_update_buffer_setting ( mm_player_streaming_t* streamer,
861 GstMessage *buffering_msg, // can be null
862 guint64 content_size,
866 streaming_buffer_t* buffer_handle = NULL;
867 MMPlayerBufferingMode buffering_mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
869 streaming_buffer_info_t buffer_info;
870 streaming_content_info_t content_info;
871 streaming_bitrate_info_t bitrate_info;
873 gdouble low_percent = 0.0;
877 return_if_fail ( streamer );
879 memset(&buffer_info, 0x00, sizeof(streaming_buffer_info_t));
880 memset(&content_info, 0x00, sizeof(streaming_content_info_t));
881 memset(&bitrate_info, 0x00, sizeof(streaming_bitrate_info_t));
883 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
885 if (streamer->buffering_req.is_pre_buffering == TRUE)
886 buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
888 buffering_mode = streamer->buffering_req.mode;
890 buffer_info.buffering_bytes = buffer_handle->buffering_bytes;
891 buffer_info.buffering_time = buffer_handle->buffering_time;
892 buffer_info.percent_byte = buffer_handle->buffer_high_percent;
893 buffer_info.percent_time = buffer_handle->buffer_high_percent;
895 content_info.position = position;
896 content_info.duration = duration;
897 content_info.content_size = content_size;
899 streaming_get_current_bitrate_info(streamer, buffering_msg, content_info, &bitrate_info);
901 debug_log ("buffering mode %d, new info in_r:%d, out_r:%d, cb:%d, bt:%f\n",
902 buffering_mode, bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
903 bitrate_info.buffer_criteria, bitrate_info.time_rate);
905 /* calculate buffer low/high percent */
906 low_percent = DEFAULT_BUFFER_LOW_PERCENT;
908 /********************
910 ********************/
912 if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED)
914 gdouble buffering_time = 0.0;
916 if (streamer->buffering_req.is_pre_buffering == TRUE)
917 buffering_time = (gdouble)streamer->buffering_req.initial_second;
919 buffering_time = (gdouble)streamer->buffering_req.runtime_second;
921 streaming_handle_fixed_buffering_mode(streamer, bitrate_info.byte_out_rate, buffering_time, &buffer_info);
924 /***********************************
925 * (2) once mode for samsung link *
926 ***********************************/
927 else if (buffering_mode == MM_PLAYER_BUFFERING_MODE_SLINK)
929 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, TO_THE_END);
932 /*********************************
933 * (3) adaptive mode (default) *
934 *********************************/
937 gint expected_play_time = DEFAULT_PLAYING_TIME;
939 if (streamer->buffering_req.runtime_second > 0)
941 expected_play_time = streamer->buffering_req.runtime_second;
943 else if ((position == 0) && (streamer->is_buffering))
945 expected_play_time = streamer->buffering_req.initial_second;
948 if (expected_play_time <= 0)
949 expected_play_time = DEFAULT_PLAYING_TIME;
951 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, expected_play_time);
953 if (IS_MUXED_BUFFERING_MODE(streamer)) // even if new byte size is smaller than the previous one, time need to be updated.
954 buffer_handle->buffering_time = buffer_info.buffering_time;
957 debug_log ("new buffer size [%d -> %d bytes] / [%2.2f -> %2.2f sec] / %s \n",
958 GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_info.buffering_bytes,
959 GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_info.buffering_time,
960 (IS_MUXED_BUFFERING_MODE(streamer))?"MUXED":((IS_DEMUXED_BUFFERING_MODE(streamer))?"DEMUXED":"----"));
962 // queue2 : bytes, multiqueue : time
963 if (((GET_CURRENT_BUFFERING_BYTE(buffer_handle) < buffer_info.buffering_bytes) && IS_MUXED_BUFFERING_MODE(streamer)) ||
964 ((GET_CURRENT_BUFFERING_TIME(buffer_handle) < buffer_info.buffering_time) && IS_DEMUXED_BUFFERING_MODE(streamer)))
966 if (duration > 0 && position > 0)
968 gdouble buffering_time_limit = (gdouble)(duration - position)/GST_SECOND;
970 if (buffer_info.buffering_time > buffering_time_limit)
971 buffer_info.buffering_time = buffering_time_limit;
974 streaming_set_buffer_size(streamer, streamer->streaming_buffer_type, buffer_info.buffering_bytes, buffer_info.buffering_time);
977 streaming_set_buffer_percent(streamer, streamer->streaming_buffer_type, low_percent, buffer_info.percent_byte, buffer_info.percent_time);
979 debug_log("[FINAL] buffer setting : size %d, time %f, per %f\n",
980 GET_CURRENT_BUFFERING_BYTE(buffer_handle),
981 GET_CURRENT_BUFFERING_TIME(buffer_handle),
982 buffer_handle->buffer_high_percent);
984 streamer->need_sync = TRUE;
988 streaming_adjust_min_threshold(mm_player_streaming_t* streamer, gint64 position)
990 #define DEFAULT_TIME_PAD 1 // sec
991 gint playing_time = 0;
995 return_if_fail(streamer);
997 playing_time = (gint)((position - streamer->default_val.prev_pos) / GST_SECOND);
999 debug_log ("[GRACE_NEW] buffering monitor = %s\n", (streamer->default_val.buffering_monitor)?"ON":"OFF");
1000 debug_log ("[GRACE_NEW] playing_time ( %d sec) = %lld - %lld \n", playing_time, position, streamer->default_val.prev_pos);
1001 debug_log ("[GRACE_NEW] default time : %2.3f, prev buffering t : %2.3f\n",
1002 streamer->default_val.buffering_time, streamer->buffer_handle[streamer->streaming_buffer_type].buffering_time);
1004 if ((streamer->default_val.buffering_monitor) && (playing_time <= (gint)streamer->default_val.buffering_time))
1007 time_gap = (gint)(streamer->default_val.buffering_time - DEFAULT_BUFFERING_TIME);
1009 time_gap = DEFAULT_TIME_PAD;
1011 streamer->default_val.buffering_time += time_gap*2;
1012 streamer->default_val.buffering_time = MIN(streamer->default_val.buffering_time, MAX_BUFFERING_TIME);
1016 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
1019 debug_log ("[GRACE_NEW] new default min value %2.3f \n", streamer->default_val.buffering_time);
1021 streamer->default_val.buffering_monitor = FALSE;
1022 streamer->default_val.prev_pos = position;
1026 streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position)
1028 gint buffer_percent = 0;
1029 gboolean increased_per = TRUE;
1033 return_if_fail(streamer);
1034 return_if_fail(buffering_msg);
1036 /* update when buffering has started. */
1037 if ( !streamer->is_buffering )
1039 debug_log ("buffering has started.\n");
1040 streamer->is_buffering = TRUE;
1041 streamer->is_buffering_done = FALSE;
1042 streamer->buffering_percent = -1;
1044 if (!streamer->buffering_req.is_pre_buffering)
1046 streamer->need_update = TRUE;
1047 streaming_adjust_min_threshold(streamer, position);
1051 /* update buffer percent */
1052 gst_message_parse_buffering (buffering_msg, &buffer_percent);
1054 if (streamer->buffering_percent < buffer_percent)
1056 debug_log ("[%s] buffering %d%%....\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
1057 streamer->buffering_percent = buffer_percent;
1061 increased_per = FALSE;
1064 if ((streamer->buffering_percent == MAX_BUFFER_PERCENT) || (streamer->is_buffering_done == TRUE))
1066 debug_log ("buffering had done. finished!!\n");
1067 streamer->is_buffering = FALSE;
1068 streamer->buffering_req.is_pre_buffering = FALSE;
1069 if (streamer->buffering_percent == MAX_BUFFER_PERCENT)
1070 streamer->is_buffering_done = FALSE;
1072 streamer->buffering_percent = MAX_BUFFER_PERCENT;
1076 // need to update periodically in case of slink mode
1077 if ((increased_per == TRUE) &&
1078 (buffer_percent%10 == 0) &&
1079 (streamer->buffering_req.mode == MM_PLAYER_BUFFERING_MODE_SLINK) &&
1080 (streamer->buffering_req.is_pre_buffering == FALSE))
1082 debug_log ("Update buffer setting to reflect data receiving rate (slink mode)\n");
1083 streamer->need_update = TRUE;
1088 void __mm_player_streaming_buffering( mm_player_streaming_t* streamer,
1089 GstMessage *buffering_msg,
1090 guint64 content_size,
1096 return_if_fail ( streamer );
1097 return_if_fail ( buffering_msg );
1098 return_if_fail ( GST_IS_MESSAGE ( buffering_msg ) );
1099 return_if_fail ( (GST_MESSAGE_TYPE ( buffering_msg ) == GST_MESSAGE_BUFFERING) );
1103 if (position > (gint64)(streamer->buffering_req.initial_second * GST_SECOND))
1104 streamer->buffering_req.is_pre_buffering = FALSE;
1106 streaming_update_buffering_status(streamer, buffering_msg, position);
1108 if (!streamer->need_update)
1110 //debug_log ("don't need to update buffering stats during buffering.\n");
1114 streamer->need_update = FALSE;
1117 streaming_update_buffer_setting (streamer, buffering_msg, content_size, position, duration);