[0.6.169] use attr for buffering criteria
[platform/core/multimedia/libmm-player.git] / src / mm_player_streaming.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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>
8  *
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
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
21  */
22
23 #include <dlog.h>
24 #include "mm_player_utils.h"
25 #include "mm_player_streaming.h"
26
27 #define ESTIMATED_BUFFER_UNIT (1 * 1024 * 1024) /* 1 MBytes */
28
29 typedef struct {
30         gint byte_in_rate;              // byte
31         gint byte_out_rate;             // byte
32         gint time_rate;                 // ms
33         guint buffer_criteria;  // byte
34 } streaming_bitrate_info_t;
35
36 typedef struct {
37         gint64 position;        // ns
38         gint64 duration;        // ns
39         guint64 content_size;   // bytes
40 } streaming_content_info_t;
41
42 typedef struct {
43         guint buffering_bytes;          // bytes
44         gint buffering_time;            // ms
45         gdouble watermark_byte;
46         gdouble watermark_time;
47 } streaming_buffer_info_t;
48
49 static void streaming_set_buffer_watermark(mm_player_streaming_t *streamer, BufferType type, gdouble high_watermark_byte, gdouble high_watermark_time);
50 static void streaming_set_queue2_queue_type(mm_player_streaming_t *streamer, MuxedBufferType type);
51 static void streaming_set_buffer_size(mm_player_streaming_t *streamer, BufferType type, guint buffering_bytes, gint buffering_time);
52 static void streaming_update_buffering_status(mm_player_streaming_t *streamer, GstMessage *buffering_msg, gint64 position);
53 static void streaming_get_current_bitrate_info(mm_player_streaming_t *streamer,
54                                                                                                 GstMessage *buffering_msg,
55                                                                                                 streaming_content_info_t content_info,
56                                                                                                 streaming_bitrate_info_t *bitrate_info);
57 static void
58 streaming_handle_fixed_buffering_mode(mm_player_streaming_t *streamer,
59                                                                                 gint byte_out_rate,
60                                                                                 gint fixed_buffering_time,
61                                                                                 streaming_buffer_info_t *buffer_info);
62 static void
63 streaming_handle_adaptive_buffering_mode(mm_player_streaming_t *streamer,
64                                                                                 streaming_content_info_t content_info,
65                                                                                 streaming_bitrate_info_t bitrate_info,
66                                                                                 streaming_buffer_info_t *buffer_info,
67                                                                                 gint expected_play_time);
68 static void
69 streaming_update_buffer_setting(mm_player_streaming_t *streamer,
70                                                                 GstMessage *buffering_msg,
71                                                                 guint64 content_size,
72                                                                 gint64 position,
73                                                                 gint64 duration);
74
75 mm_player_streaming_t *__mm_player_streaming_create(void)
76 {
77         mm_player_streaming_t *streamer = NULL;
78
79         MMPLAYER_FENTER();
80
81         streamer = (mm_player_streaming_t *)g_try_malloc0(sizeof(mm_player_streaming_t));
82         if (!streamer) {
83                 LOGE("fail to create streaming player handle..");
84                 return NULL;
85         }
86
87         MMPLAYER_FLEAVE();
88
89         return streamer;
90 }
91
92 static void streaming_buffer_initialize(streaming_buffer_t *buffer_handle, gboolean buffer_init)
93 {
94         if (buffer_init)
95                 buffer_handle->buffer = NULL;
96
97         buffer_handle->buffering_bytes = DEFAULT_BUFFER_SIZE_BYTES;
98         buffer_handle->buffering_time = DEFAULT_BUFFERING_TIME;
99         buffer_handle->buffer_high_watermark = DEFAULT_BUFFER_HIGH_WATERMARK;
100         buffer_handle->is_live = FALSE;
101
102 }
103
104 void __mm_player_streaming_initialize(mm_player_streaming_t *streamer, gboolean buffer_init)
105 {
106         MMPLAYER_FENTER();
107         MMPLAYER_RETURN_IF_FAIL(streamer);
108
109         streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT;
110
111         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), buffer_init);
112         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), buffer_init);
113
114         streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
115         streamer->buffering_req.is_pre_buffering = TRUE;
116         streamer->buffering_req.prebuffer_time = 0;
117         streamer->buffering_req.rebuffer_time = 0;
118
119         streamer->default_val.buffering_monitor = FALSE;
120         streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
121
122         streamer->buffer_avg_bitrate = 0;
123         streamer->buffer_max_bitrate = 0;
124         streamer->need_update = FALSE;
125         streamer->need_sync = FALSE;
126
127         streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
128         streamer->is_adaptive_streaming = FALSE;
129
130         streamer->buffering_percent = -1;
131         streamer->ring_buffer_size = DEFAULT_RING_BUFFER_SIZE_BYTES;
132
133         MMPLAYER_FLEAVE();
134         return;
135 }
136
137 void __mm_player_streaming_destroy(mm_player_streaming_t *streamer)
138 {
139         MMPLAYER_FENTER();
140
141         MMPLAYER_FREEIF(streamer);
142
143         MMPLAYER_FLEAVE();
144
145         return;
146 }
147
148 void __mm_player_streaming_set_content_bitrate(
149         mm_player_streaming_t *streamer, guint max_bitrate, guint avg_bitrate)
150 {
151         gboolean is_update = FALSE;
152
153         MMPLAYER_FENTER();
154         MMPLAYER_RETURN_IF_FAIL(streamer);
155
156         /* Note : Update buffering criterion bytes
157          *      1. maximum bitrate is considered first.
158          *      2. average bitrage * 3 is next.
159          *      3. if there are no updated bitrate, use default buffering limit.
160          */
161         if (max_bitrate > 0 && streamer->buffer_max_bitrate != max_bitrate) {
162                 is_update = TRUE;
163                 streamer->buffer_max_bitrate = max_bitrate;
164         }
165
166         if (avg_bitrate > 0 && streamer->buffer_avg_bitrate != avg_bitrate) {
167                 is_update = TRUE;
168                 streamer->buffer_avg_bitrate = avg_bitrate;
169         }
170
171         if (is_update) {
172                 if (streamer->buffering_req.is_pre_buffering) {
173                         /* have to recalc queue2 size value after getting bitrate information */
174                         if (IS_MUXED_BUFFERING_MODE(streamer))
175                                 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
176                 } else {
177                         streamer->need_update = TRUE;
178                 }
179         }
180
181         MMPLAYER_FLEAVE();
182         return;
183 }
184
185 static gdouble streaming_get_min_watermark(gdouble high_watermark, gint max_size_time)
186 {
187         gdouble min_threshold = 0.05; /* 5% of buffer size */
188         gdouble max_threshold = 0.1;  /* 10% of buffer size */
189         gdouble low_watermark = 0.0;
190
191         if (max_size_time > 0)
192                 min_threshold = (gdouble)500 / max_size_time;  /* watermark for 500 ms */
193
194         low_watermark = high_watermark / 10; /* 10% of hig_watermark */
195
196         LOGD("threshold [%1.3f ~ %1.3f] watermakr[%1.3f ~ %1.3f]",
197                 min_threshold, max_threshold, low_watermark, high_watermark);
198
199         low_watermark = MAX(low_watermark, min_threshold);
200         low_watermark = MIN(low_watermark, max_threshold);
201
202         return low_watermark;
203 }
204
205 static void streaming_set_buffer_watermark(mm_player_streaming_t *streamer,
206         BufferType type, gdouble high_watermark_byte, gdouble high_watermark_time)
207 {
208         gdouble high_watermark = 0.0;
209
210         streaming_buffer_t *buffer_handle = NULL;
211         gchar *factory_name = NULL;
212
213         MMPLAYER_FENTER();
214         MMPLAYER_RETURN_IF_FAIL(streamer);
215         MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
216
217         buffer_handle = &(streamer->buffer_handle[type]);
218         if (!(buffer_handle && buffer_handle->buffer)) {
219                 LOGE("buffer_handle->buffer is NULL!");
220                 return;
221         }
222
223         factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
224
225         if (!factory_name) {
226                 LOGE("Fail to get factory name!");
227                 return;
228         }
229
230         if (type == BUFFER_TYPE_MUXED)
231                 high_watermark = high_watermark_byte;
232         else
233                 high_watermark = MAX(high_watermark_time, high_watermark_byte);
234
235         if (high_watermark <= MIN_BUFFER_WATERMARK || high_watermark  >=  MAX_BUFFER_WATERMARK)
236                 high_watermark = DEFAULT_BUFFER_HIGH_WATERMARK;
237
238         /* if use-buffering is disabled, this settings do not have any meaning. */
239         LOGD("target buffer elem : %s (~ %1.3f)",
240                 GST_ELEMENT_NAME(buffer_handle->buffer), high_watermark);
241
242         if ((high_watermark == DEFAULT_BUFFER_HIGH_WATERMARK) ||
243                 (buffer_handle->buffer_high_watermark != high_watermark)) {
244                 gdouble low_watermark = 0.0;
245
246                 /* if the low_watermark is too small, it can cause the underflow issue. */
247                 low_watermark = streaming_get_min_watermark(high_watermark, ((type == BUFFER_TYPE_MUXED) ? (0) : (buffer_handle->buffering_time)));
248
249                 LOGD("target buffer elem : %s ( %1.3f ~ %1.3f)",
250                         GST_ELEMENT_NAME(buffer_handle->buffer), low_watermark, high_watermark);
251
252                 g_object_set(G_OBJECT(buffer_handle->buffer), "high-watermark", high_watermark,
253                                                         "low-watermark", low_watermark, NULL);
254         }
255
256         buffer_handle->buffer_high_watermark = high_watermark;
257
258         MMPLAYER_FLEAVE();
259         return;
260 }
261
262 static void streaming_set_queue2_queue_type(mm_player_streaming_t *streamer, MuxedBufferType type)
263 {
264         streaming_buffer_t *buffer_handle = NULL;
265         guint64 buffer_size = 0;  /* bytes */
266
267         MMPLAYER_FENTER();
268         MMPLAYER_RETURN_IF_FAIL(streamer);
269         MMPLAYER_RETURN_IF_FAIL(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer);
270
271         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_MUXED]);
272
273         if (!(buffer_handle && buffer_handle->buffer)) {
274                 LOGE("buffer_handle->buffer is NULL!");
275                 return;
276         }
277
278         if (type == MUXED_BUFFER_TYPE_MEM_QUEUE) { /* ts */
279                 LOGD("use memory queue for buffering. streaming is played on push-based. \n"
280                                         "buffering position would not be updated.\n"
281                                         "buffered data would be flushed after played.\n"
282                                         "seeking and getting duration could be failed due to file format.");
283                 return;
284         }
285
286         /* @see ini->http_ring_buffer_size */
287         buffer_size = (guint64)((streamer->ring_buffer_size > 0) ? (streamer->ring_buffer_size) : DEFAULT_RING_BUFFER_SIZE_BYTES);
288
289         LOGW("ring buffer size: %"G_GUINT64_FORMAT, buffer_size);
290         g_object_set(G_OBJECT(buffer_handle->buffer), "ring-buffer-max-size", buffer_size, NULL);
291
292         MMPLAYER_FLEAVE();
293         return;
294 }
295
296 static void streaming_set_buffer_size(mm_player_streaming_t *streamer,
297         BufferType type, guint buffering_bytes, gint buffering_time)
298 {
299         streaming_buffer_t *buffer_handle = NULL;
300
301         MMPLAYER_FENTER();
302
303         MMPLAYER_RETURN_IF_FAIL(streamer);
304         MMPLAYER_RETURN_IF_FAIL(buffering_bytes > 0);
305         MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
306
307         buffer_handle = &(streamer->buffer_handle[type]);
308
309         if (buffer_handle && buffer_handle->buffer) {
310                 if (g_strrstr(GST_ELEMENT_NAME(buffer_handle->buffer), "multiqueue")) {
311                         if (buffering_time <= 0)
312                                 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
313
314                         g_object_set(G_OBJECT(buffer_handle->buffer),
315                                                         "max-size-bytes", MAX_BUFFER_SIZE_BYTES,        /* mq size is fixed, control it with high/low watermark value*/
316                                                         "max-size-time", (guint64)(buffering_time * GST_MSECOND),
317                                                         "max-size-buffers", 0, NULL);                                           /* disable */
318
319                         buffer_handle->buffering_time = buffering_time;
320                         buffer_handle->buffering_bytes = MAX_BUFFER_SIZE_BYTES;
321
322                         LOGD("byte: %d, max-size-time : %d ms", buffering_bytes, buffering_time);
323                 } else {
324                         /* queue2 */
325                         if (buffer_handle->is_live)
326                                 g_object_set(G_OBJECT(buffer_handle->buffer),
327                                                                 "max-size-bytes", buffering_bytes,
328                                                                 "max-size-time", (guint64)(buffering_time * GST_MSECOND),
329                                                                 "max-size-buffers", 0,
330                                                                 "use-rate-estimate", TRUE, NULL);
331                         else
332                                 g_object_set(G_OBJECT(buffer_handle->buffer),
333                                                                 "max-size-bytes", buffering_bytes,
334                                                                 "max-size-time", (guint64)0,
335                                                                 "max-size-buffers", 0,
336                                                                 "use-rate-estimate", FALSE, NULL);
337
338                         buffer_handle->buffering_bytes = buffering_bytes;
339                         buffer_handle->buffering_time = buffering_time;
340
341                         LOGD("max-size-bytes : %d, time : %d", buffering_bytes, buffering_time);
342                 }
343         }
344
345         MMPLAYER_FLEAVE();
346         return;
347 }
348
349 void __mm_player_streaming_set_queue2(mm_player_streaming_t *streamer, GstElement *buffer,
350         gboolean use_buffering, MuxedBufferType type, guint64 content_size)
351 {
352         guint queue_size_bytes = 0;
353         guint queue_size_time = 0;
354
355         MMPLAYER_FENTER();
356         MMPLAYER_RETURN_IF_FAIL(streamer && buffer);
357
358         LOGD("use buffering %d, type %d, content_size %"G_GUINT64_FORMAT, use_buffering, type, content_size);
359
360         streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer = buffer;
361
362         if (use_buffering) { /* audio only content use queue2 for buffering */
363                 streamer->streaming_buffer_type = BUFFER_TYPE_MUXED;
364
365                 if (streamer->buffering_req.prebuffer_time <= MIN_BUFFERING_TIME)
366                         streamer->buffering_req.prebuffer_time = DEFAULT_PREBUFFERING_TIME;
367
368                 if (content_size == 0) {
369                         LOGD("live streaming without mq");
370                         streamer->buffer_handle[BUFFER_TYPE_MUXED].is_live = TRUE;
371                 }
372
373                 /* keep estimated value till the pipeline share the bitrate information */
374                 queue_size_bytes = (guint)(streamer->buffering_req.prebuffer_time / 1000) * ESTIMATED_BUFFER_UNIT; /* temp size */
375                 queue_size_bytes = MAX(queue_size_bytes, DEFAULT_BUFFER_SIZE_BYTES);
376                 queue_size_time = streamer->buffering_req.prebuffer_time;
377         } else {
378                 if (type >= MUXED_BUFFER_TYPE_MAX) {
379                         LOGE("invalid queue type");
380                         return;
381                 }
382
383                 /* set the simple queue size */
384                 queue_size_bytes = DEFAULT_BUFFER_SIZE_BYTES;
385                 streaming_set_queue2_queue_type(streamer, type);
386                 queue_size_time = 0; /* set in case of use-buffering */
387         }
388
389         g_object_set(G_OBJECT(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL);
390
391         LOGD("buffer time: %d ms, buffer bytes: %d", queue_size_time, queue_size_bytes);
392         streaming_set_buffer_size(streamer, BUFFER_TYPE_MUXED, queue_size_bytes, queue_size_time);
393         streaming_set_buffer_watermark(streamer, BUFFER_TYPE_MUXED, DEFAULT_BUFFER_HIGH_WATERMARK, 0);
394
395         MMPLAYER_FLEAVE();
396         return;
397 }
398
399 void __mm_player_streaming_sync_property(mm_player_streaming_t *streamer, GstElement *decodebin)
400 {
401         streaming_buffer_t *buffer_handle = NULL;
402         gdouble low_watermark = 0.0;
403
404         MMPLAYER_FENTER();
405         MMPLAYER_RETURN_IF_FAIL(streamer && decodebin);
406
407         if ((!streamer->need_sync) || (streamer->streaming_buffer_type != BUFFER_TYPE_DEMUXED)) {
408                 streamer->need_sync = FALSE;
409                 return;
410         }
411
412         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
413         low_watermark = streaming_get_min_watermark(buffer_handle->buffer_high_watermark, buffer_handle->buffering_time);
414
415         g_object_set(G_OBJECT(decodebin),
416                                 "max-size-bytes", buffer_handle->buffering_bytes,
417                                 "max-size-time", (guint64)(buffer_handle->buffering_time * GST_MSECOND),
418                                 "high-percent", (gint)(buffer_handle->buffer_high_watermark * 100),
419                                 "low-percent", (gint)(low_watermark * 100), NULL);
420
421         streamer->need_sync = FALSE;
422 }
423
424 void __mm_player_streaming_set_multiqueue(mm_player_streaming_t *streamer, GstElement *buffer)
425 {
426         streaming_buffer_t *buffer_handle = NULL;
427         gdouble high_watermark = 0.0;
428
429         MMPLAYER_FENTER();
430         MMPLAYER_RETURN_IF_FAIL(streamer && buffer);
431
432         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
433         buffer_handle->buffer = buffer;
434
435         LOGD("pre_buffering: %d ms", streamer->buffering_req.prebuffer_time);
436
437         streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
438         g_object_set(G_OBJECT(buffer_handle->buffer), "use-buffering", TRUE, NULL);
439
440         if (streamer->buffering_req.prebuffer_time <= MIN_BUFFERING_TIME)
441                 streamer->buffering_req.prebuffer_time = DEFAULT_PREBUFFERING_TIME;
442
443         high_watermark = (gdouble)(streamer->buffering_req.prebuffer_time) / MAX_BUFFER_SIZE_TIME;
444         LOGD("new pre buffer time %d ms, high_watermark %1.3f %%", streamer->buffering_req.prebuffer_time, high_watermark);
445
446         /* initial setting */
447         streaming_set_buffer_size(streamer, BUFFER_TYPE_DEMUXED, MAX_BUFFER_SIZE_BYTES, MAX_BUFFER_SIZE_TIME);
448         streaming_set_buffer_watermark(streamer, BUFFER_TYPE_DEMUXED, 0, high_watermark);
449
450         streamer->need_sync = TRUE;
451
452         MMPLAYER_FLEAVE();
453         return;
454 }
455
456 static void streaming_get_current_bitrate_info(mm_player_streaming_t *streamer,
457         GstMessage *buffering_msg, streaming_content_info_t content_info, streaming_bitrate_info_t *bitrate_info)
458 {
459         GstQuery *query = NULL;
460         GstBufferingMode mode = GST_BUFFERING_STREAM;
461         gint in_rate = 0;
462         gint out_rate = 0;
463         gint64 buffering_left = -1;
464
465         guint buffer_criteria = 0;
466         guint estimated_content_bitrate = 0;
467
468         gint buffer_buffering_time = DEFAULT_BUFFERING_TIME;
469
470         MMPLAYER_FENTER();
471
472         MMPLAYER_RETURN_IF_FAIL(streamer);
473         MMPLAYER_RETURN_IF_FAIL(bitrate_info);
474
475         if ((buffering_msg == NULL) ||
476                 ((streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer != NULL) &&
477                 (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer != NULL) &&
478                 (buffering_msg->src == (GstObject *)streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer))) {
479                 query = gst_query_new_buffering(GST_FORMAT_PERCENT);
480
481                 if (gst_element_query((streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), query))
482                         gst_query_parse_buffering_stats(query, &mode, &in_rate, &out_rate, &buffering_left);
483                 gst_query_unref(query);
484         } else {
485                 gst_message_parse_buffering_stats(buffering_msg, &mode, &in_rate, &out_rate, &buffering_left);
486         }
487
488         LOGD("Streaming Info : in %d, out %d, left %"G_GINT64_FORMAT, in_rate, out_rate, buffering_left);
489
490         if ((content_info.content_size > 0) && (content_info.duration > 0) && ((content_info.duration / GST_SECOND) > 0))
491                 estimated_content_bitrate = GET_BIT_FROM_BYTE((guint)(content_info.content_size / (content_info.duration / GST_SECOND)));
492
493         if (streamer->buffer_max_bitrate > 0) {
494                 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, streamer->buffer_avg_bitrate);
495                 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, estimated_content_bitrate);
496
497                 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate);
498
499                 if (streamer->buffer_avg_bitrate > estimated_content_bitrate)
500                         out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate);
501                 else if (estimated_content_bitrate != 0)
502                         out_rate = GET_BYTE_FROM_BIT(estimated_content_bitrate);
503                 else
504                         out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate/3);
505
506                 LOGD("(max)content_max_byte_rate %d, byte_out_rate %d", buffer_criteria, out_rate);
507         } else if (streamer->buffer_avg_bitrate > 0) {
508                 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3);
509                 out_rate = GET_BYTE_FROM_BIT(MAX(streamer->buffer_avg_bitrate, estimated_content_bitrate));
510
511                 LOGD("(avg)content_max_byte_rate %d, byte_out_rate %d", buffer_criteria, out_rate);
512         } else {
513                 LOGW("There is no content bitrate information, use estimated value");
514                 out_rate = estimated_content_bitrate;
515         }
516
517         if ((in_rate > 0) && (out_rate > 0))
518                 buffer_buffering_time =  (gint)(out_rate / in_rate) * 1000;
519         else if ((in_rate <= 0) && (out_rate > 0))
520                 buffer_buffering_time = MAX_BUFFERING_TIME;
521         else
522                 buffer_buffering_time = DEFAULT_BUFFERING_TIME;
523
524         (*bitrate_info).byte_in_rate = in_rate;
525         (*bitrate_info).byte_out_rate = out_rate;
526         (*bitrate_info).time_rate = buffer_buffering_time;
527         (*bitrate_info).buffer_criteria = buffer_criteria;
528 }
529
530 static void streaming_handle_fixed_buffering_mode(mm_player_streaming_t *streamer,
531         gint byte_out_rate, gint expected_play_time, streaming_buffer_info_t *buffer_info)
532 {
533         streaming_buffer_t *buffer_handle = NULL;
534
535         guint expected_play_bytes = 0;
536         gdouble wm_byte = 0.0;
537         gdouble wm_time = 0.0;
538
539         MMPLAYER_RETURN_IF_FAIL(streamer);
540         MMPLAYER_RETURN_IF_FAIL(buffer_info);
541
542         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
543
544         LOGD("buffering time: %d ms, out rate: %d", expected_play_time, byte_out_rate);
545
546         if (byte_out_rate > 0) {
547                 guint max_size_byte = GET_MAX_BYTE_BUFFER_SIZE(streamer->streaming_buffer_type);
548                 expected_play_bytes = (guint)GET_NEW_BUFFERING_BYTE((gdouble)(byte_out_rate * expected_play_time) / 1000, max_size_byte);
549         } else {
550                 LOGW("content bitrate is not updated yet.");
551                 expected_play_bytes = GET_CURRENT_BUFFERING_BYTE(buffer_handle);
552         }
553
554         GET_WATERMARK(expected_play_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_watermark, wm_time);
555         GET_WATERMARK(expected_play_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_watermark, wm_byte);
556
557         LOGD("bytes %d, time %d, wm_byte %f, wm_time %f", expected_play_bytes, expected_play_time, wm_byte, wm_time);
558
559         (*buffer_info).buffering_bytes = expected_play_bytes;
560         (*buffer_info).buffering_time = expected_play_time;
561         (*buffer_info).watermark_byte = wm_byte;
562         (*buffer_info).watermark_time = wm_time;
563 }
564
565 static void streaming_handle_adaptive_buffering_mode(mm_player_streaming_t *streamer,
566         streaming_content_info_t content_info, streaming_bitrate_info_t bitrate_info,
567         streaming_buffer_info_t *buffer_info, gint expected_play_time)
568 {
569         streaming_buffer_t *buffer_handle = NULL;
570
571         gint buffering_bytes = 0;
572         gint adj_buffering_bytes = 0;
573         gint buffer_buffering_time = 0;
574         gdouble wm_byte = 0.0;
575         gdouble wm_time = 0.0;
576         gdouble portion = 0.0;
577         gint default_buffering_time = 0;
578
579         MMPLAYER_RETURN_IF_FAIL(streamer);
580         MMPLAYER_RETURN_IF_FAIL(buffer_info);
581
582         LOGD("pos %"G_GINT64_FORMAT", dur %"G_GINT64_FORMAT", size %"G_GUINT64_FORMAT", in/out:%d/%d, buffer_criteria:%d, time_rate:%d, need:%d ms",
583                                                         content_info.position, content_info.duration, content_info.content_size,
584                                                         bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
585                                                         bitrate_info.buffer_criteria, bitrate_info.time_rate, expected_play_time);
586
587         if ((content_info.duration <= 0) ||
588                 (content_info.content_size <= 0)) {
589                 LOGW("keep previous setting.");
590                 return;
591         }
592
593         if ((bitrate_info.byte_out_rate <= 0) || (bitrate_info.buffer_criteria == 0)) {
594                 LOGW("keep previous setting.");
595                 return;
596         }
597
598         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
599
600         if (bitrate_info.byte_in_rate < bitrate_info.byte_out_rate) {
601                 guint max_size_byte = GET_MAX_BYTE_BUFFER_SIZE(streamer->streaming_buffer_type);
602                 portion = (double)(expected_play_time * GST_MSECOND) / (double)content_info.duration;
603                 buffering_bytes = GET_NEW_BUFFERING_BYTE(
604                         (((double)content_info.content_size * portion) *
605                           (1 - (double)bitrate_info.byte_in_rate / (double)bitrate_info.byte_out_rate)), max_size_byte);
606         } else {
607                 /* buffering_bytes will be set as streamer->default_val.buffering_time *
608                  * receiving rate is bigger than avg content bitrate
609                  * so there is no reason to buffering. if the buffering msg is posted
610                  * in-rate or contents bitrate has wrong value. */
611                 LOGW("don't need to do buffering.");
612         }
613
614         if (buffering_bytes > 0)
615                 buffer_buffering_time = (gint)(buffering_bytes / bitrate_info.byte_out_rate) * 1000;
616
617         if (content_info.position <= 0) {
618                 /* if the buffer is filled under 50%, MSL use the original default buffering time.
619                    if not, MSL use just 2 sec as a default buffering time. (to reduce initial buffering time) */
620                 default_buffering_time = streamer->default_val.buffering_time - ((gdouble)streamer->buffering_percent / 50) * 1000;
621         } else {
622                 default_buffering_time = streamer->default_val.buffering_time;
623         }
624
625         if (buffer_buffering_time < default_buffering_time) {
626                 guint max_size_byte = GET_MAX_BYTE_BUFFER_SIZE(streamer->streaming_buffer_type);
627
628                 LOGD("adjusted time: %d -> %d ms", buffer_buffering_time, default_buffering_time);
629                 LOGD("adjusted bytes : %d or %d or %d",
630                         buffering_bytes,
631                         (gint)(bitrate_info.byte_out_rate * buffer_buffering_time / 1000),
632                         (gint)(bitrate_info.buffer_criteria * buffer_buffering_time / 1000));
633
634                 /* start monitoring the abmormal state */
635                 if (content_info.position > 0)
636                         streamer->default_val.buffering_monitor = TRUE;
637
638                 buffer_buffering_time = default_buffering_time;
639                 adj_buffering_bytes = GET_NEW_BUFFERING_BYTE(
640                         (bitrate_info.byte_out_rate * (gint)ceil((gdouble)buffer_buffering_time / 1000)), max_size_byte);
641                 buffering_bytes = MAX(buffering_bytes, adj_buffering_bytes);
642         }
643
644         GET_WATERMARK(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_watermark, wm_byte);
645         GET_WATERMARK(buffer_buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_watermark, wm_time);
646
647         LOGD("monitor %d, bytes %d, time %d, wm_byte %f, wm_time %f",
648                                                                                 streamer->default_val.buffering_monitor,
649                                                                                 buffering_bytes, buffer_buffering_time, wm_byte, wm_time);
650
651         (*buffer_info).buffering_bytes = buffering_bytes;
652         (*buffer_info).buffering_time = buffer_buffering_time;
653         (*buffer_info).watermark_byte = wm_byte;
654         (*buffer_info).watermark_time = wm_time;
655
656 }
657
658 static void streaming_update_buffer_setting(mm_player_streaming_t *streamer,
659         GstMessage *buffering_msg, guint64 content_size, gint64 position, gint64 duration)
660 {
661         streaming_buffer_t *buffer_handle = NULL;
662         MMPlayerBufferingMode buffering_mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
663         gint expected_play_time = DEFAULT_REBUFFERING_TIME;
664
665         streaming_buffer_info_t buffer_info;
666         streaming_content_info_t content_info;
667         streaming_bitrate_info_t bitrate_info;
668
669         MMPLAYER_FENTER();
670
671         MMPLAYER_RETURN_IF_FAIL(streamer);
672
673         memset(&buffer_info, 0x00, sizeof(streaming_buffer_info_t));
674         memset(&content_info, 0x00, sizeof(streaming_content_info_t));
675         memset(&bitrate_info, 0x00, sizeof(streaming_bitrate_info_t));
676
677         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
678
679         if (streamer->buffering_req.is_pre_buffering == TRUE) {
680                 buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
681                 expected_play_time = streamer->buffering_req.prebuffer_time;
682         } else {
683                 if (content_size == 0 || duration == 0) /* can not support adaptive mode */
684                         buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
685                 else
686                         buffering_mode = streamer->buffering_req.mode;
687
688                 if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED) {
689                         if (streamer->buffering_req.rebuffer_time > 0)
690                                 expected_play_time = streamer->buffering_req.rebuffer_time;
691                         else
692                                 expected_play_time = DEFAULT_LIVE_REBUFFER_TIME;
693                 }
694         }
695
696         LOGD("buffering mode: %d, time: %d", buffering_mode, expected_play_time);
697
698         buffer_info.buffering_bytes = buffer_handle->buffering_bytes;
699         buffer_info.buffering_time = buffer_handle->buffering_time;
700         buffer_info.watermark_byte = buffer_handle->buffer_high_watermark;
701         buffer_info.watermark_time = buffer_handle->buffer_high_watermark;
702
703         content_info.position = position;
704         content_info.duration = duration;
705         content_info.content_size = content_size;
706
707         streaming_get_current_bitrate_info(streamer, buffering_msg, content_info, &bitrate_info);
708
709         LOGD("in_r:%d, out_r:%d", bitrate_info.byte_in_rate, bitrate_info.byte_out_rate);
710
711         if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED) {
712                 streaming_handle_fixed_buffering_mode(streamer, bitrate_info.byte_out_rate, expected_play_time, &buffer_info);
713         } else {
714                 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, expected_play_time);
715
716                 /* even if new byte size is smaller than the previous one, time need to be updated. */
717                 if (IS_MUXED_BUFFERING_MODE(streamer))
718                         buffer_handle->buffering_time = buffer_info.buffering_time;
719         }
720
721         LOGD("adj buffer(%d) %d->%d bytes/%d->%d ms",
722                 streamer->streaming_buffer_type,
723                 GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_info.buffering_bytes,
724                 GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_info.buffering_time);
725
726         /* queue2 : bytes, multiqueue : time */
727         if (((GET_CURRENT_BUFFERING_BYTE(buffer_handle) < buffer_info.buffering_bytes) && IS_MUXED_BUFFERING_MODE(streamer)) ||
728                 ((GET_CURRENT_BUFFERING_TIME(buffer_handle) < buffer_info.buffering_time) && IS_DEMUXED_BUFFERING_MODE(streamer))) {
729                 if (duration > 0 && position > 0) {
730                         gint buffering_time_limit = (gint)(duration - position) / GST_MSECOND;
731
732                         if (buffer_info.buffering_time > buffering_time_limit)
733                                 buffer_info.buffering_time = buffering_time_limit;
734                 }
735
736                 streaming_set_buffer_size(streamer, streamer->streaming_buffer_type, buffer_info.buffering_bytes, buffer_info.buffering_time);
737         }
738
739         streaming_set_buffer_watermark(streamer, streamer->streaming_buffer_type, buffer_info.watermark_byte, buffer_info.watermark_time);
740
741         LOGD("buffer setting: size %d, time %d, watermark %f",
742                 GET_CURRENT_BUFFERING_BYTE(buffer_handle),
743                 GET_CURRENT_BUFFERING_TIME(buffer_handle),
744                 buffer_handle->buffer_high_watermark);
745
746         streamer->need_sync = TRUE;
747 }
748
749 static void streaming_adjust_min_threshold(mm_player_streaming_t *streamer, gint64 position)
750 {
751 #define DEFAULT_TIME_PAD 1000   /* ms */
752         gint playing_time = 0;
753
754         MMPLAYER_FENTER();
755
756         MMPLAYER_RETURN_IF_FAIL(streamer);
757
758         playing_time = (gint)((position - streamer->default_val.prev_pos) / GST_MSECOND);
759
760         LOGD("buffering monitor = %s", (streamer->default_val.buffering_monitor) ? "ON" : "OFF");
761         LOGD("playing_time (%d ms) = %"G_GINT64_FORMAT" - %"G_GINT64_FORMAT, playing_time, position, streamer->default_val.prev_pos);
762         LOGD("default time : %d, prev buffering t : %d",
763                 streamer->default_val.buffering_time, streamer->buffer_handle[streamer->streaming_buffer_type].buffering_time);
764
765         if ((streamer->default_val.buffering_monitor) && (playing_time <= streamer->default_val.buffering_time)) {
766                 gint time_gap = 0;
767                 time_gap = streamer->default_val.buffering_time - DEFAULT_BUFFERING_TIME;
768                 if (time_gap <= 0)
769                         time_gap = DEFAULT_TIME_PAD;
770
771                 streamer->default_val.buffering_time += time_gap * 2;
772                 streamer->default_val.buffering_time = MIN(streamer->default_val.buffering_time, MAX_BUFFERING_TIME);
773         } else {
774                 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
775         }
776
777         LOGD("new default min value %d", streamer->default_val.buffering_time);
778
779         streamer->default_val.buffering_monitor = FALSE;
780         streamer->default_val.prev_pos = position;
781 }
782
783 static void streaming_update_buffering_status(mm_player_streaming_t *streamer, GstMessage *buffering_msg, gint64 position)
784 {
785         gint buffer_percent = 0;
786
787         MMPLAYER_FENTER();
788
789         MMPLAYER_RETURN_IF_FAIL(streamer);
790         MMPLAYER_RETURN_IF_FAIL(buffering_msg);
791
792         /* update when buffering has started. */
793         if (!(streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
794                 streamer->buffering_state = MM_PLAYER_BUFFERING_IN_PROGRESS;
795                 streamer->buffering_percent = -1;
796
797                 if (!streamer->buffering_req.is_pre_buffering) {
798                         streamer->need_update = TRUE;
799                         streaming_adjust_min_threshold(streamer, position);
800                 }
801         }
802
803         /* update buffer percent */
804         gst_message_parse_buffering(buffering_msg, &buffer_percent);
805
806         /* LOGD("[%s] buffering per %d%% -> %d%%, state 0x%X", streamer->buffering_percent, buffer_percent, streamer->buffering_state); */
807
808         if (streamer->buffering_percent < buffer_percent) {
809                 LOGD("[%s] buffering %d%%....",
810                         GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
811                 streamer->buffering_percent = buffer_percent;
812         }
813
814         if (streamer->buffering_percent == MAX_BUFFER_PERCENT) {
815                 streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
816                 streamer->buffering_req.is_pre_buffering = FALSE;
817         } else if (streamer->buffering_state & MM_PLAYER_BUFFERING_COMPLETE) {
818                 streamer->buffering_state = MM_PLAYER_BUFFERING_COMPLETE; /* have to keep state to ignore remained msg till get 100% msg */
819                 streamer->buffering_req.is_pre_buffering = FALSE;
820                 streamer->buffering_percent = MAX_BUFFER_PERCENT;
821                 LOGD("updated to the buffering 100%%.... (by force)");
822         }
823 }
824
825 void __mm_player_streaming_buffering(mm_player_streaming_t *streamer, GstMessage *buffering_msg,
826         guint64 content_size, gint64 position, gint64 duration)
827 {
828         MMPLAYER_FENTER();
829
830         MMPLAYER_RETURN_IF_FAIL(streamer);
831         MMPLAYER_RETURN_IF_FAIL(buffering_msg);
832         MMPLAYER_RETURN_IF_FAIL(GST_IS_MESSAGE(buffering_msg));
833         MMPLAYER_RETURN_IF_FAIL((GST_MESSAGE_TYPE(buffering_msg) == GST_MESSAGE_BUFFERING));
834
835         if (position > (gint64)(streamer->buffering_req.prebuffer_time * GST_MSECOND))
836                 streamer->buffering_req.is_pre_buffering = FALSE;
837
838         streaming_update_buffering_status(streamer, buffering_msg, position);
839
840         if (!streamer->need_update)
841                 return;
842
843         streamer->need_update = FALSE;
844         streaming_update_buffer_setting(streamer, buffering_msg, content_size, position, duration);
845
846         return;
847 }