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