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