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