1da6f4d33f466589b8b554f6a853e0ef3cc68823
[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 <sys/vfs.h>
24 #include <dlog.h>
25 #include "mm_player_utils.h"
26 #include "mm_player_streaming.h"
27
28 typedef struct {
29         gint byte_in_rate;              // byte
30         gint byte_out_rate;             // byte
31         gint time_rate;                 // ms
32         guint buffer_criteria;  // byte
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 percent_byte;
45         gdouble percent_time;
46 } streaming_buffer_info_t;
47
48 static void streaming_set_buffer_percent(mm_player_streaming_t* streamer, BufferType type, gdouble high_percent_byte, gdouble high_percent_time);
49 static void streaming_set_queue2_queue_type(mm_player_streaming_t* streamer, MuxedBufferType type, gchar * file_path, guint64 content_size);
50 static void streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gint buffering_time);
51 static void streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position);
52 static void streaming_get_current_bitrate_info(mm_player_streaming_t* streamer,
53                                                                                                 GstMessage *buffering_msg,
54                                                                                                 streaming_content_info_t content_info,
55                                                                                                 streaming_bitrate_info_t* bitrate_info);
56 static void
57 streaming_handle_fixed_buffering_mode(mm_player_streaming_t* streamer,
58                                                                                 gint byte_out_rate,
59                                                                                 gint fixed_buffering_time,
60                                                                                 streaming_buffer_info_t* buffer_info);
61 static void
62 streaming_handle_adaptive_buffering_mode(mm_player_streaming_t* streamer,
63                                                                                         streaming_content_info_t content_info,
64                                                                                         streaming_bitrate_info_t bitrate_info,
65                                                                                         streaming_buffer_info_t* buffer_info,
66                                                                                         gint expected_play_time);
67 static void
68 streaming_update_buffer_setting(mm_player_streaming_t* streamer,
69                                                                         GstMessage *buffering_msg,
70                                                                         guint64 content_size,
71                                                                         gint64 position,
72                                                                         gint64 duration);
73
74 mm_player_streaming_t *
75 __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_malloc0(sizeof(mm_player_streaming_t));
82         if (!streamer) {
83                 LOGE("fail to create streaming player handle..\n");
84                 return NULL;
85         }
86
87         MMPLAYER_FLEAVE();
88
89         return streamer;
90 }
91
92 static void
93 streaming_buffer_initialize(streaming_buffer_t* buffer_handle, gboolean buffer_init)
94 {
95         if (buffer_init)
96                 buffer_handle->buffer = NULL;
97
98         buffer_handle->buffering_bytes = DEFAULT_BUFFER_SIZE_BYTES;
99         buffer_handle->buffering_time = DEFAULT_BUFFERING_TIME;
100         buffer_handle->buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
101         buffer_handle->is_live = FALSE;
102
103 }
104
105 void __mm_player_streaming_initialize(mm_player_streaming_t* streamer)
106 {
107         MMPLAYER_FENTER();
108
109         streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT;  // multi-queue
110
111         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), TRUE);
112         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), TRUE);
113
114         streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
115         streamer->buffering_req.is_pre_buffering = FALSE;
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;
132
133         MMPLAYER_FLEAVE();
134         return;
135 }
136
137 void __mm_player_streaming_deinitialize(mm_player_streaming_t* streamer)
138 {
139         MMPLAYER_FENTER();
140         MMPLAYER_RETURN_IF_FAIL(streamer);
141
142         streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT;  // multi-queue
143
144         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), FALSE);
145         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), FALSE);
146
147         streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
148         streamer->buffering_req.is_pre_buffering = FALSE;
149         streamer->buffering_req.prebuffer_time = 0;
150         streamer->buffering_req.rebuffer_time = 0;
151
152         streamer->default_val.buffering_monitor = FALSE;
153         streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
154
155         streamer->buffer_avg_bitrate = 0;
156         streamer->buffer_max_bitrate = 0;
157         streamer->need_update = FALSE;
158         streamer->need_sync = FALSE;
159
160         streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
161         streamer->is_adaptive_streaming = FALSE;
162
163         streamer->buffering_percent = -1;
164         streamer->ring_buffer_size = DEFAULT_RING_BUFFER_SIZE;
165
166         MMPLAYER_FLEAVE();
167         return;
168 }
169
170 void __mm_player_streaming_destroy(mm_player_streaming_t* streamer)
171 {
172         MMPLAYER_FENTER();
173
174         g_free(streamer);
175
176         MMPLAYER_FLEAVE();
177
178         return;
179 }
180
181 void __mm_player_streaming_set_content_bitrate(mm_player_streaming_t* streamer, guint max_bitrate, guint avg_bitrate)
182 {
183         MMPLAYER_FENTER();
184
185         MMPLAYER_RETURN_IF_FAIL(streamer);
186
187         /* Note : Update buffering criterion bytes
188         *      1. maximum bitrate is considered first.
189         *      2. average bitrage * 3 is next.
190         *      3. if there are no updated bitrate, use default buffering limit.
191         */
192         if (max_bitrate > 0 && streamer->buffer_max_bitrate != max_bitrate) {
193                 LOGD("set maximum bitrate(%dbps).\n", max_bitrate);
194                 streamer->buffer_max_bitrate = max_bitrate;
195                 if (streamer->buffering_req.is_pre_buffering == FALSE) {
196                         streamer->need_update = TRUE;
197                 } else {
198                         LOGD("pre-buffering...\n");
199
200                         if (IS_MUXED_BUFFERING_MODE(streamer))
201                                 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
202                 }
203         }
204
205         if (avg_bitrate > 0 && streamer->buffer_avg_bitrate != avg_bitrate) {
206                 LOGD("set averate bitrate(%dbps).\n", avg_bitrate);
207                 streamer->buffer_avg_bitrate = avg_bitrate;
208
209                 if (streamer->buffering_req.is_pre_buffering == FALSE) {
210                         streamer->need_update = TRUE;
211                 } else {
212                         LOGD("pre-buffering...\n");
213
214                         if (IS_MUXED_BUFFERING_MODE(streamer))
215                                 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
216                 }
217         }
218
219         MMPLAYER_FLEAVE();
220         return;
221 }
222
223 static void
224 streaming_set_buffer_percent(mm_player_streaming_t* streamer,
225                                                                 BufferType type,
226                                                                 gdouble high_percent_byte,
227                                                                 gdouble high_percent_time)
228 {
229         gdouble high_percent = 0.0;
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 (type == BUFFER_TYPE_MUXED)
252                 high_percent = high_percent_byte;
253         else
254                 high_percent = MAX(high_percent_time, high_percent_byte);
255
256         if (high_percent <= MIN_BUFFER_PERCENT || high_percent  >=  MAX_BUFFER_PERCENT)
257                 high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
258
259         /* if use-buffering is disabled, this settings do not have any meaning. */
260         LOGD("target buffer elem : %s (~ %2.3f)",
261                 GST_ELEMENT_NAME(buffer_handle->buffer), high_percent);
262
263         if ((high_percent == DEFAULT_BUFFER_HIGH_PERCENT) ||
264                 (buffer_handle->buffer_high_percent != high_percent))
265                 g_object_set(G_OBJECT(buffer_handle->buffer), "high-percent", (gint)high_percent, NULL);
266
267         buffer_handle->buffer_high_percent = high_percent;
268
269         MMPLAYER_FLEAVE();
270         return;
271 }
272
273 static void
274 streaming_set_queue2_queue_type(mm_player_streaming_t* streamer, MuxedBufferType type, gchar * file_path, guint64 content_size)
275 {
276         streaming_buffer_t* buffer_handle = NULL;
277         guint64 storage_available_size = 0; /* bytes */
278         guint64 buffer_size = 0;  /* bytes */
279         gchar file_buffer_name[MM_MAX_URL_LEN] = {0};
280         struct statfs buf = {0};
281         gchar* factory_name = NULL;
282
283         MMPLAYER_FENTER();
284         MMPLAYER_RETURN_IF_FAIL(streamer);
285         MMPLAYER_RETURN_IF_FAIL(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer);
286
287         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_MUXED]);
288
289         if (!(buffer_handle && buffer_handle->buffer)) {
290                 LOGE("buffer_handle->buffer is NULL!");
291                 return;
292         }
293
294         factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
295
296         if (!factory_name) {
297                 LOGE("Fail to get factory name!");
298                 return;
299         }
300
301         LOGD("target buffer elem : %s", GST_ELEMENT_NAME(buffer_handle->buffer));
302
303         if (!g_strrstr(factory_name, "queue2")) {
304                 LOGD("only queue2 can use file buffer. not decodebin2 or multiQ\n");
305                 return;
306         }
307
308         if (type == MUXED_BUFFER_TYPE_MEM_QUEUE) {
309                 LOGD("use memory queue for buffering. streaming is played on push-based. \n"
310                                         "buffering position would not be updated.\n"
311                                         "buffered data would be flushed after played.\n"
312                                         "seeking and getting duration could be failed due to file format.");
313                 return;
314         }
315
316         LOGD("[Queue2] buffering type : %d. streaming is played on pull-based. \n", type);
317         if (type == MUXED_BUFFER_TYPE_FILE && file_path && strlen(file_path) > 0) {
318                 if (statfs((const char *)file_path, &buf) < 0) {
319                         LOGW("[Queue2] fail to get available storage capacity. set mem ring buffer instead of file buffer.\n");
320                         buffer_size = (guint64)((streamer->ring_buffer_size > 0) ? (streamer->ring_buffer_size) : DEFAULT_RING_BUFFER_SIZE);
321                 } else {
322                         storage_available_size = (guint64)buf.f_bavail * (guint64)buf.f_bsize; //bytes
323
324                         LOGD("[Queue2] the number of available blocks : %"G_GUINT64_FORMAT
325                                                 ", the block size is %"G_GUINT64_FORMAT".\n",
326                                                 (guint64)buf.f_bavail, (guint64)buf.f_bsize);
327
328                         LOGD("[Queue2] calculated available storage size is %"
329                                                                 G_GUINT64_FORMAT" Bytes.\n", storage_available_size);
330
331                         if (content_size <= 0 || content_size >= storage_available_size)
332                                 buffer_size = storage_available_size;
333                         else
334                                 buffer_size = 0L;
335
336                         g_snprintf(file_buffer_name, MM_MAX_URL_LEN, "%sXXXXXX", file_path);
337                         SECURE_LOGD("[Queue2] the buffering file name is %s.\n", file_buffer_name);
338
339                         g_object_set(G_OBJECT(buffer_handle->buffer), "temp-template", file_buffer_name, NULL);
340                 }
341         } else {
342                 buffer_size = (guint64)((streamer->ring_buffer_size > 0) ? (streamer->ring_buffer_size) : DEFAULT_RING_BUFFER_SIZE);
343         }
344
345         LOGW("[Queue2] set ring buffer size: %"G_GUINT64_FORMAT, buffer_size);
346         g_object_set(G_OBJECT(buffer_handle->buffer), "ring-buffer-max-size", buffer_size, NULL);
347
348         MMPLAYER_FLEAVE();
349         return;
350 }
351
352 static void
353 streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gint buffering_time)
354 {
355         streaming_buffer_t* buffer_handle = NULL;
356
357         MMPLAYER_FENTER();
358
359         MMPLAYER_RETURN_IF_FAIL(streamer);
360         MMPLAYER_RETURN_IF_FAIL(buffering_bytes > 0);
361         MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
362
363         buffer_handle = &(streamer->buffer_handle[type]);
364
365         if (buffer_handle && buffer_handle->buffer) {
366                 if (g_strrstr(GST_ELEMENT_NAME(buffer_handle->buffer), "multiqueue")) {
367                         if (buffering_time <= 0)
368                                 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
369
370                         g_object_set(G_OBJECT(buffer_handle->buffer),
371                                                         "max-size-bytes", GET_MAX_BUFFER_BYTES(streamer),       /* mq size is fixed, control it with high/low percent value*/
372                                                         "max-size-time", (guint64)(buffering_time * GST_MSECOND),
373                                                         "max-size-buffers", 0, NULL);                                           /* disable */
374
375                         buffer_handle->buffering_time = buffering_time;
376                         buffer_handle->buffering_bytes = GET_MAX_BUFFER_BYTES(streamer);
377
378                         LOGD("max-size-time : %d ms", buffering_time);
379                 } else {
380                         /* queue2 */
381                         if (buffer_handle->is_live)
382                                 g_object_set(G_OBJECT(buffer_handle->buffer),
383                                                                 "max-size-bytes", buffering_bytes,
384                                                                 "max-size-time", (guint64)(buffering_time*GST_MSECOND),
385                                                                 "max-size-buffers", 0,
386                                                                 "use-rate-estimate", TRUE, NULL);
387                         else
388                                 g_object_set(G_OBJECT(buffer_handle->buffer),
389                                                                 "max-size-bytes", buffering_bytes,
390                                                                 "max-size-time", (guint64)0,
391                                                                 "max-size-buffers", 0,
392                                                                 "use-rate-estimate", FALSE, NULL);
393
394                         buffer_handle->buffering_bytes = buffering_bytes;
395                         buffer_handle->buffering_time = buffering_time;
396
397                         LOGD("max-size-bytes : %d", buffering_bytes);
398                 }
399         }
400
401         MMPLAYER_FLEAVE();
402         return;
403 }
404
405 void __mm_player_streaming_set_queue2(mm_player_streaming_t* streamer,
406                                                                                 GstElement* buffer,
407                                                                                 gboolean use_buffering,
408                                                                                 guint buffering_bytes,
409                                                                                 gint buffering_time,
410                                                                                 MuxedBufferType type,
411                                                                                 gchar* file_path,
412                                                                                 guint64 content_size)
413 {
414         MMPLAYER_FENTER();
415         MMPLAYER_RETURN_IF_FAIL(streamer);
416
417         if (buffer) {
418                 LOGD("USE-BUFFERING : %s", (use_buffering) ? "OOO" : "XXX");
419
420                 streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer = buffer;
421
422                 if (use_buffering) {
423                         streamer->streaming_buffer_type = BUFFER_TYPE_MUXED;
424
425                         if (content_size > 0) {
426                                 if (streamer->buffering_req.prebuffer_time > 0)
427                                         streamer->buffering_req.is_pre_buffering = TRUE;
428                                 else
429                                         streamer->buffering_req.prebuffer_time = buffering_time;
430                         } else {
431                                 LOGD("live streaming without mq");
432
433                                 streamer->buffer_handle[BUFFER_TYPE_MUXED].is_live = TRUE;
434                                 streamer->buffering_req.prebuffer_time = buffering_time = DEFAULT_BUFFERING_TIME;
435                         }
436                 }
437
438                 g_object_set(G_OBJECT(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL);
439         }
440
441         /* initial setting */
442         streaming_set_buffer_size(streamer, BUFFER_TYPE_MUXED, buffering_bytes, buffering_time);
443         streaming_set_buffer_percent(streamer, BUFFER_TYPE_MUXED, DEFAULT_BUFFER_HIGH_PERCENT, 0);
444         if (type < MUXED_BUFFER_TYPE_MAX)
445                 streaming_set_queue2_queue_type(streamer, type, file_path, content_size);
446
447         MMPLAYER_FLEAVE();
448         return;
449 }
450
451 void __mm_player_streaming_sync_property(mm_player_streaming_t* streamer, GstElement* decodebin)
452 {
453         streaming_buffer_t* buffer_handle = NULL;
454
455         MMPLAYER_FENTER();
456
457         MMPLAYER_RETURN_IF_FAIL(streamer && decodebin);
458
459         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
460
461         if ((streamer->need_sync) && (streamer->streaming_buffer_type == BUFFER_TYPE_DEMUXED)) {
462                 g_object_set(G_OBJECT(decodebin),
463                                         "max-size-bytes", buffer_handle->buffering_bytes,
464                                         "max-size-time", (guint64)(buffer_handle->buffering_time * GST_MSECOND),
465                                         "high-percent", (gint)buffer_handle->buffer_high_percent, NULL);
466         }
467
468         streamer->need_sync = FALSE;
469 }
470
471 void __mm_player_streaming_set_multiqueue(mm_player_streaming_t* streamer,
472                                                                                 GstElement* buffer,
473                                                                                 gint buffering_time)
474 {
475         streaming_buffer_t* buffer_handle = NULL;
476         gdouble high_percent = 0.0;
477
478         MMPLAYER_FENTER();
479         MMPLAYER_RETURN_IF_FAIL(streamer && buffer);
480
481         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
482
483         buffer_handle->buffer = buffer;
484
485         streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
486         g_object_set(G_OBJECT(buffer_handle->buffer), "use-buffering", TRUE, NULL);
487
488
489         LOGD("pre_buffering: %d ms, during playing: %d ms\n", streamer->buffering_req.prebuffer_time, buffering_time);
490
491         if (streamer->buffering_req.prebuffer_time > 0)
492                 streamer->buffering_req.is_pre_buffering = TRUE;
493         else
494                 streamer->buffering_req.prebuffer_time = GET_DEFAULT_PLAYING_TIME(streamer);
495
496         high_percent = (gdouble)(streamer->buffering_req.prebuffer_time * 100) / GET_MAX_BUFFER_TIME(streamer);
497         LOGD("high_percent %2.3f %%\n", high_percent);
498
499         /* initial setting */
500         streaming_set_buffer_size(streamer, BUFFER_TYPE_DEMUXED, GET_MAX_BUFFER_BYTES(streamer), GET_MAX_BUFFER_TIME(streamer));
501         streaming_set_buffer_percent(streamer, BUFFER_TYPE_DEMUXED, 0, high_percent);
502
503         streamer->need_sync = TRUE;
504
505         MMPLAYER_FLEAVE();
506         return;
507 }
508
509 static void
510 streaming_get_current_bitrate_info(mm_player_streaming_t* streamer,
511                                                                         GstMessage *buffering_msg,
512                                                                         streaming_content_info_t content_info,
513                                                                         streaming_bitrate_info_t* bitrate_info)
514 {
515
516         GstQuery *query = NULL;
517         GstBufferingMode mode = GST_BUFFERING_STREAM;
518         gint in_rate = 0;
519         gint out_rate = 0;
520         gint64 buffering_left = -1;
521
522         guint buffer_criteria = 0;
523         guint estimated_content_bitrate = 0;
524
525         gint buffer_buffering_time = DEFAULT_BUFFERING_TIME;
526
527         MMPLAYER_FENTER();
528
529         MMPLAYER_RETURN_IF_FAIL(streamer);
530         MMPLAYER_RETURN_IF_FAIL(bitrate_info);
531
532         if ((buffering_msg == NULL) ||
533                 ((streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer != NULL) &&
534                 (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer != NULL) &&
535                 (buffering_msg->src == (GstObject *)streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer))) {
536                 query = gst_query_new_buffering(GST_FORMAT_PERCENT);
537
538                 if (gst_element_query((streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), query))
539                         gst_query_parse_buffering_stats(query, &mode, &in_rate, &out_rate, &buffering_left);
540                 gst_query_unref(query);
541         } else {
542                 gst_message_parse_buffering_stats(buffering_msg, &mode, &in_rate, &out_rate, &buffering_left);
543         }
544
545         LOGD("Streaming Info : in %d, out %d, left %"G_GINT64_FORMAT, in_rate, out_rate, buffering_left);
546
547         if ((content_info.content_size > 0) && (content_info.duration > 0) && ((content_info.duration/GST_SECOND) > 0))
548                 estimated_content_bitrate = GET_BIT_FROM_BYTE((guint)(content_info.content_size / (content_info.duration/GST_SECOND)));
549
550         if (streamer->buffer_max_bitrate > 0) {
551                 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, streamer->buffer_avg_bitrate);
552                 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, estimated_content_bitrate);
553
554                 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate);
555
556                 if (streamer->buffer_avg_bitrate > estimated_content_bitrate)
557                         out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate);
558                 else if (estimated_content_bitrate != 0)
559                         out_rate = GET_BYTE_FROM_BIT(estimated_content_bitrate);
560                 else
561                         out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate/3);
562
563                 LOGD("(max)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
564         } else if (streamer->buffer_avg_bitrate > 0) {
565                 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3);
566                 out_rate = GET_BYTE_FROM_BIT(MAX(streamer->buffer_avg_bitrate, estimated_content_bitrate));
567
568                 LOGD("(avg)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
569         } else {
570                 LOGW("There is no content bitrate information\n");
571         }
572
573         if ((in_rate > 0) && (out_rate > 0))
574                 buffer_buffering_time =  (gint)(out_rate / in_rate)*1000;
575         else if ((in_rate <= 0) && (out_rate > 0))
576                 buffer_buffering_time = MAX_BUFFERING_TIME;
577         else
578                 buffer_buffering_time = DEFAULT_BUFFERING_TIME;
579
580         (*bitrate_info).byte_in_rate = in_rate;
581         (*bitrate_info).byte_out_rate = out_rate;
582         (*bitrate_info).time_rate = buffer_buffering_time;
583         (*bitrate_info).buffer_criteria = buffer_criteria;
584 }
585
586 static void
587 streaming_handle_fixed_buffering_mode(mm_player_streaming_t* streamer,
588                                                                                 gint byte_out_rate,
589                                                                                 gint fixed_buffering_time,
590                                                                                 streaming_buffer_info_t* buffer_info)
591 {
592         streaming_buffer_t* buffer_handle = NULL;
593
594         guint buffering_bytes = 0;
595         gint buffering_time = 0;
596         gdouble per_byte = 0.0;
597         gdouble per_time = 0.0;
598
599         MMPLAYER_RETURN_IF_FAIL(streamer);
600         MMPLAYER_RETURN_IF_FAIL(buffer_info);
601
602         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
603         buffering_time = fixed_buffering_time;
604
605         LOGD("buffering time: %d ms, out rate: %d\n", buffering_time, byte_out_rate);
606
607         if ((buffering_time > 0) && (byte_out_rate > 0)) {
608                 buffering_bytes = (guint)GET_NEW_BUFFERING_BYTE((gdouble)(byte_out_rate * buffering_time)/1000);
609         } else {
610                 if (buffering_time <= 0)
611                         buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
612
613                 LOGW("content bitrate is not updated yet.\n");
614                 buffering_bytes = GET_CURRENT_BUFFERING_BYTE(buffer_handle);
615         }
616
617         GET_PERCENT(buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
618         GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
619
620         LOGD("bytes %d, time %d, per_byte %f, per_time %f\n", buffering_bytes, buffering_time, per_byte, per_time);
621
622         (*buffer_info).buffering_bytes = buffering_bytes;
623         (*buffer_info).buffering_time = buffering_time;
624         (*buffer_info).percent_byte = per_byte;
625         (*buffer_info).percent_time = per_time;
626 }
627
628 static void
629 streaming_handle_adaptive_buffering_mode(mm_player_streaming_t* streamer,
630                                                                                 streaming_content_info_t content_info,
631                                                                                 streaming_bitrate_info_t bitrate_info,
632                                                                                 streaming_buffer_info_t* buffer_info,
633                                                                                 gint expected_play_time)
634 {
635         streaming_buffer_t* buffer_handle = NULL;
636
637         gint buffering_bytes = 0;
638         gint adj_buffering_bytes = 0;
639         gint buffer_buffering_time = 0;
640         gdouble per_byte = 0.0;
641         gdouble per_time = 0.0;
642         gdouble portion = 0.0;
643         gint default_buffering_time = 0;
644
645         MMPLAYER_RETURN_IF_FAIL(streamer);
646         MMPLAYER_RETURN_IF_FAIL(buffer_info);
647
648         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\n",
649                                                         content_info.position, content_info.duration, content_info.content_size,
650                                                         bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
651                                                         bitrate_info.buffer_criteria, bitrate_info.time_rate, expected_play_time);
652
653         if ((content_info.duration <= 0) ||
654                 (content_info.content_size <= 0)) {
655                 LOGW("keep previous setting.\n");
656                 return;
657         }
658
659         if ((bitrate_info.byte_out_rate <= 0) || (bitrate_info.buffer_criteria == 0)) {
660                 LOGW("keep previous setting.\n");
661                 return;
662         }
663
664         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
665
666         if (bitrate_info.byte_in_rate < bitrate_info.byte_out_rate) {
667                 portion = (double)(expected_play_time * GST_MSECOND) / (double)content_info.duration;
668                 buffering_bytes = GET_NEW_BUFFERING_BYTE(((double)content_info.content_size * portion)  \
669                                                                                                                         * (1 - (double)bitrate_info.byte_in_rate/(double)bitrate_info.byte_out_rate));
670         } else {
671                 /* buffering_bytes will be set as streamer->default_val.buffering_time *
672                  * receiving rate is bigger than avg content bitrate
673                  * so there is no reason to buffering. if the buffering msg is posted
674                  * in-rate or contents bitrate has wrong value. */
675                 LOGW("don't need to do buffering.\n");
676         }
677
678         if (buffering_bytes > 0)
679                 buffer_buffering_time = (gint)(buffering_bytes / bitrate_info.byte_out_rate)*1000;
680
681         if (content_info.position <= 0) {
682                 /* if the buffer is filled under 50%, MSL use the original default buffering time.
683                    if not, MSL use just 2 sec as a default buffering time. (to reduce initial buffering time) */
684                 default_buffering_time = streamer->default_val.buffering_time - ((gdouble)streamer->buffering_percent/50)*1000;
685         } else {
686                 default_buffering_time = streamer->default_val.buffering_time;
687         }
688
689         if (buffer_buffering_time < default_buffering_time) {
690                 LOGD("adjusted time: %d -> %d ms\n", buffer_buffering_time, default_buffering_time);
691                 LOGD("adjusted bytes : %d or %d or %d\n",
692                         buffering_bytes,
693                         (gint)(bitrate_info.byte_out_rate * buffer_buffering_time/1000),
694                         (gint)(bitrate_info.buffer_criteria * buffer_buffering_time/1000));
695
696                 /* start monitoring the abmormal state */
697                 if (content_info.position > 0)
698                         streamer->default_val.buffering_monitor = TRUE;
699
700                 buffer_buffering_time = default_buffering_time;
701                 adj_buffering_bytes = GET_NEW_BUFFERING_BYTE(bitrate_info.byte_out_rate * (gint)ceil((gdouble)buffer_buffering_time/1000));
702                 buffering_bytes = MAX(buffering_bytes, adj_buffering_bytes);
703         }
704
705         GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
706         GET_PERCENT(buffer_buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
707
708         LOGD("monitor %d, bytes %d, time %d, per_byte %f, per_time %f\n",
709                                                                                 streamer->default_val.buffering_monitor,
710                                                                                 buffering_bytes, buffer_buffering_time, per_byte, per_time);
711
712         (*buffer_info).buffering_bytes = buffering_bytes;
713         (*buffer_info).buffering_time = buffer_buffering_time;
714         (*buffer_info).percent_byte = per_byte;
715         (*buffer_info).percent_time = per_time;
716
717 }
718
719 static void
720 streaming_update_buffer_setting(mm_player_streaming_t* streamer,
721                                                                         GstMessage *buffering_msg,      /* can be null */
722                                                                         guint64 content_size,
723                                                                         gint64 position,
724                                                                         gint64 duration)
725 {
726         streaming_buffer_t* buffer_handle = NULL;
727         MMPlayerBufferingMode buffering_mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
728
729         streaming_buffer_info_t buffer_info;
730         streaming_content_info_t content_info;
731         streaming_bitrate_info_t bitrate_info;
732
733         MMPLAYER_FENTER();
734
735         MMPLAYER_RETURN_IF_FAIL(streamer);
736
737         memset(&buffer_info, 0x00, sizeof(streaming_buffer_info_t));
738         memset(&content_info, 0x00, sizeof(streaming_content_info_t));
739         memset(&bitrate_info, 0x00, sizeof(streaming_bitrate_info_t));
740
741         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
742
743         if (streamer->buffering_req.is_pre_buffering == TRUE)
744                 buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
745         else
746                 buffering_mode = streamer->buffering_req.mode;
747
748         buffer_info.buffering_bytes = buffer_handle->buffering_bytes;
749         buffer_info.buffering_time = buffer_handle->buffering_time;
750         buffer_info.percent_byte = buffer_handle->buffer_high_percent;
751         buffer_info.percent_time = buffer_handle->buffer_high_percent;
752
753         content_info.position = position;
754         content_info.duration = duration;
755         content_info.content_size = content_size;
756
757         streaming_get_current_bitrate_info(streamer, buffering_msg, content_info, &bitrate_info);
758
759         LOGD("buffering mode %d, new info in_r:%d, out_r:%d, cb:%d, bt:%d\n",
760                                         buffering_mode, bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
761                                         bitrate_info.buffer_criteria, bitrate_info.time_rate);
762
763         if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED) {
764                 /********************
765                  * (1) fixed mode   *
766                  ********************/
767                 gint buffering_time = 0;
768
769                 if (streamer->buffering_req.is_pre_buffering == TRUE)
770                         buffering_time = streamer->buffering_req.prebuffer_time;
771                 else
772                         buffering_time = streamer->buffering_req.rebuffer_time;
773
774                 streaming_handle_fixed_buffering_mode(streamer, bitrate_info.byte_out_rate, buffering_time, &buffer_info);
775         } else {
776                 /*********************************
777                  * (2) adaptive mode (default)   *
778                  *********************************/
779                 gint expected_play_time = DEFAULT_PLAYING_TIME;
780
781                 if (streamer->buffering_req.rebuffer_time > 0)
782                         expected_play_time = streamer->buffering_req.rebuffer_time;
783                 else if ((position == 0) && (streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS))
784                         expected_play_time = streamer->buffering_req.prebuffer_time;
785
786                 if (expected_play_time <= 0)
787                         expected_play_time = DEFAULT_PLAYING_TIME;
788
789                 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, expected_play_time);
790
791                 if (IS_MUXED_BUFFERING_MODE(streamer))  // even if new byte size is smaller than the previous one, time need to be updated.
792                         buffer_handle->buffering_time = buffer_info.buffering_time;
793         }
794
795         LOGD("adj buffer(%d) %d->%d bytes/%d->%d ms\n",
796                                         streamer->streaming_buffer_type,
797                                         GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_info.buffering_bytes,
798                                         GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_info.buffering_time);
799
800         /* queue2 : bytes, multiqueue : time */
801         if (((GET_CURRENT_BUFFERING_BYTE(buffer_handle) < buffer_info.buffering_bytes) && IS_MUXED_BUFFERING_MODE(streamer)) ||
802                 ((GET_CURRENT_BUFFERING_TIME(buffer_handle) < buffer_info.buffering_time) && IS_DEMUXED_BUFFERING_MODE(streamer))) {
803                 if (duration > 0 && position > 0) {
804                         gint buffering_time_limit = (gint)(duration - position)/GST_MSECOND;
805
806                         if (buffer_info.buffering_time > buffering_time_limit)
807                                 buffer_info.buffering_time = buffering_time_limit;
808                 }
809
810                 streaming_set_buffer_size(streamer, streamer->streaming_buffer_type, buffer_info.buffering_bytes, buffer_info.buffering_time);
811         }
812
813         streaming_set_buffer_percent(streamer, streamer->streaming_buffer_type, buffer_info.percent_byte, buffer_info.percent_time);
814
815         LOGD("buffer setting: size %d, time %d, per %f\n",
816                                                         GET_CURRENT_BUFFERING_BYTE(buffer_handle),
817                                                         GET_CURRENT_BUFFERING_TIME(buffer_handle),
818                                                         buffer_handle->buffer_high_percent);
819
820         streamer->need_sync = TRUE;
821 }
822
823 static void
824 streaming_adjust_min_threshold(mm_player_streaming_t* streamer, gint64 position)
825 {
826 #define DEFAULT_TIME_PAD 1000   /* ms */
827         gint playing_time = 0;
828
829         MMPLAYER_FENTER();
830
831         MMPLAYER_RETURN_IF_FAIL(streamer);
832
833         playing_time = (gint)((position - streamer->default_val.prev_pos) / GST_MSECOND);
834
835         LOGD("buffering monitor = %s", (streamer->default_val.buffering_monitor) ? "ON" : "OFF");
836         LOGD("playing_time (%d ms) = %"G_GINT64_FORMAT" - %"G_GINT64_FORMAT, playing_time, position, streamer->default_val.prev_pos);
837         LOGD("default time : %d, prev buffering t : %d",
838                                         streamer->default_val.buffering_time, streamer->buffer_handle[streamer->streaming_buffer_type].buffering_time);
839
840         if ((streamer->default_val.buffering_monitor) && (playing_time <= streamer->default_val.buffering_time)) {
841                 gint time_gap = 0;
842                 time_gap = streamer->default_val.buffering_time - DEFAULT_BUFFERING_TIME;
843                 if (time_gap <= 0)
844                         time_gap = DEFAULT_TIME_PAD;
845
846                 streamer->default_val.buffering_time += time_gap*2;
847                 streamer->default_val.buffering_time = MIN(streamer->default_val.buffering_time, MAX_BUFFERING_TIME);
848         } else {
849                 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
850         }
851
852         LOGD("new default min value %d \n", streamer->default_val.buffering_time);
853
854         streamer->default_val.buffering_monitor = FALSE;
855         streamer->default_val.prev_pos = position;
856 }
857
858 static void
859 streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position)
860 {
861         gint buffer_percent = 0;
862
863         MMPLAYER_FENTER();
864
865         MMPLAYER_RETURN_IF_FAIL(streamer);
866         MMPLAYER_RETURN_IF_FAIL(buffering_msg);
867
868         /* update when buffering has started. */
869         if (!(streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
870                 streamer->buffering_state = MM_PLAYER_BUFFERING_IN_PROGRESS;
871                 streamer->buffering_percent = -1;
872
873                 if (!streamer->buffering_req.is_pre_buffering) {
874                         streamer->need_update = TRUE;
875                         streaming_adjust_min_threshold(streamer, position);
876                 }
877         }
878
879         /* update buffer percent */
880         gst_message_parse_buffering(buffering_msg, &buffer_percent);
881
882         /* LOGD("[%s] buffering per %d%% -> %d%%, state 0x%X", streamer->buffering_percent, buffer_percent, streamer->buffering_state); */
883
884         if (streamer->buffering_percent < buffer_percent) {
885                 LOGD("[%s] buffering %d%%....",
886                         GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
887                 streamer->buffering_percent = buffer_percent;
888         }
889
890         if (streamer->buffering_percent == MAX_BUFFER_PERCENT) {
891                 streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
892                 streamer->buffering_req.is_pre_buffering = FALSE;
893         } else if (streamer->buffering_state & MM_PLAYER_BUFFERING_COMPLETE) {
894                 streamer->buffering_state = MM_PLAYER_BUFFERING_COMPLETE; /* have to keep state to ignore remained msg till get 100% msg */
895                 streamer->buffering_req.is_pre_buffering = FALSE;
896                 streamer->buffering_percent = MAX_BUFFER_PERCENT;
897                 LOGD("updated to the buffering 100%%.... (by force)");
898         }
899 }
900
901 void __mm_player_streaming_buffering(mm_player_streaming_t* streamer,
902                                                                                 GstMessage *buffering_msg,
903                                                                                 guint64 content_size,
904                                                                                 gint64 position,
905                                                                                 gint64 duration)
906 {
907         MMPLAYER_FENTER();
908
909         MMPLAYER_RETURN_IF_FAIL(streamer);
910         MMPLAYER_RETURN_IF_FAIL(buffering_msg);
911         MMPLAYER_RETURN_IF_FAIL(GST_IS_MESSAGE(buffering_msg));
912         MMPLAYER_RETURN_IF_FAIL((GST_MESSAGE_TYPE(buffering_msg) == GST_MESSAGE_BUFFERING));
913
914         if (position > (gint64)(streamer->buffering_req.prebuffer_time * GST_MSECOND))
915                 streamer->buffering_req.is_pre_buffering = FALSE;
916
917         streaming_update_buffering_status(streamer, buffering_msg, position);
918
919         if (!streamer->need_update)
920                 return;
921
922         streamer->need_update = FALSE;
923         streaming_update_buffer_setting(streamer, buffering_msg, content_size, position, duration);
924
925         return;
926 }