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