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_OBJECT_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 g_object_set (G_OBJECT(buffer_handle->buffer), "low-percent", (gint)confirmed_low, NULL);
324 if ((confirmed_high == DEFAULT_BUFFER_HIGH_PERCENT) ||
325 (buffer_handle->buffer_high_percent != confirmed_high))
327 g_object_set (G_OBJECT(buffer_handle->buffer), "high-percent", (gint)confirmed_high, NULL);
330 buffer_handle->buffer_low_percent = confirmed_low;
331 buffer_handle->buffer_high_percent = confirmed_high;
338 streaming_set_queue2_queue_type (mm_player_streaming_t* streamer, gboolean use_file, gchar * file_path, guint64 content_size)
340 streaming_buffer_t* buffer_handle = NULL;
341 guint64 storage_available_size = 0L; //bytes
342 guint64 file_buffer_size = 0L; //bytes
343 gchar file_buffer_name[MM_MAX_URL_LEN] = {0};
344 struct statfs buf = {0};
345 gchar* factory_name = NULL;
348 return_if_fail(streamer);
349 return_if_fail(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer);
351 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_MUXED]);
353 if (!(buffer_handle && buffer_handle->buffer))
355 debug_error("buffer_handle->buffer is NULL!");
359 factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
363 debug_error("Fail to get factory name!");
367 debug_log("target buffer elem : %s", GST_ELEMENT_NAME(buffer_handle->buffer));
369 if (!g_strrstr(factory_name, "queue2"))
371 debug_log("only queue2 can use file buffer. not decodebin2 or multiQ\n");
375 if ((!use_file) || (!g_strrstr(factory_name, "queue2")))
377 debug_log("use memory for buffering. streaming is played on push-based. \n"
378 "buffering position would not be updated.\n"
379 "buffered data would be flushed after played.\n"
380 "seeking and getting duration could be failed due to file format.");
384 debug_log("[Queue2] use file for buffering. streaming is played on pull-based. \n");
386 if (!file_path || strlen(file_path) <= 0)
387 file_path = g_strdup(DEFAULT_FILE_BUFFER_PATH);
389 g_snprintf(file_buffer_name, MM_MAX_URL_LEN, "%s/XXXXXX", file_path);
390 secure_debug_log("[Queue2] the buffering file name is %s.\n", file_buffer_name);
392 if (statfs((const char *)file_path, &buf) < 0)
394 debug_warning ("[Queue2] fail to get availabe storage capacity. just use file buffer.\n");
395 file_buffer_size = 0L;
399 storage_available_size = (guint64)buf.f_bavail * (guint64)buf.f_bsize; //bytes
401 debug_log ("[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 debug_log ("[Queue2] calculated availabe storage size is %"
406 G_GUINT64_FORMAT" Bytes.\n", storage_available_size);
408 if (content_size <= 0 || content_size >= storage_available_size)
409 file_buffer_size = storage_available_size;
411 file_buffer_size = 0L;
414 if (file_buffer_size>0)
415 debug_log("[Queue2] use file ring buffer for buffering.");
417 g_object_set (G_OBJECT(buffer_handle->buffer), "temp-template", file_buffer_name, NULL);
418 g_object_set (G_OBJECT(buffer_handle->buffer), "file-buffer-max-size", file_buffer_size, NULL);
425 streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gdouble buffering_time)
427 streaming_buffer_t* buffer_handle = NULL;
431 return_if_fail(streamer);
432 return_if_fail(buffering_bytes > 0);
433 return_if_fail(type < BUFFER_TYPE_MAX);
435 buffer_handle = &(streamer->buffer_handle[type]);
437 if (buffer_handle && buffer_handle->buffer)
439 if (g_strrstr(GST_ELEMENT_NAME(buffer_handle->buffer), "multiqueue"))
441 if (buffering_time <= 0)
442 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
444 g_object_set (G_OBJECT(buffer_handle->buffer),
445 "max-size-bytes", MAX_DECODEBIN_BUFFER_BYTES, // fixed
446 "max-size-time", ((guint)ceil(buffering_time) * GST_SECOND),
447 "max-size-buffers", 0, NULL); // disable
449 buffer_handle->buffering_time = buffering_time;
450 buffer_handle->buffering_bytes = MAX_DECODEBIN_BUFFER_BYTES;
452 debug_log("[New][MQ] max-size-time : %f", buffering_time);
456 if (buffer_handle->is_live)
458 g_object_set (G_OBJECT(buffer_handle->buffer),
459 "max-size-bytes", buffering_bytes,
460 "max-size-time", (guint64)(buffering_time*GST_SECOND),
461 "max-size-buffers", 0,
462 "use-rate-estimate", TRUE, NULL);
466 g_object_set (G_OBJECT(buffer_handle->buffer),
467 "max-size-bytes", buffering_bytes,
468 "max-size-time", (guint64)0,
469 "max-size-buffers", 0,
470 "use-rate-estimate", FALSE, NULL);
473 buffer_handle->buffering_bytes = buffering_bytes;
474 buffer_handle->buffering_time = buffering_time;
476 debug_log("[New][Q2] max-size-bytes : %d", buffering_bytes);
484 void __mm_player_streaming_set_queue2( mm_player_streaming_t* streamer,
486 gboolean use_buffering,
487 guint buffering_bytes,
488 gdouble buffering_time,
490 gdouble high_percent,
493 guint64 content_size)
496 return_if_fail(streamer);
500 debug_log("USE-BUFFERING : %s", (use_buffering)?"OOO":"XXX");
502 streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer = buffer;
506 streamer->streaming_buffer_type = BUFFER_TYPE_MUXED;
508 if (content_size > 0)
510 if (streamer->buffering_req.initial_second > 0)
511 streamer->buffering_req.is_pre_buffering = TRUE;
513 streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
517 debug_log("live streaming without mq");
519 streamer->buffer_handle[BUFFER_TYPE_MUXED].is_live = TRUE;
520 streamer->buffering_req.initial_second = buffering_time = DEFAULT_BUFFERING_TIME;
524 g_object_set ( G_OBJECT (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL );
527 streaming_set_buffer_size (streamer, BUFFER_TYPE_MUXED, buffering_bytes, buffering_time);
528 streaming_set_buffer_percent (streamer, BUFFER_TYPE_MUXED, low_percent, high_percent, 0);
529 streaming_set_queue2_queue_type (streamer, use_file, file_path, content_size);
535 void __mm_player_streaming_sync_property(mm_player_streaming_t* streamer, GstElement* decodebin)
537 streaming_buffer_t* buffer_handle = NULL;
541 return_if_fail ( streamer && decodebin );
543 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
545 if ((streamer->need_sync) && (streamer->streaming_buffer_type == BUFFER_TYPE_DEMUXED))
547 g_object_set (G_OBJECT(decodebin),
548 "max-size-bytes", buffer_handle->buffering_bytes,
549 "max-size-time", (guint64)(ceil(buffer_handle->buffering_time) * GST_SECOND),
550 "low-percent", (gint)buffer_handle->buffer_low_percent,
551 "high-percent", (gint)buffer_handle->buffer_high_percent, NULL);
555 streamer->need_sync = FALSE;
558 void __mm_player_streaming_set_multiqueue( mm_player_streaming_t* streamer,
560 gboolean use_buffering,
561 guint buffering_bytes,
562 gdouble buffering_time,
564 gdouble high_percent)
566 streaming_buffer_t* buffer_handle = NULL;
567 gdouble pre_buffering_time = 0.0;
570 return_if_fail(streamer);
572 buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
573 pre_buffering_time = (gdouble)streamer->buffering_req.initial_second;
577 debug_log("USE-BUFFERING : %s", (use_buffering)?"OOO":"XXX");
579 buffer_handle->buffer = buffer;
583 streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
585 // during prebuffering by requirement, buffer setting should not be changed.
586 if (pre_buffering_time > 0)
587 streamer->buffering_req.is_pre_buffering = TRUE;
590 g_object_set ( G_OBJECT (buffer_handle->buffer), "use-buffering", use_buffering, NULL );
593 debug_log ("time req: %2.2f, default: %2.2f\n", pre_buffering_time, buffering_time);
595 if (pre_buffering_time <= 0.0)
597 pre_buffering_time = DEFAULT_PLAYING_TIME;
598 streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
601 high_percent = (pre_buffering_time * 100) / MAX_DECODEBIN_BUFFER_TIME;
602 debug_log ("high_percent : per %2.3f %%\n", high_percent);
604 streaming_set_buffer_size (streamer, BUFFER_TYPE_DEMUXED, MAX_DECODEBIN_BUFFER_BYTES, MAX_DECODEBIN_BUFFER_TIME);
605 streaming_set_buffer_percent (streamer, BUFFER_TYPE_DEMUXED, low_percent, 0, high_percent);
607 streamer->need_sync = TRUE;
614 streaming_get_current_bitrate_info( mm_player_streaming_t* streamer,
615 GstMessage *buffering_msg,
616 streaming_content_info_t content_info,
617 streaming_bitrate_info_t* bitrate_info)
620 GstQuery *query = NULL;
621 GstBufferingMode mode = GST_BUFFERING_STREAM;
624 gint64 buffering_left = -1;
626 guint buffer_criteria = 0;
627 guint estimated_content_bitrate = 0;
629 gdouble buffer_buffering_time = DEFAULT_BUFFERING_TIME;
633 return_if_fail(streamer);
634 return_if_fail(bitrate_info);
636 if ((buffering_msg == NULL) ||
637 ((streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer != NULL) &&
638 (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer != NULL) &&
639 (buffering_msg->src == (GstObject *)streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer)))
641 query = gst_query_new_buffering (GST_FORMAT_PERCENT);
643 if (gst_element_query ((streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), query))
645 gst_query_parse_buffering_stats (query, &mode, &in_rate, &out_rate, &buffering_left);
648 gst_query_unref (query);
652 gst_message_parse_buffering_stats (buffering_msg, &mode, &in_rate, &out_rate, &buffering_left);
655 debug_log ("Streaming Info : in %d, out %d, left %lld\n", in_rate, out_rate, buffering_left);
657 if ((content_info.content_size > 0) && (content_info.duration > 0) && ((content_info.duration/GST_SECOND) > 0))
658 estimated_content_bitrate = GET_BIT_FROM_BYTE((guint)(content_info.content_size / (content_info.duration/GST_SECOND)));
660 if (streamer->buffer_max_bitrate > 0)
662 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, streamer->buffer_avg_bitrate);
663 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, estimated_content_bitrate);
665 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate);
667 if (streamer->buffer_avg_bitrate > estimated_content_bitrate)
668 out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate);
669 else if (estimated_content_bitrate != 0)
670 out_rate = GET_BYTE_FROM_BIT(estimated_content_bitrate);
672 out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate/3);
674 debug_log ("(max)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
676 else if (streamer->buffer_avg_bitrate > 0)
678 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3);
679 out_rate = GET_BYTE_FROM_BIT(MAX(streamer->buffer_avg_bitrate,estimated_content_bitrate));
681 debug_log ("(avg)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
685 debug_warning ("There is no content bitrate information\n");
688 if ((in_rate > 0) && (out_rate > 0))
689 buffer_buffering_time = (gdouble)out_rate / (gdouble)in_rate;
690 else if ((in_rate <= 0) && (out_rate > 0))
691 buffer_buffering_time = MAX_BUFFERING_TIME;
693 buffer_buffering_time = DEFAULT_BUFFERING_TIME;
695 (*bitrate_info).byte_in_rate = in_rate;
696 (*bitrate_info).byte_out_rate = out_rate;
697 (*bitrate_info).time_rate = buffer_buffering_time;
698 (*bitrate_info).buffer_criteria = buffer_criteria;
702 streaming_handle_fixed_buffering_mode( mm_player_streaming_t* streamer,
704 gdouble fixed_buffering_time,
705 streaming_buffer_info_t* buffer_info)
707 streaming_buffer_t* buffer_handle = NULL;
709 guint buffering_bytes = 0;
710 gdouble buffering_time = 0.0;
711 gdouble per_byte = 0.0;
712 gdouble per_time = 0.0;
714 return_if_fail(streamer);
715 return_if_fail(buffer_info);
717 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
718 buffering_time = fixed_buffering_time;
720 debug_log ("[IN] MM_PLAYER_BUFFERING_MODE_FIXED (%2.2f sec), out:%d\n", buffering_time, byte_out_rate);
722 if ((buffering_time > 0) && (byte_out_rate > 0))
724 buffering_bytes = GET_NEW_BUFFERING_BYTE(byte_out_rate * buffering_time);
728 if (buffering_time <= 0)
729 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
731 debug_warning ("content bitrate is not updated yet.\n");
732 buffering_bytes = GET_CURRENT_BUFFERING_BYTE(buffer_handle);
735 GET_PERCENT(buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
736 GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
738 debug_log ("[NEW] bytes %d, time %f, per_byte %f, per_time %f\n",
739 buffering_bytes, buffering_time, per_byte, per_time);
741 (*buffer_info).buffering_bytes = buffering_bytes;
742 (*buffer_info).buffering_time = buffering_time;
743 (*buffer_info).percent_byte = per_byte;
744 (*buffer_info).percent_time = per_time;
748 streaming_handle_adaptive_buffering_mode( mm_player_streaming_t* streamer,
749 streaming_content_info_t content_info,
750 streaming_bitrate_info_t bitrate_info,
751 streaming_buffer_info_t* buffer_info,
752 gint expected_play_time)
754 streaming_buffer_t* buffer_handle = NULL;
756 gint buffering_bytes = 0;
757 gint adj_buffering_bytes = 0;
758 gdouble buffer_buffering_time = 0.0;
759 gdouble per_byte = 0.0;
760 gdouble per_time = 0.0;
761 gdouble portion = 0.0;
762 gdouble default_buffering_time = 0.0;
764 return_if_fail(streamer);
765 return_if_fail(buffer_info);
767 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",
768 content_info.position, content_info.duration, content_info.content_size,
769 bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
770 bitrate_info.buffer_criteria, bitrate_info.time_rate, expected_play_time);
772 if (((expected_play_time == TO_THE_END) && (content_info.position <= 0)) ||
773 (content_info.duration <= 0) ||
774 (content_info.content_size <= 0))
776 debug_warning ("Impossible to update buffer setting!! keep previous setting!\n");
780 if ((bitrate_info.byte_out_rate <= 0) || (bitrate_info.buffer_criteria == 0))
782 debug_warning ("Don't need to change buffer setting(or impossible)!! keep previous setting!\n");
786 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
788 if (bitrate_info.byte_in_rate < bitrate_info.byte_out_rate)
790 if (expected_play_time != TO_THE_END)
791 portion = (double)(expected_play_time * GST_SECOND) / (double)content_info.duration;
793 portion = (1 - (double)content_info.position/(double)content_info.duration);
795 buffering_bytes = GET_NEW_BUFFERING_BYTE(((double)content_info.content_size * portion) \
796 * (1 - (double)bitrate_info.byte_in_rate/(double)bitrate_info.byte_out_rate));
800 // buffering_bytes will be set as streamer->default_val.buffering_time
801 debug_warning ("*Warning : receiving rate(%d) > avg content bitrate(%d)!\n", bitrate_info.byte_in_rate, bitrate_info.byte_out_rate);
802 debug_warning ("*Warning : There is no reason to buffering.!\n");
803 debug_warning ("*Warning : in-rate or content bitrate has reported wrong value.!\n");
806 if (buffering_bytes > 0)
807 buffer_buffering_time = (gdouble)buffering_bytes / (gdouble)bitrate_info.byte_out_rate;
809 if (content_info.position <= 0)
811 /* if the buffer is filled under 50%, MSL use the original default buffering time.
812 if not, MSL use just 2 sec as a default buffering time. (to reduce initial buffering time) */
813 default_buffering_time = streamer->default_val.buffering_time - (streamer->buffering_percent/50);
817 default_buffering_time = streamer->default_val.buffering_time;
820 if (buffer_buffering_time < default_buffering_time)
822 debug_log ("[NEW- adj] buffering time : %2.2f --> %2.2f\n", buffer_buffering_time, default_buffering_time);
823 debug_log ("[NEW- adj] buffering bytes : %d or %d or %d\n",
825 (gint)(bitrate_info.byte_out_rate * buffer_buffering_time),
826 (gint)(bitrate_info.buffer_criteria * buffer_buffering_time));
828 if (content_info.position > 0)
830 // start monitoring the abmormal state
831 streamer->default_val.buffering_monitor = TRUE;
834 buffer_buffering_time = default_buffering_time;
835 adj_buffering_bytes = GET_NEW_BUFFERING_BYTE(bitrate_info.byte_out_rate * (gint)ceil(buffer_buffering_time));
836 buffering_bytes = MAX(buffering_bytes, adj_buffering_bytes);
839 GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
840 GET_PERCENT(buffer_buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
842 debug_log ("[NEW- last][buffering_monitor == %s] bytes %d, time %f, per_byte %f, per_time %f\n",
843 (streamer->default_val.buffering_monitor)?"OO":"XX",
844 buffering_bytes, buffer_buffering_time, per_byte, per_time);
846 (*buffer_info).buffering_bytes = buffering_bytes;
847 (*buffer_info).buffering_time = buffer_buffering_time;
848 (*buffer_info).percent_byte = per_byte;
849 (*buffer_info).percent_time = per_time;
854 streaming_update_buffer_setting ( mm_player_streaming_t* streamer,
855 GstMessage *buffering_msg, // can be null
856 guint64 content_size,
860 streaming_buffer_t* buffer_handle = NULL;
861 MMPlayerBufferingMode buffering_mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
863 streaming_buffer_info_t buffer_info;
864 streaming_content_info_t content_info;
865 streaming_bitrate_info_t bitrate_info;
867 gdouble low_percent = 0.0;
871 return_if_fail ( streamer );
873 memset(&buffer_info, 0x00, sizeof(streaming_buffer_info_t));
874 memset(&content_info, 0x00, sizeof(streaming_content_info_t));
875 memset(&bitrate_info, 0x00, sizeof(streaming_bitrate_info_t));
877 buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
879 if (streamer->buffering_req.is_pre_buffering == TRUE)
880 buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
882 buffering_mode = streamer->buffering_req.mode;
884 buffer_info.buffering_bytes = buffer_handle->buffering_bytes;
885 buffer_info.buffering_time = buffer_handle->buffering_time;
886 buffer_info.percent_byte = buffer_handle->buffer_high_percent;
887 buffer_info.percent_time = buffer_handle->buffer_high_percent;
889 content_info.position = position;
890 content_info.duration = duration;
891 content_info.content_size = content_size;
893 streaming_get_current_bitrate_info(streamer, buffering_msg, content_info, &bitrate_info);
895 debug_log ("buffering mode %d, new info in_r:%d, out_r:%d, cb:%d, bt:%f\n",
896 buffering_mode, bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
897 bitrate_info.buffer_criteria, bitrate_info.time_rate);
899 /* calculate buffer low/high percent */
900 low_percent = DEFAULT_BUFFER_LOW_PERCENT;
902 /********************
904 ********************/
906 if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED)
908 gdouble buffering_time = 0.0;
910 if (streamer->buffering_req.is_pre_buffering == TRUE)
911 buffering_time = (gdouble)streamer->buffering_req.initial_second;
913 buffering_time = (gdouble)streamer->buffering_req.runtime_second;
915 streaming_handle_fixed_buffering_mode(streamer, bitrate_info.byte_out_rate, buffering_time, &buffer_info);
918 /***********************************
919 * (2) once mode for samsung link *
920 ***********************************/
921 else if (buffering_mode == MM_PLAYER_BUFFERING_MODE_SLINK)
923 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, TO_THE_END);
926 /*********************************
927 * (3) adaptive mode (default) *
928 *********************************/
931 gint expected_play_time = DEFAULT_PLAYING_TIME;
933 if (streamer->buffering_req.runtime_second > 0)
935 expected_play_time = streamer->buffering_req.runtime_second;
937 else if ((position == 0) && (streamer->is_buffering))
939 expected_play_time = streamer->buffering_req.initial_second;
942 if (expected_play_time <= 0)
943 expected_play_time = DEFAULT_PLAYING_TIME;
945 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, expected_play_time);
947 if (IS_MUXED_BUFFERING_MODE(streamer)) // even if new byte size is smaller than the previous one, time need to be updated.
948 buffer_handle->buffering_time = buffer_info.buffering_time;
951 debug_log ("new buffer size [%d -> %d bytes] / [%2.2f -> %2.2f sec] / %s \n",
952 GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_info.buffering_bytes,
953 GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_info.buffering_time,
954 (IS_MUXED_BUFFERING_MODE(streamer))?"MUXED":((IS_DEMUXED_BUFFERING_MODE(streamer))?"DEMUXED":"----"));
956 // queue2 : bytes, multiqueue : time
957 if (((GET_CURRENT_BUFFERING_BYTE(buffer_handle) < buffer_info.buffering_bytes) && IS_MUXED_BUFFERING_MODE(streamer)) ||
958 ((GET_CURRENT_BUFFERING_TIME(buffer_handle) < buffer_info.buffering_time) && IS_DEMUXED_BUFFERING_MODE(streamer)))
960 if (duration > 0 && position > 0)
962 gdouble buffering_time_limit = (gdouble)(duration - position)/GST_SECOND;
964 if (buffer_info.buffering_time > buffering_time_limit)
965 buffer_info.buffering_time = buffering_time_limit;
968 streaming_set_buffer_size(streamer, streamer->streaming_buffer_type, buffer_info.buffering_bytes, buffer_info.buffering_time);
971 streaming_set_buffer_percent(streamer, streamer->streaming_buffer_type, low_percent, buffer_info.percent_byte, buffer_info.percent_time);
973 debug_log("[FINAL] buffer setting : size %d, time %f, per %f\n",
974 GET_CURRENT_BUFFERING_BYTE(buffer_handle),
975 GET_CURRENT_BUFFERING_TIME(buffer_handle),
976 buffer_handle->buffer_high_percent);
978 streamer->need_sync = TRUE;
982 streaming_adjust_min_threshold(mm_player_streaming_t* streamer, gint64 position)
984 #define DEFAULT_TIME_PAD 1 // sec
985 gint playing_time = 0;
989 return_if_fail(streamer);
991 playing_time = (gint)((position - streamer->default_val.prev_pos) / GST_SECOND);
993 debug_log ("[NEW] buffering monitor = %s\n", (streamer->default_val.buffering_monitor)?"ON":"OFF");
994 debug_log ("[NEW] playing_time ( %d sec) = %lld - %lld \n", playing_time, position, streamer->default_val.prev_pos);
995 debug_log ("[NEW] default time : %2.3f, prev buffering t : %2.3f\n",
996 streamer->default_val.buffering_time, streamer->buffer_handle[streamer->streaming_buffer_type].buffering_time);
998 if ((streamer->default_val.buffering_monitor) && (playing_time <= (gint)streamer->default_val.buffering_time))
1001 time_gap = (gint)(streamer->default_val.buffering_time - DEFAULT_BUFFERING_TIME);
1003 time_gap = DEFAULT_TIME_PAD;
1005 streamer->default_val.buffering_time += time_gap*2;
1006 streamer->default_val.buffering_time = MIN(streamer->default_val.buffering_time, MAX_BUFFERING_TIME);
1010 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
1013 debug_log ("[NEW] new default min value %2.3f \n", streamer->default_val.buffering_time);
1015 streamer->default_val.buffering_monitor = FALSE;
1016 streamer->default_val.prev_pos = position;
1020 streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position)
1022 gint buffer_percent = 0;
1023 gboolean increased_per = TRUE;
1027 return_if_fail(streamer);
1028 return_if_fail(buffering_msg);
1030 /* update when buffering has started. */
1031 if ( !streamer->is_buffering )
1033 debug_log ("buffering has started.\n");
1034 streamer->is_buffering = TRUE;
1035 streamer->is_buffering_done = FALSE;
1036 streamer->buffering_percent = -1;
1038 if (!streamer->buffering_req.is_pre_buffering)
1040 streamer->need_update = TRUE;
1041 streaming_adjust_min_threshold(streamer, position);
1045 /* update buffer percent */
1046 gst_message_parse_buffering (buffering_msg, &buffer_percent);
1048 if (streamer->buffering_percent < buffer_percent)
1050 debug_log ("[%s] buffering %d%%....\n", GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
1051 streamer->buffering_percent = buffer_percent;
1055 increased_per = FALSE;
1058 if ((streamer->buffering_percent == MAX_BUFFER_PERCENT) || (streamer->is_buffering_done == TRUE))
1060 debug_log ("buffering had done. finished!!\n");
1061 streamer->is_buffering = FALSE;
1062 streamer->buffering_req.is_pre_buffering = FALSE;
1063 if (streamer->buffering_percent == MAX_BUFFER_PERCENT)
1064 streamer->is_buffering_done = FALSE;
1066 streamer->buffering_percent = MAX_BUFFER_PERCENT;
1070 // need to update periodically in case of slink mode
1071 if ((increased_per == TRUE) &&
1072 (buffer_percent%10 == 0) &&
1073 (streamer->buffering_req.mode == MM_PLAYER_BUFFERING_MODE_SLINK) &&
1074 (streamer->buffering_req.is_pre_buffering == FALSE))
1076 debug_log ("Update buffer setting to reflect data receiving rate (slink mode)\n");
1077 streamer->need_update = TRUE;
1082 void __mm_player_streaming_buffering( mm_player_streaming_t* streamer,
1083 GstMessage *buffering_msg,
1084 guint64 content_size,
1090 return_if_fail ( streamer );
1091 return_if_fail ( buffering_msg );
1092 return_if_fail ( GST_IS_MESSAGE ( buffering_msg ) );
1093 return_if_fail ( (GST_MESSAGE_TYPE ( buffering_msg ) == GST_MESSAGE_BUFFERING) );
1097 if (position > (gint64)(streamer->buffering_req.initial_second * GST_SECOND))
1098 streamer->buffering_req.is_pre_buffering = FALSE;
1100 streaming_update_buffering_status(streamer, buffering_msg, position);
1102 if (!streamer->need_update)
1104 //debug_log ("don't need to update buffering stats during buffering.\n");
1108 streamer->need_update = FALSE;
1111 streaming_update_buffer_setting (streamer, buffering_msg, content_size, position, duration);