change default buffering type from file to mem
[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 #define TO_THE_END 0
29
30 typedef struct{
31         gint byte_in_rate;              // byte
32         gint byte_out_rate;             // byte
33         gdouble time_rate;              // second
34         guint buffer_criteria;  // byte
35 }streaming_bitrate_info_t;
36
37 typedef struct{
38         gint64 position;        // ns
39         gint64 duration;        // ns
40         guint64 content_size;   // bytes
41 }streaming_content_info_t;
42
43 typedef struct{
44         guint buffering_bytes;          // bytes
45         gdouble buffering_time;         // second
46         gdouble percent_byte;
47         gdouble percent_time;
48 }streaming_buffer_info_t;
49
50 static void streaming_check_buffer_percent(gdouble in_low, gdouble in_high, gdouble *out_low, gdouble *out_high);
51 static void streaming_set_buffer_percent(mm_player_streaming_t* streamer, BufferType type, gdouble low_percent, gdouble high_percent_byte, gdouble high_percent_time);
52 static void streaming_set_queue2_queue_type (mm_player_streaming_t* streamer, muxed_buffer_type_e type, gchar * file_path, guint64 content_size);
53 static void streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gdouble buffering_time);
54 static void streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position);
55 static void streaming_get_current_bitrate_info( mm_player_streaming_t* streamer,
56                                                                                                 GstMessage *buffering_msg,
57                                                                                                 streaming_content_info_t content_info,
58                                                                                                 streaming_bitrate_info_t* bitrate_info);
59 static void
60 streaming_handle_fixed_buffering_mode(  mm_player_streaming_t* streamer,
61                                                                                 gint byte_out_rate,
62                                                                                 gdouble fixed_buffering_time,
63                                                                                 streaming_buffer_info_t* buffer_info);
64 static void
65 streaming_handle_adaptive_buffering_mode(       mm_player_streaming_t* streamer,
66                                                                                         streaming_content_info_t content_info,
67                                                                                         streaming_bitrate_info_t bitrate_info,
68                                                                                         streaming_buffer_info_t* buffer_info,
69                                                                                         gint expected_play_time);
70 static void
71 streaming_update_buffer_setting (       mm_player_streaming_t* streamer,
72                                                                         GstMessage *buffering_msg,
73                                                                         guint64 content_size,
74                                                                         gint64 position,
75                                                                         gint64 duration);
76
77 mm_player_streaming_t *
78 __mm_player_streaming_create (void)
79 {
80         mm_player_streaming_t *streamer = NULL;
81
82         MMPLAYER_FENTER();
83
84         streamer = (mm_player_streaming_t *) malloc (sizeof (mm_player_streaming_t));
85         if (!streamer)
86         {
87                 LOGE ("fail to create streaming player handle..\n");
88                 return NULL;
89         }
90
91         memset(streamer, 0, sizeof(mm_player_streaming_t));
92
93         MMPLAYER_FLEAVE();
94
95         return streamer;
96 }
97
98 static void
99 streaming_buffer_initialize (streaming_buffer_t* buffer_handle, gboolean buffer_init)
100 {
101         if (buffer_init)
102                 buffer_handle->buffer = NULL;
103
104         buffer_handle->buffering_bytes = DEFAULT_BUFFER_SIZE_BYTES;
105         buffer_handle->buffering_time = DEFAULT_BUFFERING_TIME;
106         buffer_handle->buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
107         buffer_handle->buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
108         buffer_handle->is_live = FALSE;
109
110 }
111
112 void __mm_player_streaming_initialize (mm_player_streaming_t* streamer)
113 {
114         MMPLAYER_FENTER();
115
116         streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT;  // multi-queue
117
118         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), TRUE);
119         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), TRUE);
120
121         streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
122         streamer->buffering_req.is_pre_buffering = FALSE;
123         streamer->buffering_req.initial_second = 0;
124         streamer->buffering_req.runtime_second = 0;
125
126         streamer->default_val.buffering_monitor = FALSE;
127         streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
128
129         streamer->buffer_avg_bitrate = 0;
130         streamer->buffer_max_bitrate = 0;
131         streamer->need_update = FALSE;
132         streamer->need_sync = FALSE;
133
134         streamer->is_buffering = FALSE;
135         streamer->is_buffering_done = FALSE;
136         streamer->is_adaptive_streaming = FALSE;
137         streamer->buffering_percent = -1;
138
139         streamer->ring_buffer_size = DEFAULT_RING_BUFFER_SIZE;
140         MMPLAYER_FLEAVE();
141         return;
142 }
143
144 void __mm_player_streaming_deinitialize (mm_player_streaming_t* streamer)
145 {
146         MMPLAYER_FENTER();
147         MMPLAYER_RETURN_IF_FAIL(streamer);
148
149         streamer->streaming_buffer_type = BUFFER_TYPE_DEFAULT;  // multi-queue
150
151         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_MUXED]), FALSE);
152         streaming_buffer_initialize(&(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]), FALSE);
153
154         streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
155         streamer->buffering_req.is_pre_buffering = FALSE;
156         streamer->buffering_req.initial_second = 0;
157         streamer->buffering_req.runtime_second = 0;
158
159         streamer->default_val.buffering_monitor = FALSE;
160         streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
161
162         streamer->buffer_avg_bitrate = 0;
163         streamer->buffer_max_bitrate = 0;
164         streamer->need_update = FALSE;
165         streamer->need_sync = FALSE;
166
167         streamer->is_buffering = FALSE;
168         streamer->is_buffering_done = FALSE;
169         streamer->is_adaptive_streaming = FALSE;
170
171         streamer->buffering_percent = -1;
172         streamer->ring_buffer_size = DEFAULT_RING_BUFFER_SIZE;
173
174         MMPLAYER_FLEAVE();
175         return;
176 }
177
178 void __mm_player_streaming_destroy (mm_player_streaming_t* streamer)
179 {
180         MMPLAYER_FENTER();
181
182         if(streamer)
183         {
184                 g_free (streamer);
185                 streamer = NULL;
186         }
187
188         MMPLAYER_FLEAVE();
189
190         return;
191 }
192
193 void __mm_player_streaming_set_content_bitrate(mm_player_streaming_t* streamer, guint max_bitrate, guint avg_bitrate)
194 {
195         MMPLAYER_FENTER();
196
197         MMPLAYER_RETURN_IF_FAIL(streamer);
198
199         /* Note : Update buffering criterion bytes
200         *      1. maximum bitrate is considered first.
201         *      2. average bitrage * 3 is next.
202         *      3. if there are no updated bitrate, use default buffering limit.
203         */
204         if (max_bitrate > 0 && streamer->buffer_max_bitrate != max_bitrate)
205         {
206                 LOGD("set maximum bitrate(%dbps).\n", max_bitrate);
207                 streamer->buffer_max_bitrate = max_bitrate;
208                 if (streamer->buffering_req.is_pre_buffering == FALSE)
209                 {
210                         streamer->need_update = TRUE;
211                 }
212                 else
213                 {
214                         LOGD("pre-buffering...\n");
215
216                         if (IS_MUXED_BUFFERING_MODE(streamer))
217                                 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
218                 }
219         }
220
221         if (avg_bitrate > 0 && streamer->buffer_avg_bitrate != avg_bitrate)
222         {
223                 LOGD("set averate bitrate(%dbps).\n", avg_bitrate);
224                 streamer->buffer_avg_bitrate = avg_bitrate;
225
226                 if (streamer->buffering_req.is_pre_buffering == FALSE)
227                 {
228                         streamer->need_update = TRUE;
229                 }
230                 else
231                 {
232                         LOGD("pre-buffering...\n");
233
234                         if (IS_MUXED_BUFFERING_MODE(streamer))
235                                 streaming_update_buffer_setting(streamer, NULL, 0, 0, 0);
236                 }
237         }
238
239         MMPLAYER_FLEAVE();
240         return;
241 }
242
243 static void
244 streaming_check_buffer_percent(gdouble in_low, gdouble in_high, gdouble *out_low, gdouble *out_high)
245 {
246         gdouble buffer_low_percent = DEFAULT_BUFFER_LOW_PERCENT;
247         gdouble buffer_high_percent = DEFAULT_BUFFER_HIGH_PERCENT;
248
249         MMPLAYER_FENTER();
250
251         MMPLAYER_RETURN_IF_FAIL(out_low && out_high);
252
253         if (in_low <= MIN_BUFFER_PERCENT || in_low >= MAX_BUFFER_PERCENT)
254         {
255                 LOGW("buffer low percent is out of range. use defaut value.");
256         }
257         else
258         {
259                 buffer_low_percent = in_low;
260         }
261
262         if (in_high  <=  MIN_BUFFER_PERCENT || in_high  >=  MAX_BUFFER_PERCENT)
263         {
264                 LOGW("buffer high percent is out of range. use defaut value.");
265         }
266         else
267         {
268                 buffer_high_percent = in_high;
269         }
270
271         if (buffer_high_percent <= buffer_low_percent)
272                 buffer_high_percent =  buffer_low_percent + 1.0;
273
274         LOGD("set buffer percent to %2.3f ~ %2.3f.",  buffer_low_percent, buffer_high_percent);
275
276         *out_low = buffer_low_percent;
277         *out_high = buffer_high_percent;
278 }
279
280 static void
281 streaming_set_buffer_percent(   mm_player_streaming_t* streamer,
282                                                                 BufferType type,
283                                                                 gdouble low_percent,
284                                                                 gdouble high_percent_byte,
285                                                                 gdouble high_percent_time)
286 {
287         gdouble confirmed_low = DEFAULT_BUFFER_LOW_PERCENT;
288         gdouble confirmed_high = DEFAULT_BUFFER_HIGH_PERCENT;
289         gdouble high_percent = 0.0;
290
291         streaming_buffer_t* buffer_handle = NULL;
292         gchar* factory_name = NULL;
293
294         MMPLAYER_FENTER();
295         MMPLAYER_RETURN_IF_FAIL(streamer);
296         MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
297
298         buffer_handle = &(streamer->buffer_handle[type]);
299         if (!(buffer_handle && buffer_handle->buffer))
300         {
301                 LOGE("buffer_handle->buffer is NULL!");
302                 return;
303         }
304
305         factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
306
307         if (!factory_name)
308         {
309                 LOGE("Fail to get factory name!");
310                 return;
311         }
312
313         if (type == BUFFER_TYPE_MUXED)
314                 high_percent = high_percent_byte;
315         else
316                 high_percent = MAX(high_percent_time, high_percent_byte);
317
318         streaming_check_buffer_percent(low_percent, high_percent, &confirmed_low, &confirmed_high);
319
320         /* if use-buffering is disabled, this settings do not have any meaning. */
321         LOGD("target buffer elem : %s (%2.3f ~ %2.3f)",
322                 GST_ELEMENT_NAME(buffer_handle->buffer), confirmed_low, confirmed_high);
323
324         if ((confirmed_low == DEFAULT_BUFFER_LOW_PERCENT) ||
325                 (buffer_handle->buffer_low_percent != confirmed_low))
326         {
327                 g_object_set (G_OBJECT(buffer_handle->buffer), "low-percent", (gint)confirmed_low, NULL);
328         }
329
330         if ((confirmed_high == DEFAULT_BUFFER_HIGH_PERCENT) ||
331                 (buffer_handle->buffer_high_percent != confirmed_high))
332         {
333                 g_object_set (G_OBJECT(buffer_handle->buffer), "high-percent", (gint)confirmed_high, NULL);
334         }
335
336         buffer_handle->buffer_low_percent = confirmed_low;
337         buffer_handle->buffer_high_percent = confirmed_high;
338
339         MMPLAYER_FLEAVE();
340         return;
341 }
342
343 static void
344 streaming_set_queue2_queue_type (mm_player_streaming_t* streamer, muxed_buffer_type_e type, gchar * file_path, guint64 content_size)
345 {
346         streaming_buffer_t* buffer_handle = NULL;
347         guint64 storage_available_size = 0L; //bytes
348         guint64 buffer_size = 0L;  //bytes
349         gchar file_buffer_name[MM_MAX_URL_LEN] = {0};
350         struct statfs buf = {0};
351         gchar* factory_name = NULL;
352
353         MMPLAYER_FENTER();
354         MMPLAYER_RETURN_IF_FAIL(streamer);
355         MMPLAYER_RETURN_IF_FAIL(streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer);
356
357         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_MUXED]);
358
359         if (!(buffer_handle && buffer_handle->buffer))
360         {
361                 LOGE("buffer_handle->buffer is NULL!");
362                 return;
363         }
364
365         factory_name = GST_OBJECT_NAME(gst_element_get_factory(buffer_handle->buffer));
366
367         if (!factory_name)
368         {
369                 LOGE("Fail to get factory name!");
370                 return;
371         }
372
373         LOGD("target buffer elem : %s", GST_ELEMENT_NAME(buffer_handle->buffer));
374
375         if (!g_strrstr(factory_name, "queue2"))
376         {
377                 LOGD("only queue2 can use file buffer. not decodebin2 or multiQ\n");
378                 return;
379         }
380
381         if ((type == MUXED_BUFFER_TYPE_MEM_QUEUE) || (!g_strrstr(factory_name, "queue2")))
382         {
383                 LOGD("use memory queue for buffering. streaming is played on push-based. \n"
384                                         "buffering position would not be updated.\n"
385                                         "buffered data would be flushed after played.\n"
386                                         "seeking and getting duration could be failed due to file format.");
387                 return;
388         }
389
390         LOGD("[Queue2] buffering type : %d. streaming is played on pull-based. \n", type);
391         if (type == MUXED_BUFFER_TYPE_FILE && file_path && strlen(file_path)>0) {
392                 if (statfs((const char *)file_path, &buf) < 0)
393                 {
394                         LOGW ("[Queue2] fail to get available storage capacity. set mem ring buffer instead of file buffer.\n");
395                         buffer_size = (guint64)((streamer->ring_buffer_size>0)?(streamer->ring_buffer_size):DEFAULT_RING_BUFFER_SIZE);
396                 }
397                 else
398                 {
399                         storage_available_size = (guint64)buf.f_bavail * (guint64)buf.f_bsize; //bytes
400
401                         LOGD ("[Queue2] the number of available blocks : %"G_GUINT64_FORMAT
402                                                 ", the block size is %"G_GUINT64_FORMAT".\n",
403                                                 (guint64)buf.f_bavail, (guint64)buf.f_bsize);
404
405                         LOGD ("[Queue2] calculated available storage size is %"
406                                                                 G_GUINT64_FORMAT" Bytes.\n", storage_available_size);
407
408                         if (content_size <= 0 || content_size >= storage_available_size)
409                                 buffer_size = storage_available_size;
410                         else
411                                 buffer_size = 0L;
412
413                         g_snprintf(file_buffer_name, MM_MAX_URL_LEN, "%sXXXXXX", file_path);
414                         SECURE_LOGD("[Queue2] the buffering file name is %s.\n", file_buffer_name);
415
416                         g_object_set (G_OBJECT(buffer_handle->buffer), "temp-template", file_buffer_name, NULL);
417                 }
418         } else {
419                 buffer_size = (guint64)((streamer->ring_buffer_size>0)?(streamer->ring_buffer_size):DEFAULT_RING_BUFFER_SIZE);
420         }
421
422         LOGW ("[Queue2] set ring buffer size: %lld\n", buffer_size);
423         g_object_set (G_OBJECT(buffer_handle->buffer), "ring-buffer-max-size", buffer_size, NULL);
424
425         MMPLAYER_FLEAVE();
426         return;
427 }
428
429 static void
430 streaming_set_buffer_size(mm_player_streaming_t* streamer, BufferType type, guint buffering_bytes, gdouble buffering_time)
431 {
432         streaming_buffer_t* buffer_handle = NULL;
433
434         MMPLAYER_FENTER();
435
436         MMPLAYER_RETURN_IF_FAIL(streamer);
437         MMPLAYER_RETURN_IF_FAIL(buffering_bytes > 0);
438         MMPLAYER_RETURN_IF_FAIL(type < BUFFER_TYPE_MAX);
439
440         buffer_handle = &(streamer->buffer_handle[type]);
441
442         if (buffer_handle && buffer_handle->buffer)
443         {
444                 if (g_strrstr(GST_ELEMENT_NAME(buffer_handle->buffer), "multiqueue"))
445                 {
446                         if (buffering_time <= 0)
447                                 buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
448
449                         g_object_set (G_OBJECT(buffer_handle->buffer),
450                                                         "max-size-bytes", GET_MAX_BUFFER_BYTES(streamer), /* mq size is fixed, control it with high/low percent value*/
451                                                         "max-size-time", ((guint)ceil(buffering_time) * GST_SECOND),
452                                                         "max-size-buffers", 0, NULL);                                     /* disable */
453
454                         buffer_handle->buffering_time = buffering_time;
455                         buffer_handle->buffering_bytes = GET_MAX_BUFFER_BYTES(streamer);
456
457                         LOGD("max-size-time : %f", buffering_time);
458                 }
459                 else    /* queue2 */
460                 {
461                         if (buffer_handle->is_live)
462                         {
463                                 g_object_set (G_OBJECT(buffer_handle->buffer),
464                                                                 "max-size-bytes", buffering_bytes,
465                                                                 "max-size-time", (guint64)(buffering_time*GST_SECOND),
466                                                                 "max-size-buffers", 0,
467                                                                 "use-rate-estimate", TRUE, NULL);
468                         }
469                         else
470                         {
471                                 g_object_set (G_OBJECT(buffer_handle->buffer),
472                                                                 "max-size-bytes", buffering_bytes,
473                                                                 "max-size-time", (guint64)0,
474                                                                 "max-size-buffers", 0,
475                                                                 "use-rate-estimate", FALSE, NULL);
476                         }
477
478                         buffer_handle->buffering_bytes = buffering_bytes;
479                         buffer_handle->buffering_time = buffering_time;
480
481                         LOGD("max-size-bytes : %d", buffering_bytes);
482                 }
483         }
484
485         MMPLAYER_FLEAVE();
486         return;
487 }
488
489 void __mm_player_streaming_set_queue2(  mm_player_streaming_t* streamer,
490                                                                                 GstElement* buffer,
491                                                                                 gboolean use_buffering,
492                                                                                 guint buffering_bytes,
493                                                                                 gdouble buffering_time,
494                                                                                 gdouble low_percent,
495                                                                                 gdouble high_percent,
496                                                                                 muxed_buffer_type_e type,
497                                                                                 gchar* file_path,
498                                                                                 guint64 content_size)
499 {
500         MMPLAYER_FENTER();
501         MMPLAYER_RETURN_IF_FAIL(streamer);
502
503         if (buffer)
504         {
505                 LOGD("USE-BUFFERING : %s", (use_buffering)?"OOO":"XXX");
506
507                 streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer = buffer;
508
509                 if (use_buffering)
510                 {
511                         streamer->streaming_buffer_type = BUFFER_TYPE_MUXED;
512
513                         if (content_size > 0)
514                         {
515                                 if (streamer->buffering_req.initial_second > 0)
516                                         streamer->buffering_req.is_pre_buffering = TRUE;
517                                 else
518                                         streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
519                         }
520                         else
521                         {
522                                 LOGD("live streaming without mq");
523
524                                 streamer->buffer_handle[BUFFER_TYPE_MUXED].is_live = TRUE;
525                                 streamer->buffering_req.initial_second = buffering_time = DEFAULT_BUFFERING_TIME;
526                         }
527                 }
528
529                 g_object_set ( G_OBJECT (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), "use-buffering", use_buffering, NULL );
530         }
531
532         streaming_set_buffer_size               (streamer, BUFFER_TYPE_MUXED, buffering_bytes, buffering_time);
533         streaming_set_buffer_percent    (streamer, BUFFER_TYPE_MUXED, low_percent, high_percent, 0);
534         streaming_set_queue2_queue_type (streamer, type, file_path, content_size);
535
536         MMPLAYER_FLEAVE();
537         return;
538 }
539
540 void __mm_player_streaming_sync_property(mm_player_streaming_t* streamer, GstElement* decodebin)
541 {
542         streaming_buffer_t* buffer_handle = NULL;
543
544         MMPLAYER_FENTER();
545
546         MMPLAYER_RETURN_IF_FAIL ( streamer && decodebin );
547
548         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
549
550         if ((streamer->need_sync) && (streamer->streaming_buffer_type == BUFFER_TYPE_DEMUXED))
551         {
552                 g_object_set (G_OBJECT(decodebin),
553                                         "max-size-bytes", buffer_handle->buffering_bytes,
554                                         "max-size-time", (guint64)(ceil(buffer_handle->buffering_time) * GST_SECOND),
555                                         "low-percent", (gint)buffer_handle->buffer_low_percent,
556                                         "high-percent", (gint)buffer_handle->buffer_high_percent, NULL);
557
558         }
559
560         streamer->need_sync = FALSE;
561 }
562
563 void __mm_player_streaming_set_multiqueue(      mm_player_streaming_t* streamer,
564                                                                                 GstElement* buffer,
565                                                                                 gboolean use_buffering,
566                                                                                 gdouble buffering_time,
567                                                                                 gdouble low_percent,
568                                                                                 gdouble high_percent)
569 {
570         streaming_buffer_t* buffer_handle = NULL;
571         gdouble pre_buffering_time = 0.0;
572
573         MMPLAYER_FENTER();
574         MMPLAYER_RETURN_IF_FAIL(streamer);
575
576         buffer_handle = &(streamer->buffer_handle[BUFFER_TYPE_DEMUXED]);
577         pre_buffering_time = (gdouble)streamer->buffering_req.initial_second;
578
579         if (buffer)
580         {
581                 buffer_handle->buffer = buffer;
582
583                 if (use_buffering)
584                 {
585                         streamer->streaming_buffer_type = BUFFER_TYPE_DEMUXED;
586
587                         // during prebuffering by requirement, buffer setting should not be changed.
588                         if (pre_buffering_time > 0)
589                                 streamer->buffering_req.is_pre_buffering = TRUE;
590                 }
591
592                 g_object_set ( G_OBJECT (buffer_handle->buffer), "use-buffering", use_buffering, NULL );
593         }
594
595         LOGD ("pre_buffering: %2.2f, during playing: %2.2f\n", pre_buffering_time, buffering_time);
596
597         if (pre_buffering_time <= 0.0)
598         {
599                 pre_buffering_time = GET_DEFAULT_PLAYING_TIME(streamer);
600                 streamer->buffering_req.initial_second = (gint)ceil(buffering_time);
601         }
602
603         high_percent = (pre_buffering_time * 100) / GET_MAX_BUFFER_TIME(streamer);
604         LOGD ("high_percent %2.3f %%\n", high_percent);
605
606         streaming_set_buffer_size (streamer, BUFFER_TYPE_DEMUXED, GET_MAX_BUFFER_BYTES(streamer), GET_MAX_BUFFER_TIME(streamer));
607         streaming_set_buffer_percent (streamer, BUFFER_TYPE_DEMUXED, low_percent, 0, high_percent);
608
609         streamer->need_sync = TRUE;
610
611         MMPLAYER_FLEAVE();
612         return;
613 }
614
615 static void
616 streaming_get_current_bitrate_info(     mm_player_streaming_t* streamer,
617                                                                         GstMessage *buffering_msg,
618                                                                         streaming_content_info_t content_info,
619                                                                         streaming_bitrate_info_t* bitrate_info)
620 {
621
622         GstQuery *query = NULL;
623         GstBufferingMode mode = GST_BUFFERING_STREAM;
624         gint in_rate = 0;
625         gint out_rate = 0;
626         gint64 buffering_left = -1;
627
628         guint buffer_criteria = 0;
629         guint estimated_content_bitrate = 0;
630
631         gdouble buffer_buffering_time = DEFAULT_BUFFERING_TIME;
632
633         MMPLAYER_FENTER();
634
635         MMPLAYER_RETURN_IF_FAIL(streamer);
636         MMPLAYER_RETURN_IF_FAIL(bitrate_info);
637
638         if ((buffering_msg == NULL) ||
639                 ((streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer != NULL) &&
640                 (streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer != NULL) &&
641                 (buffering_msg->src == (GstObject *)streamer->buffer_handle[BUFFER_TYPE_DEMUXED].buffer)))
642         {
643                 query = gst_query_new_buffering (GST_FORMAT_PERCENT);
644
645                 if (gst_element_query ((streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), query))
646                 {
647                         gst_query_parse_buffering_stats (query, &mode, &in_rate, &out_rate, &buffering_left);
648                 }
649
650                 gst_query_unref (query);
651         }
652         else
653         {
654                 gst_message_parse_buffering_stats (buffering_msg, &mode, &in_rate, &out_rate, &buffering_left);
655         }
656
657         LOGD ("Streaming Info : in %d, out %d, left %lld\n", in_rate, out_rate, buffering_left);
658
659         if ((content_info.content_size > 0) && (content_info.duration > 0) && ((content_info.duration/GST_SECOND) > 0))
660                 estimated_content_bitrate = GET_BIT_FROM_BYTE((guint)(content_info.content_size / (content_info.duration/GST_SECOND)));
661
662         if (streamer->buffer_max_bitrate > 0)
663         {
664                 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, streamer->buffer_avg_bitrate);
665                 streamer->buffer_max_bitrate = MAX(streamer->buffer_max_bitrate, estimated_content_bitrate);
666
667                 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate);
668
669                 if (streamer->buffer_avg_bitrate > estimated_content_bitrate)
670                         out_rate = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate);
671                 else if (estimated_content_bitrate != 0)
672                         out_rate = GET_BYTE_FROM_BIT(estimated_content_bitrate);
673                 else
674                         out_rate = GET_BYTE_FROM_BIT(streamer->buffer_max_bitrate/3);
675
676                 LOGD ("(max)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
677         }
678         else if (streamer->buffer_avg_bitrate > 0)
679         {
680                 buffer_criteria = GET_BYTE_FROM_BIT(streamer->buffer_avg_bitrate * 3);
681                 out_rate = GET_BYTE_FROM_BIT(MAX(streamer->buffer_avg_bitrate,estimated_content_bitrate));
682
683                 LOGD ("(avg)content_max_byte_rate %d, byte_out_rate %d\n", buffer_criteria, out_rate);
684         }
685         else
686         {
687                 LOGW ("There is no content bitrate information\n");
688         }
689
690         if ((in_rate > 0) && (out_rate > 0))
691                 buffer_buffering_time =  (gdouble)out_rate / (gdouble)in_rate;
692         else if ((in_rate <= 0) && (out_rate > 0))
693                 buffer_buffering_time = MAX_BUFFERING_TIME;
694         else
695                 buffer_buffering_time = DEFAULT_BUFFERING_TIME;
696
697         (*bitrate_info).byte_in_rate = in_rate;
698         (*bitrate_info).byte_out_rate = out_rate;
699         (*bitrate_info).time_rate = buffer_buffering_time;
700         (*bitrate_info).buffer_criteria = buffer_criteria;
701 }
702
703 static void
704 streaming_handle_fixed_buffering_mode(  mm_player_streaming_t* streamer,
705                                                                                 gint byte_out_rate,
706                                                                                 gdouble fixed_buffering_time,
707                                                                                 streaming_buffer_info_t* buffer_info)
708 {
709         streaming_buffer_t* buffer_handle = NULL;
710
711         guint buffering_bytes = 0;
712         gdouble buffering_time = 0.0;
713         gdouble per_byte = 0.0;
714         gdouble per_time = 0.0;
715
716         MMPLAYER_RETURN_IF_FAIL(streamer);
717         MMPLAYER_RETURN_IF_FAIL(buffer_info);
718
719         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
720         buffering_time = fixed_buffering_time;
721
722         LOGD ("buffering time: %2.2f sec, out rate: %d\n", buffering_time, byte_out_rate);
723
724         if ((buffering_time > 0) && (byte_out_rate > 0))
725         {
726                 buffering_bytes = GET_NEW_BUFFERING_BYTE(byte_out_rate * buffering_time);
727         }
728         else
729         {
730                 if (buffering_time <= 0)
731                         buffering_time = GET_CURRENT_BUFFERING_TIME(buffer_handle);
732
733                 LOGW ("content bitrate is not updated yet.\n");
734                 buffering_bytes = GET_CURRENT_BUFFERING_BYTE(buffer_handle);
735         }
736
737         GET_PERCENT(buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
738         GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
739
740         LOGD ("bytes %d, time %f, per_byte %f, per_time %f\n",
741                                                                                 buffering_bytes, buffering_time, per_byte, per_time);
742
743         (*buffer_info).buffering_bytes = buffering_bytes;
744         (*buffer_info).buffering_time = buffering_time;
745         (*buffer_info).percent_byte = per_byte;
746         (*buffer_info).percent_time = per_time;
747 }
748
749 static void
750 streaming_handle_adaptive_buffering_mode(       mm_player_streaming_t* streamer,
751                                                                                 streaming_content_info_t content_info,
752                                                                                 streaming_bitrate_info_t bitrate_info,
753                                                                                 streaming_buffer_info_t* buffer_info,
754                                                                                 gint expected_play_time)
755 {
756         streaming_buffer_t* buffer_handle = NULL;
757
758         gint buffering_bytes = 0;
759         gint adj_buffering_bytes = 0;
760         gdouble buffer_buffering_time = 0.0;
761         gdouble per_byte = 0.0;
762         gdouble per_time = 0.0;
763         gdouble portion = 0.0;
764         gdouble default_buffering_time = 0.0;
765
766         MMPLAYER_RETURN_IF_FAIL(streamer);
767         MMPLAYER_RETURN_IF_FAIL(buffer_info);
768
769         LOGD ("pos %lld, dur %lld, size %lld, in/out:%d/%d, buffer_criteria:%d, time_rate:%f, need:%d sec\n",
770                                                         content_info.position, content_info.duration, content_info.content_size,
771                                                         bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
772                                                         bitrate_info.buffer_criteria, bitrate_info.time_rate, expected_play_time);
773
774         if (((expected_play_time == TO_THE_END) && (content_info.position <= 0)) ||
775                 (content_info.duration <= 0) ||
776                 (content_info.content_size <= 0))
777         {
778                 LOGW ("keep previous setting.\n");
779                 return;
780         }
781
782         if ((bitrate_info.byte_out_rate <= 0) || (bitrate_info.buffer_criteria == 0))
783         {
784                 LOGW ("keep previous setting.\n");
785                 return;
786         }
787
788         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
789
790         if (bitrate_info.byte_in_rate < bitrate_info.byte_out_rate)
791         {
792                 if (expected_play_time != TO_THE_END)
793                         portion = (double)(expected_play_time * GST_SECOND) / (double)content_info.duration;
794                 else
795                         portion = (1 - (double)content_info.position/(double)content_info.duration);
796
797                 buffering_bytes = GET_NEW_BUFFERING_BYTE(((double)content_info.content_size * portion)  \
798                                                                                                                         * (1 - (double)bitrate_info.byte_in_rate/(double)bitrate_info.byte_out_rate));
799         }
800         else
801         {
802                 /* buffering_bytes will be set as streamer->default_val.buffering_time *
803                  * receiving rate is bigger than avg content bitrate
804                  * so there is no reason to buffering. if the buffering msg is posted
805                  * in-rate or contents bitrate has wrong value. */
806                 LOGW ("don't need to do buffering.\n");
807         }
808
809         if (buffering_bytes > 0)
810                 buffer_buffering_time = (gdouble)buffering_bytes / (gdouble)bitrate_info.byte_out_rate;
811
812         if (content_info.position <= 0)
813         {
814                 /* if the buffer is filled under 50%, MSL use the original default buffering time.
815                    if not, MSL use just 2 sec as a default buffering time. (to reduce initial buffering time) */
816                 default_buffering_time = streamer->default_val.buffering_time - ((gdouble)streamer->buffering_percent/50);
817         }
818         else
819         {
820                 default_buffering_time = streamer->default_val.buffering_time;
821         }
822
823         if (buffer_buffering_time < default_buffering_time)
824         {
825                 LOGD ("adjusted time: %2.2f -> %2.2f\n", buffer_buffering_time, default_buffering_time);
826                 LOGD ("adjusted bytes : %d or %d or %d\n",
827                         buffering_bytes,
828                         (gint)(bitrate_info.byte_out_rate * buffer_buffering_time),
829                         (gint)(bitrate_info.buffer_criteria * buffer_buffering_time));
830
831                 if (content_info.position > 0)
832                 {
833                         /* start monitoring the abmormal state */
834                         streamer->default_val.buffering_monitor = TRUE;
835                 }
836
837                 buffer_buffering_time = default_buffering_time;
838                 adj_buffering_bytes = GET_NEW_BUFFERING_BYTE(bitrate_info.byte_out_rate * (gint)ceil(buffer_buffering_time));
839                 buffering_bytes = MAX(buffering_bytes, adj_buffering_bytes);
840         }
841
842         GET_PERCENT(buffering_bytes, GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_handle->buffer_high_percent, per_byte);
843         GET_PERCENT(buffer_buffering_time, GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_handle->buffer_high_percent, per_time);
844
845         LOGD ("monitor %d, bytes %d, time %f, per_byte %f, per_time %f\n",
846                                                                                 streamer->default_val.buffering_monitor,
847                                                                                 buffering_bytes, buffer_buffering_time, per_byte, per_time);
848
849         (*buffer_info).buffering_bytes = buffering_bytes;
850         (*buffer_info).buffering_time = buffer_buffering_time;
851         (*buffer_info).percent_byte = per_byte;
852         (*buffer_info).percent_time = per_time;
853
854 }
855
856 static void
857 streaming_update_buffer_setting (       mm_player_streaming_t* streamer,
858                                                                         GstMessage *buffering_msg,      // can be null
859                                                                         guint64 content_size,
860                                                                         gint64 position,
861                                                                         gint64 duration)
862 {
863         streaming_buffer_t* buffer_handle = NULL;
864         MMPlayerBufferingMode buffering_mode = MM_PLAYER_BUFFERING_MODE_ADAPTIVE;
865
866         streaming_buffer_info_t buffer_info;
867         streaming_content_info_t content_info;
868         streaming_bitrate_info_t bitrate_info;
869
870         gdouble low_percent = 0.0;
871
872         MMPLAYER_FENTER();
873
874         MMPLAYER_RETURN_IF_FAIL ( streamer );
875
876         memset(&buffer_info, 0x00, sizeof(streaming_buffer_info_t));
877         memset(&content_info, 0x00, sizeof(streaming_content_info_t));
878         memset(&bitrate_info, 0x00, sizeof(streaming_bitrate_info_t));
879
880         buffer_handle = &(streamer->buffer_handle[streamer->streaming_buffer_type]);
881
882         if (streamer->buffering_req.is_pre_buffering == TRUE)
883                 buffering_mode = MM_PLAYER_BUFFERING_MODE_FIXED;
884         else
885                 buffering_mode = streamer->buffering_req.mode;
886
887         buffer_info.buffering_bytes = buffer_handle->buffering_bytes;
888         buffer_info.buffering_time = buffer_handle->buffering_time;
889         buffer_info.percent_byte = buffer_handle->buffer_high_percent;
890         buffer_info.percent_time = buffer_handle->buffer_high_percent;
891
892         content_info.position = position;
893         content_info.duration = duration;
894         content_info.content_size = content_size;
895
896         streaming_get_current_bitrate_info(streamer, buffering_msg, content_info, &bitrate_info);
897
898         LOGD ("buffering mode %d, new info in_r:%d, out_r:%d, cb:%d, bt:%f\n",
899                                         buffering_mode, bitrate_info.byte_in_rate, bitrate_info.byte_out_rate,
900                                         bitrate_info.buffer_criteria, bitrate_info.time_rate);
901
902         /* calculate buffer low/high percent */
903         low_percent = DEFAULT_BUFFER_LOW_PERCENT;
904
905         /********************
906          * (1) fixed mode   *
907          ********************/
908
909         if (buffering_mode == MM_PLAYER_BUFFERING_MODE_FIXED)
910         {
911                 gdouble buffering_time = 0.0;
912
913                 if (streamer->buffering_req.is_pre_buffering == TRUE)
914                         buffering_time = (gdouble)streamer->buffering_req.initial_second;
915                 else
916                         buffering_time = (gdouble)streamer->buffering_req.runtime_second;
917
918                 streaming_handle_fixed_buffering_mode(streamer, bitrate_info.byte_out_rate, buffering_time, &buffer_info);
919         }
920
921         /***********************************
922          * (2) once mode for samsung link  *
923          ***********************************/
924         else if (buffering_mode == MM_PLAYER_BUFFERING_MODE_SLINK)
925         {
926                 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, TO_THE_END);
927         }
928
929         /*********************************
930          * (3) adaptive mode (default)   *
931          *********************************/
932         else
933         {
934                 gint expected_play_time = DEFAULT_PLAYING_TIME;
935
936                 if (streamer->buffering_req.runtime_second > 0)
937                 {
938                         expected_play_time = streamer->buffering_req.runtime_second;
939                 }
940                 else if ((position == 0) && (streamer->is_buffering))
941                 {
942                         expected_play_time = streamer->buffering_req.initial_second;
943                 }
944
945                 if (expected_play_time <= 0)
946                         expected_play_time = DEFAULT_PLAYING_TIME;
947
948                 streaming_handle_adaptive_buffering_mode(streamer, content_info, bitrate_info, &buffer_info, expected_play_time);
949
950                 if (IS_MUXED_BUFFERING_MODE(streamer))  // even if new byte size is smaller than the previous one, time need to be updated.
951                         buffer_handle->buffering_time = buffer_info.buffering_time;
952         }
953
954         LOGD ("adj buffer(%d) %d->%d bytes/%2.2f->%2.2f sec\n",
955                                         streamer->streaming_buffer_type,
956                                         GET_CURRENT_BUFFERING_BYTE(buffer_handle), buffer_info.buffering_bytes,
957                                         GET_CURRENT_BUFFERING_TIME(buffer_handle), buffer_info.buffering_time);
958
959         /* queue2 : bytes, multiqueue : time */
960         if (((GET_CURRENT_BUFFERING_BYTE(buffer_handle) < buffer_info.buffering_bytes) && IS_MUXED_BUFFERING_MODE(streamer)) ||
961                 ((GET_CURRENT_BUFFERING_TIME(buffer_handle) < buffer_info.buffering_time) && IS_DEMUXED_BUFFERING_MODE(streamer)))
962         {
963                 if (duration > 0 && position > 0)
964                 {
965                         gdouble buffering_time_limit = (gdouble)(duration - position)/GST_SECOND;
966
967                         if (buffer_info.buffering_time > buffering_time_limit)
968                                 buffer_info.buffering_time = buffering_time_limit;
969                 }
970
971                 streaming_set_buffer_size(streamer, streamer->streaming_buffer_type, buffer_info.buffering_bytes, buffer_info.buffering_time);
972         }
973
974         streaming_set_buffer_percent(streamer, streamer->streaming_buffer_type, low_percent, buffer_info.percent_byte, buffer_info.percent_time);
975
976         LOGD("buffer setting: size %d, time %f, per %f\n",
977                                                         GET_CURRENT_BUFFERING_BYTE(buffer_handle),
978                                                         GET_CURRENT_BUFFERING_TIME(buffer_handle),
979                                                         buffer_handle->buffer_high_percent);
980
981         streamer->need_sync = TRUE;
982 }
983
984 static void
985 streaming_adjust_min_threshold(mm_player_streaming_t* streamer, gint64 position)
986 {
987 #define DEFAULT_TIME_PAD 1      /* sec */
988         gint playing_time = 0;
989
990         MMPLAYER_FENTER();
991
992         MMPLAYER_RETURN_IF_FAIL(streamer);
993
994         playing_time = (gint)((position - streamer->default_val.prev_pos) / GST_SECOND);
995
996         LOGD ("buffering monitor = %s\n", (streamer->default_val.buffering_monitor)?"ON":"OFF");
997         LOGD ("playing_time ( %d sec) = %lld - %lld \n", playing_time, position, streamer->default_val.prev_pos);
998         LOGD ("default time : %2.3f, prev buffering t : %2.3f\n",
999                                         streamer->default_val.buffering_time, streamer->buffer_handle[streamer->streaming_buffer_type].buffering_time);
1000
1001         if ((streamer->default_val.buffering_monitor) && (playing_time <= (gint)streamer->default_val.buffering_time))
1002         {
1003                 gint time_gap = 0;
1004                 time_gap = (gint)(streamer->default_val.buffering_time - DEFAULT_BUFFERING_TIME);
1005                 if (time_gap <= 0)
1006                         time_gap = DEFAULT_TIME_PAD;
1007
1008                 streamer->default_val.buffering_time += time_gap*2;
1009                 streamer->default_val.buffering_time = MIN(streamer->default_val.buffering_time, MAX_BUFFERING_TIME);
1010         }
1011         else
1012         {
1013                 streamer->default_val.buffering_time = DEFAULT_BUFFERING_TIME;
1014         }
1015
1016         LOGD ("new default min value %2.3f \n", streamer->default_val.buffering_time);
1017
1018         streamer->default_val.buffering_monitor = FALSE;
1019         streamer->default_val.prev_pos = position;
1020 }
1021
1022 static void
1023 streaming_update_buffering_status(mm_player_streaming_t* streamer, GstMessage *buffering_msg, gint64 position)
1024 {
1025         gint buffer_percent = 0;
1026         gboolean increased_per = TRUE;
1027
1028         MMPLAYER_FENTER();
1029
1030         MMPLAYER_RETURN_IF_FAIL(streamer);
1031         MMPLAYER_RETURN_IF_FAIL(buffering_msg);
1032
1033         /* update when buffering has started. */
1034         if ( !streamer->is_buffering )
1035         {
1036                 streamer->is_buffering = TRUE;
1037                 streamer->is_buffering_done = FALSE;
1038                 streamer->buffering_percent = -1;
1039
1040                 if (!streamer->buffering_req.is_pre_buffering)
1041                 {
1042                         streamer->need_update = TRUE;
1043                         streaming_adjust_min_threshold(streamer, position);
1044                 }
1045         }
1046
1047         /* update buffer percent */
1048         gst_message_parse_buffering (buffering_msg, &buffer_percent);
1049
1050         if (streamer->buffering_percent < buffer_percent)
1051         {
1052                 LOGD ("[%s] buffering %d%%....\n",
1053                         GST_OBJECT_NAME(GST_MESSAGE_SRC(buffering_msg)), buffer_percent);
1054                 streamer->buffering_percent = buffer_percent;
1055         }
1056         else
1057         {
1058                 increased_per = FALSE;
1059         }
1060
1061         if ((streamer->buffering_percent == MAX_BUFFER_PERCENT) || (streamer->is_buffering_done == TRUE))
1062         {
1063                 streamer->is_buffering = FALSE;
1064                 streamer->buffering_req.is_pre_buffering = FALSE;
1065                 if (streamer->buffering_percent == MAX_BUFFER_PERCENT)
1066                         streamer->is_buffering_done = FALSE;
1067                 else
1068                         streamer->buffering_percent = MAX_BUFFER_PERCENT;
1069         }
1070         else
1071         {
1072                 /* need to update periodically in case of slink mode */
1073                 if ((increased_per == TRUE) &&
1074                         (buffer_percent%10 == 0) &&
1075                         (streamer->buffering_req.mode == MM_PLAYER_BUFFERING_MODE_SLINK) &&
1076                         (streamer->buffering_req.is_pre_buffering == FALSE))
1077                 {
1078                         /* Update buffer setting to reflect data receiving rate for slink mode */
1079                         streamer->need_update = TRUE;
1080                 }
1081         }
1082 }
1083
1084 void __mm_player_streaming_buffering( mm_player_streaming_t* streamer,
1085                                                                           GstMessage *buffering_msg,
1086                                                                           guint64 content_size,
1087                                                                           gint64 position,
1088                                                                           gint64 duration)
1089 {
1090         MMPLAYER_FENTER();
1091
1092         MMPLAYER_RETURN_IF_FAIL ( streamer );
1093         MMPLAYER_RETURN_IF_FAIL ( buffering_msg );
1094         MMPLAYER_RETURN_IF_FAIL ( GST_IS_MESSAGE ( buffering_msg ) );
1095         MMPLAYER_RETURN_IF_FAIL ( (GST_MESSAGE_TYPE ( buffering_msg ) == GST_MESSAGE_BUFFERING) );
1096
1097         if (buffering_msg)
1098         {
1099                 if (position > (gint64)(streamer->buffering_req.initial_second * GST_SECOND))
1100                         streamer->buffering_req.is_pre_buffering = FALSE;
1101
1102                 streaming_update_buffering_status(streamer, buffering_msg, position);
1103
1104                 if (!streamer->need_update)
1105                 {
1106                         //LOGD ("don't need to update buffering stats during buffering.\n");
1107                         return;
1108                 }
1109
1110                 streamer->need_update = FALSE;
1111         }
1112
1113         streaming_update_buffer_setting (streamer, buffering_msg, content_size, position, duration);
1114
1115         return;
1116 }
1117