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