bdce5241115c99a61b71a95c55b7da6b54b07c4a
[platform/core/multimedia/libmm-player.git] / src / mm_player_gst.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 /*===========================================================================================
24 |                                                                                                                                                                                       |
25 |  INCLUDE FILES                                                                                                                                                        |
26 |                                                                                                                                                                                       |
27 ========================================================================================== */
28 #include <dlog.h>
29 #include <mm_error.h>
30 #include <gst/app/gstappsrc.h>
31
32 #include "mm_player_gst.h"
33 #include "mm_player_priv.h"
34 #include "mm_player_attrs.h"
35 #include "mm_player_utils.h"
36 #include "mm_player_tracks.h"
37
38 /*===========================================================================================
39 |                                                                                                                                                                                       |
40 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
41 |                                                                                                                                                                                       |
42 ========================================================================================== */
43
44 /*---------------------------------------------------------------------------
45 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
46 ---------------------------------------------------------------------------*/
47 #define MMPLAYER_TAG_INDENT 3
48
49 /*===========================================================================================
50 |                                                                                                                                                                                       |
51 |  FUNCTION DEFINITIONS                                                                                                                                         |
52 |                                                                                                                                                                                       |
53 ========================================================================================== */
54
55 static gboolean
56 __mmplayer_check_error_posted_from_activated_track(mmplayer_t *player, gchar *src_element_name)
57 {
58         /* check whether the error is posted from not-activated track or not */
59         int msg_src_pos = 0;
60         gint active_index = 0;
61
62         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst, TRUE);
63
64         active_index = player->track[MM_PLAYER_TRACK_TYPE_AUDIO].active_track_index;
65         LOGD("current  active pad index  -%d", active_index);
66
67         if  (src_element_name) {
68                 int idx = 0;
69
70                 if (player->audio_decoders) {
71                         GList *adec = player->audio_decoders;
72                         for (; adec ; adec = g_list_next(adec)) {
73                                 gchar *name = adec->data;
74
75                                 LOGD("found audio decoder name  = %s", name);
76                                 if (g_strrstr(name, src_element_name)) {
77                                         msg_src_pos = idx;
78                                         break;
79                                 }
80                                 idx++;
81                         }
82                 }
83                 LOGD("active pad = %d, error src index = %d", active_index,  msg_src_pos);
84         }
85
86         if (active_index != msg_src_pos) {
87                 LOGD("skip error because error is posted from no activated track");
88                 return FALSE;
89         }
90
91         return TRUE;
92 }
93
94 static int
95 __mmplayer_gst_transform_error_decode(mmplayer_t *player, const char *klass)
96 {
97         /* Demuxer can't parse one track because it's corrupted.
98          * So, the decoder for it is not linked.
99          * But, it has one playable track.
100          */
101         if (g_strrstr(klass, "Demux")) {
102                 if (player->can_support_codec == FOUND_PLUGIN_VIDEO) {
103                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
104                 } else if (player->can_support_codec == FOUND_PLUGIN_AUDIO) {
105                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
106                 } else {
107                         if (player->pipeline->audiobin) { // PCM
108                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
109                         } else {
110                                 LOGD("not found any available codec. Player should be destroyed.");
111                                 return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
112                         }
113                 }
114         }
115
116         return MM_ERROR_PLAYER_INVALID_STREAM;
117 }
118
119 static int
120 __mmplayer_gst_transform_error_type(mmplayer_t *player, GstElement *src_element)
121 {
122         if (src_element == player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst) {
123                 LOGE("Not supported subtitle.");
124                 return MM_ERROR_PLAYER_NOT_SUPPORTED_SUBTITLE;
125         }
126         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
127 }
128
129 static int
130 __mmplayer_gst_transform_error_failed(mmplayer_t *player, const char *klass, GError *error)
131 {
132         /* Decoder Custom Message */
133         if (!strstr(error->message, "ongoing"))
134                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
135
136         if (strncasecmp(klass, "audio", 5)) {
137                 if ((player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
138                         LOGD("Video can keep playing.");
139                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
140                 }
141         } else if (strncasecmp(klass, "video", 5)) {
142                 if ((player->can_support_codec & FOUND_PLUGIN_AUDIO)) {
143                         LOGD("Audio can keep playing.");
144                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
145                 }
146         }
147
148         LOGD("not found any available codec. Player should be destroyed.");
149         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
150 }
151
152 static int
153 __mmplayer_gst_transform_error_decrypt(mmplayer_t *player, GError *error)
154 {
155         if (strstr(error->message, "rights expired"))
156                 return MM_ERROR_PLAYER_DRM_EXPIRED;
157         else if (strstr(error->message, "no rights"))
158                 return MM_ERROR_PLAYER_DRM_NO_LICENSE;
159         else if (strstr(error->message, "has future rights"))
160                 return MM_ERROR_PLAYER_DRM_FUTURE_USE;
161         else if (strstr(error->message, "opl violation"))
162                 return MM_ERROR_PLAYER_DRM_OUTPUT_PROTECTION;
163
164         return MM_ERROR_PLAYER_DRM_NOT_AUTHORIZED;
165 }
166
167 /* NOTE : decide gstreamer state whether there is some playable track or not. */
168 static gint
169 __mmplayer_gst_transform_gsterror(mmplayer_t *player, GstMessage *message, GError *error)
170 {
171         gchar *src_element_name = NULL;
172         GstElement *src_element = NULL;
173         GstElementFactory *factory = NULL;
174         const gchar *klass = NULL;
175
176         MMPLAYER_FENTER();
177
178         MMPLAYER_RETURN_VAL_IF_FAIL(message, MM_ERROR_INVALID_ARGUMENT);
179         MMPLAYER_RETURN_VAL_IF_FAIL(message->src, MM_ERROR_INVALID_ARGUMENT);
180         MMPLAYER_RETURN_VAL_IF_FAIL(error, MM_ERROR_INVALID_ARGUMENT);
181         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
182                                                                 player->pipeline &&
183                                                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
184
185         src_element = GST_ELEMENT_CAST(message->src);
186         src_element_name = GST_ELEMENT_NAME(src_element);
187         if (!src_element_name)
188                 return MM_ERROR_PLAYER_INTERNAL;
189
190         factory = gst_element_get_factory(src_element);
191         if (!factory)
192                 return MM_ERROR_PLAYER_INTERNAL;
193
194         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
195         if (!klass)
196                 return MM_ERROR_PLAYER_INTERNAL;
197
198         LOGD("error code=%d, msg=%s, src element=%s, class=%s",
199                         error->code, error->message, src_element_name, klass);
200
201         if (MMPLAYER_USE_DECODEBIN(player) &&
202                 !__mmplayer_check_error_posted_from_activated_track(player, src_element_name))
203                 return MM_ERROR_NONE;
204
205         switch (error->code) {
206         case GST_STREAM_ERROR_DECODE:
207                 return __mmplayer_gst_transform_error_decode(player, klass);
208         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
209         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
210         case GST_STREAM_ERROR_WRONG_TYPE:
211                 return __mmplayer_gst_transform_error_type(player, src_element);
212         case GST_STREAM_ERROR_FAILED:
213                 return __mmplayer_gst_transform_error_failed(player, klass, error);
214         case GST_STREAM_ERROR_DECRYPT:
215         case GST_STREAM_ERROR_DECRYPT_NOKEY:
216                 LOGE("decryption error, [%s] failed, reason : [%s]", src_element_name, error->message);
217                 return __mmplayer_gst_transform_error_decrypt(player, error);
218         default:
219                 break;
220         }
221
222         MMPLAYER_FLEAVE();
223
224         return MM_ERROR_PLAYER_INVALID_STREAM;
225 }
226
227 gint
228 __mmplayer_gst_handle_core_error(mmplayer_t *player, int code)
229 {
230         gint trans_err = MM_ERROR_NONE;
231
232         MMPLAYER_FENTER();
233
234         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
235
236         switch (code) {
237         case GST_CORE_ERROR_MISSING_PLUGIN:
238                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
239         case GST_CORE_ERROR_STATE_CHANGE:
240         case GST_CORE_ERROR_SEEK:
241         case GST_CORE_ERROR_NOT_IMPLEMENTED:
242         case GST_CORE_ERROR_FAILED:
243         case GST_CORE_ERROR_TOO_LAZY:
244         case GST_CORE_ERROR_PAD:
245         case GST_CORE_ERROR_THREAD:
246         case GST_CORE_ERROR_NEGOTIATION:
247         case GST_CORE_ERROR_EVENT:
248         case GST_CORE_ERROR_CAPS:
249         case GST_CORE_ERROR_TAG:
250         case GST_CORE_ERROR_CLOCK:
251         case GST_CORE_ERROR_DISABLED:
252         default:
253                 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
254                 break;
255         }
256
257         MMPLAYER_FLEAVE();
258
259         return trans_err;
260 }
261
262 gint
263 __mmplayer_gst_handle_library_error(mmplayer_t *player, int code)
264 {
265         gint trans_err = MM_ERROR_NONE;
266
267         MMPLAYER_FENTER();
268
269         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
270
271         switch (code) {
272         case GST_LIBRARY_ERROR_FAILED:
273         case GST_LIBRARY_ERROR_TOO_LAZY:
274         case GST_LIBRARY_ERROR_INIT:
275         case GST_LIBRARY_ERROR_SHUTDOWN:
276         case GST_LIBRARY_ERROR_SETTINGS:
277         case GST_LIBRARY_ERROR_ENCODE:
278         default:
279                 trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
280                 break;
281         }
282
283         MMPLAYER_FLEAVE();
284
285         return trans_err;
286 }
287
288 gint
289 __mmplayer_gst_handle_resource_error(mmplayer_t *player, int code, GstMessage *message)
290 {
291         gint trans_err = MM_ERROR_NONE;
292
293         MMPLAYER_FENTER();
294
295         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
296
297         switch (code) {
298         case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
299                 trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
300                 break;
301         case GST_RESOURCE_ERROR_NOT_FOUND:
302         case GST_RESOURCE_ERROR_OPEN_READ:
303                 if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
304                         || MMPLAYER_IS_RTSP_STREAMING(player)) {
305                         trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
306                         break;
307                 }
308         case GST_RESOURCE_ERROR_READ:
309                 if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
310                         || MMPLAYER_IS_RTSP_STREAMING(player)) {
311                         trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
312                         break;
313                 } else if (message != NULL && message->src != NULL) {
314                         storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE;
315                         mmplayer_path_type_e path_type = MMPLAYER_PATH_MAX;
316
317                         if (message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)
318                                 path_type = MMPLAYER_PATH_VOD;
319                         else if (message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SUBSRC].gst)
320                                 path_type = MMPLAYER_PATH_TEXT;
321
322                         if (path_type != MMPLAYER_PATH_MAX && player->storage_info[path_type].type == STORAGE_TYPE_EXTERNAL) {
323                                 /* check storage state */
324                                 storage_get_state(player->storage_info[path_type].id, &storage_state);
325                                 player->storage_info[path_type].state = storage_state;
326                                 LOGW("path %d, storage state %d:%d", path_type, player->storage_info[path_type].id, storage_state);
327                         }
328                 } /* fall through */
329         case GST_RESOURCE_ERROR_WRITE:
330         case GST_RESOURCE_ERROR_FAILED:
331         case GST_RESOURCE_ERROR_SEEK:
332         case GST_RESOURCE_ERROR_TOO_LAZY:
333         case GST_RESOURCE_ERROR_BUSY:
334         case GST_RESOURCE_ERROR_OPEN_WRITE:
335         case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
336         case GST_RESOURCE_ERROR_CLOSE:
337         case GST_RESOURCE_ERROR_SYNC:
338         case GST_RESOURCE_ERROR_SETTINGS:
339         default:
340                 trans_err = MM_ERROR_PLAYER_INTERNAL;
341         break;
342         }
343
344         MMPLAYER_FLEAVE();
345
346         return trans_err;
347 }
348
349 gint
350 __mmplayer_gst_handle_stream_error(mmplayer_t *player, GError *error, GstMessage *message)
351 {
352         gint trans_err = MM_ERROR_NONE;
353
354         MMPLAYER_FENTER();
355
356         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
357         MMPLAYER_RETURN_VAL_IF_FAIL(error, MM_ERROR_INVALID_ARGUMENT);
358         MMPLAYER_RETURN_VAL_IF_FAIL(message, MM_ERROR_INVALID_ARGUMENT);
359
360         switch (error->code) {
361         case GST_STREAM_ERROR_FAILED:
362         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
363         case GST_STREAM_ERROR_DECODE:
364         case GST_STREAM_ERROR_WRONG_TYPE:
365         case GST_STREAM_ERROR_DECRYPT:
366         case GST_STREAM_ERROR_DECRYPT_NOKEY:
367         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
368                 trans_err = __mmplayer_gst_transform_gsterror(player, message, error);
369                 break;
370
371         case GST_STREAM_ERROR_NOT_IMPLEMENTED:
372         case GST_STREAM_ERROR_TOO_LAZY:
373         case GST_STREAM_ERROR_ENCODE:
374         case GST_STREAM_ERROR_DEMUX:
375         case GST_STREAM_ERROR_MUX:
376         case GST_STREAM_ERROR_FORMAT:
377         default:
378                 trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
379                 break;
380         }
381
382         MMPLAYER_FLEAVE();
383
384         return trans_err;
385 }
386
387 gboolean
388 __mmplayer_handle_gst_error(mmplayer_t *player, GstMessage *message, GError *error)
389 {
390         MMMessageParamType msg_param;
391         gchar *msg_src_element;
392
393         MMPLAYER_FENTER();
394
395         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
396         MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
397
398         /* NOTE : do something necessary inside of __gst_handle_XXX_error. not here */
399
400         memset(&msg_param, 0, sizeof(MMMessageParamType));
401
402         if (error->domain == GST_CORE_ERROR) {
403                 msg_param.code = __mmplayer_gst_handle_core_error(player, error->code);
404         } else if (error->domain == GST_LIBRARY_ERROR) {
405                 msg_param.code = __mmplayer_gst_handle_library_error(player, error->code);
406         } else if (error->domain == GST_RESOURCE_ERROR) {
407                 msg_param.code = __mmplayer_gst_handle_resource_error(player, error->code, message);
408         } else if (error->domain == GST_STREAM_ERROR) {
409                 msg_param.code = __mmplayer_gst_handle_stream_error(player, error, message);
410         } else {
411                 LOGW("This error domain is not defined.");
412
413                 /* we treat system error as an internal error */
414                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
415         }
416
417         if (message->src) {
418                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
419
420                 msg_param.data = (void *)error->message;
421
422                 LOGE("-Msg src : [%s]   Domain : [%s]   Error : [%s]  Code : [%d] is translated to error code : [0x%x]",
423                         msg_src_element, g_quark_to_string(error->domain), error->message, error->code, msg_param.code);
424         }
425
426         /* no error */
427         if (msg_param.code == MM_ERROR_NONE)
428                 return TRUE;
429
430         /* skip error to avoid duplicated posting */
431         if (((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) &&
432                  (player->storage_info[MMPLAYER_PATH_VOD].state <= STORAGE_STATE_REMOVED)) ||
433                 ((player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL) &&
434                  (player->storage_info[MMPLAYER_PATH_TEXT].state <= STORAGE_STATE_REMOVED))) {
435
436                 /* The error will be handled by mused.
437                  * @ref _mmplayer_manage_external_storage_state() */
438
439                 LOGW("storage is removed, skip error post");
440                 return TRUE;
441         }
442
443         /* post error to application */
444         if (!player->msg_posted) {
445                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
446                 /* don't post more if one was sent already */
447                 player->msg_posted = TRUE;
448         } else {
449                 LOGD("skip error post because it's sent already.");
450         }
451
452         MMPLAYER_FLEAVE();
453
454         return TRUE;
455 }
456
457 static gboolean
458 __mmplayer_handle_streaming_error(mmplayer_t *player, GstMessage *message, GError *error)
459 {
460         LOGD("\n");
461         MMMessageParamType msg_param = {0, };
462         gchar *msg_src_element = NULL;
463
464         MMPLAYER_FENTER();
465
466         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
467         MMPLAYER_RETURN_VAL_IF_FAIL(message, FALSE);
468         MMPLAYER_RETURN_VAL_IF_FAIL(error, FALSE);
469
470         switch (error->code) {
471         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
472                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
473                 break;
474         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
475                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
476                 break;
477         case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
478                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
479                 break;
480         case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
481                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
482                 break;
483         case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
484                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
485                 break;
486         case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
487                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
488                 break;
489         case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
490                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
491                 break;
492         case MMPLAYER_STREAMING_ERROR_INVALID_URL:
493                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
494                 break;
495         case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
496                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
497                 break;
498         case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
499                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
500                 break;
501         case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
502                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
503                 break;
504         case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
505                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
506                 break;
507         case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
508                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
509                 break;
510         case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
511                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
512                 break;
513         case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
514                 msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
515                 break;
516         case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
517                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
518                 break;
519         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
520                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
521                 break;
522         case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
523                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
524                 break;
525         case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
526                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
527                 break;
528         case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
529                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
530                 break;
531         case MMPLAYER_STREAMING_ERROR_GONE:
532                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
533                 break;
534         case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
535                 msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
536                 break;
537         case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
538                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
539                 break;
540         case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
541                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
542                 break;
543         case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
544                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
545                 break;
546         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
547                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
548                 break;
549         case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
550                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
551                 break;
552         case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
553                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
554                 break;
555         case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
556                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
557                 break;
558         case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
559                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
560                 break;
561         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
562                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
563                 break;
564         case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
565                 msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
566                 break;
567         case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
568                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
569                 break;
570         case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
571                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
572                 break;
573         case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
574                 msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
575                 break;
576         case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
577                 msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
578                 break;
579         case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
580                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
581                 break;
582         case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
583                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
584                 break;
585         case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
586                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
587                 break;
588         case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
589                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
590                 break;
591         case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
592                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
593                 break;
594         case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
595                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
596                 break;
597         case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
598                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
599                 break;
600         case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
601                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
602                 break;
603         case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
604                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
605                 break;
606         default:
607                 {
608                         return MM_ERROR_PLAYER_STREAMING_FAIL;
609                 }
610         }
611
612         if (error->message)
613                 msg_param.data = (void *)(error->message);
614
615         if (message->src) {
616                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
617
618                 LOGE("-Msg src : [%s] Code : [0x%x] Error : [%s]",
619                         msg_src_element, msg_param.code, (char *)msg_param.data);
620         }
621
622         /* post error to application */
623         if (!player->msg_posted) {
624                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
625
626                 /* don't post more if one was sent already */
627                 player->msg_posted = TRUE;
628         } else {
629                 LOGD("skip error post because it's sent already.");
630         }
631
632         MMPLAYER_FLEAVE();
633         return TRUE;
634
635 }
636
637 static void
638 __mmplayer_get_metadata_360_from_tags(GstTagList *tags, mmplayer_spherical_metadata_t *metadata)
639 {
640         gst_tag_list_get_int(tags, "is_spherical", &metadata->is_spherical);
641         gst_tag_list_get_int(tags, "is_stitched", &metadata->is_stitched);
642         gst_tag_list_get_string(tags, "stitching_software",
643                         &metadata->stitching_software);
644         gst_tag_list_get_string(tags, "projection_type",
645                         &metadata->projection_type_string);
646         gst_tag_list_get_string(tags, "stereo_mode", &metadata->stereo_mode_string);
647         gst_tag_list_get_int(tags, "source_count", &metadata->source_count);
648         gst_tag_list_get_int(tags, "init_view_heading",
649                         &metadata->init_view_heading);
650         gst_tag_list_get_int(tags, "init_view_pitch", &metadata->init_view_pitch);
651         gst_tag_list_get_int(tags, "init_view_roll", &metadata->init_view_roll);
652         gst_tag_list_get_int(tags, "timestamp", &metadata->timestamp);
653         gst_tag_list_get_int(tags, "full_pano_width_pixels",
654                         &metadata->full_pano_width_pixels);
655         gst_tag_list_get_int(tags, "full_pano_height_pixels",
656                         &metadata->full_pano_height_pixels);
657         gst_tag_list_get_int(tags, "cropped_area_image_width",
658                         &metadata->cropped_area_image_width);
659         gst_tag_list_get_int(tags, "cropped_area_image_height",
660                         &metadata->cropped_area_image_height);
661         gst_tag_list_get_int(tags, "cropped_area_left",
662                         &metadata->cropped_area_left);
663         gst_tag_list_get_int(tags, "cropped_area_top", &metadata->cropped_area_top);
664         gst_tag_list_get_int(tags, "ambisonic_type", &metadata->ambisonic_type);
665         gst_tag_list_get_int(tags, "ambisonic_format", &metadata->ambisonic_format);
666         gst_tag_list_get_int(tags, "ambisonic_order", &metadata->ambisonic_order);
667 }
668
669 static gboolean
670 __mmplayer_gst_extract_tag_from_msg(mmplayer_t *player, GstMessage *msg)
671 {
672
673 /* macro for better code readability */
674 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, player, playertag) \
675         do { \
676                 if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
677                         if (string != NULL) { \
678                                 SECURE_LOGD("update tag string : %s", string); \
679                                 if (strlen(string) > MM_MAX_STRING_LENGTH) { \
680                                         char *new_string = g_malloc(MM_MAX_STRING_LENGTH); \
681                                         strncpy(new_string, string, MM_MAX_STRING_LENGTH - 1); \
682                                         new_string[MM_MAX_STRING_LENGTH - 1] = '\0'; \
683                                         mm_player_set_attribute((MMHandleType)player, NULL,\
684                                                         playertag, new_string, strlen(new_string), NULL); \
685                                         MMPLAYER_FREEIF(new_string); \
686                                 } else { \
687                                         mm_player_set_attribute((MMHandleType)player, NULL,\
688                                                         playertag, string, strlen(string), NULL); \
689                                 } \
690                                 MMPLAYER_FREEIF(string); \
691                         } \
692                 } \
693         } while (0)
694
695 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, player, playertag) \
696         do {    \
697                 GstSample *sample = NULL;\
698                 if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
699                         GstMapInfo info = GST_MAP_INFO_INIT;\
700                         buffer = gst_sample_get_buffer(sample);\
701                         if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
702                                 LOGD("failed to get image data from tag");\
703                                 gst_sample_unref(sample);\
704                                 break;\
705                         } \
706                         SECURE_LOGD("update album cover data : %p, size : %zu", info.data, info.size);\
707                         MMPLAYER_FREEIF(player->album_art);\
708                         player->album_art = (gchar *)g_malloc(info.size);\
709                         if (player->album_art) {\
710                                 memcpy(player->album_art, info.data, info.size);\
711                                 mm_player_set_attribute((MMHandleType)player, NULL,\
712                                                 playertag, (void *)player->album_art, info.size, NULL); \
713                                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {\
714                                         msg_param.data = (void *)player->album_art;\
715                                         msg_param.size = info.size;\
716                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_IMAGE_BUFFER, &msg_param);\
717                                         SECURE_LOGD("post message image buffer data : %p, size : %zu", info.data, info.size);\
718                                 } \
719                         } \
720                         gst_buffer_unmap(buffer, &info);\
721                         gst_sample_unref(sample);\
722                 }       \
723         } while (0)
724
725 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, player, playertag) \
726         do {    \
727                 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) { \
728                         if (v_uint) { \
729                                 int i = 0; \
730                                 mmplayer_track_type_e track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
731                                 if (strstr(GST_OBJECT_NAME(msg->src), "audio")) \
732                                         track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
733                                 else if (strstr(GST_OBJECT_NAME(msg->src), "video")) \
734                                         track_type = MM_PLAYER_TRACK_TYPE_VIDEO; \
735                                 else \
736                                         track_type = MM_PLAYER_TRACK_TYPE_TEXT; \
737                                 if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) { \
738                                         if (track_type == MM_PLAYER_TRACK_TYPE_AUDIO) \
739                                                 mm_player_set_attribute((MMHandleType)player, NULL,\
740                                                                 "content_audio_bitrate", v_uint, NULL); \
741                                         player->bitrate[track_type] = v_uint; \
742                                         player->total_bitrate = 0; \
743                                         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
744                                                 player->total_bitrate += player->bitrate[i]; \
745                                         mm_player_set_attribute((MMHandleType)player, NULL,\
746                                                         playertag, player->total_bitrate, NULL); \
747                                         SECURE_LOGD("update bitrate %d[bps] of stream #%d.", v_uint, (int)track_type); \
748                                 } else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) { \
749                                         player->maximum_bitrate[track_type] = v_uint; \
750                                         player->total_maximum_bitrate = 0; \
751                                         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
752                                                 player->total_maximum_bitrate += player->maximum_bitrate[i]; \
753                                         mm_player_set_attribute((MMHandleType)player, NULL,\
754                                                         playertag, player->total_maximum_bitrate, NULL); \
755                                         SECURE_LOGD("update maximum bitrate %d[bps] of stream #%d", v_uint, (int)track_type);\
756                                 } else { \
757                                         mm_player_set_attribute((MMHandleType)player, NULL, playertag, v_uint, NULL); \
758                                 } \
759                                 v_uint = 0;\
760                         } \
761                 } \
762         } while (0)
763
764 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, player, playertag) \
765         do { \
766                 if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
767                         if (date != NULL) {\
768                                 string = g_strdup_printf("%d", g_date_get_year(date));\
769                                 mm_player_set_attribute((MMHandleType)player, NULL,\
770                                                 playertag, string, strlen(string), NULL); \
771                                 SECURE_LOGD("metainfo year : %s", string);\
772                                 MMPLAYER_FREEIF(string);\
773                                 g_date_free(date);\
774                         } \
775                 } \
776         } while (0)
777
778 #define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, player, playertag) \
779         do { \
780                 if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
781                         if (datetime != NULL) {\
782                                 string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
783                                 mm_player_set_attribute((MMHandleType)player, NULL,\
784                                                 playertag, string, strlen(string), NULL); \
785                                 SECURE_LOGD("metainfo year : %s", string);\
786                                 MMPLAYER_FREEIF(string);\
787                                 gst_date_time_unref(datetime);\
788                         } \
789                 } \
790         } while (0)
791
792         /* function start */
793         GstTagList *tag_list = NULL;
794
795         char *string = NULL;
796         guint v_uint = 0;
797         GDate *date = NULL;
798         GstDateTime *datetime = NULL;
799         /* album cover */
800         GstBuffer *buffer = NULL;
801         gint index = 0;
802         MMMessageParamType msg_param = {0, };
803
804         /* currently not used. but those are needed for above macro */
805         //guint64 v_uint64 = 0;
806         //gdouble v_double = 0;
807
808         MMPLAYER_RETURN_VAL_IF_FAIL(player && msg, FALSE);
809
810         /* get tag list from gst message */
811         gst_message_parse_tag(msg, &tag_list);
812
813         /* store tags to player attributes */
814         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, player, "tag_title");
815         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, player, "tag_artist");
816         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, player, "tag_album");
817         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, player, "tag_author");
818         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, player, "tag_date");
819         MMPLAYER_UPDATE_TAG_DATE_TIME(GST_TAG_DATE_TIME, player, "tag_date");
820         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, player, "tag_genre");
821         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, player, "tag_track_num");
822         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, player, "tag_description");
823         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, player, "tag_copyright");
824         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, player, "content_video_codec");
825         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, player, "content_audio_codec");
826         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, player, "content_bitrate");
827         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, player, "content_max_bitrate");
828         MMPLAYER_UPDATE_TAG_LOCK(player);
829         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, player, "tag_album_cover");
830         MMPLAYER_UPDATE_TAG_UNLOCK(player);
831         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, player, "content_video_orientation");
832
833         if (strstr(GST_OBJECT_NAME(msg->src), "demux")) {
834                 if (player->video360_metadata.is_spherical == -1) {
835                         __mmplayer_get_metadata_360_from_tags(tag_list, &player->video360_metadata);
836                         mm_player_set_attribute((MMHandleType)player, NULL,
837                                         "content_video_is_spherical", player->video360_metadata.is_spherical, NULL);
838                         if (player->video360_metadata.is_spherical == 1) {
839                                 LOGD("This is spherical content for 360 playback.");
840                                 player->is_content_spherical = TRUE;
841                         } else {
842                                 LOGD("This is not spherical content");
843                                 player->is_content_spherical = FALSE;
844                         }
845
846                         if (player->video360_metadata.projection_type_string) {
847                                 if (!strcmp(player->video360_metadata.projection_type_string, "equirectangular")) {
848                                         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
849                                 } else {
850                                         LOGE("Projection %s: code not implemented.", player->video360_metadata.projection_type_string);
851                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
852                                 }
853                         }
854
855                         if (player->video360_metadata.stereo_mode_string) {
856                                 if (!strcmp(player->video360_metadata.stereo_mode_string, "mono")) {
857                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
858                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "left-right")) {
859                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_LEFT_RIGHT;
860                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "top-bottom")) {
861                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_TOP_BOTTOM;
862                                 } else {
863                                         LOGE("Stereo mode %s: code not implemented.", player->video360_metadata.stereo_mode_string);
864                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
865                                 }
866                         }
867                 }
868         }
869
870         gst_tag_list_unref(tag_list);
871
872         return TRUE;
873 }
874
875
876 static mmplayer_track_type_e
877 __mmplayer_convert_gst_stream_type_to_track_type (GstStreamType stype)
878 {
879         switch (stype) {
880         case GST_STREAM_TYPE_AUDIO:
881                 return MM_PLAYER_TRACK_TYPE_AUDIO;
882         case GST_STREAM_TYPE_VIDEO:
883                 return MM_PLAYER_TRACK_TYPE_VIDEO;
884         case GST_STREAM_TYPE_TEXT:
885                 return MM_PLAYER_TRACK_TYPE_TEXT;
886         default:
887                 LOGD("not supported stream stype");
888                 return MM_PLAYER_TRACK_TYPE_MAX;
889         }
890 }
891
892 /* if retval is FALSE, it will be dropped for performance. */
893 static gboolean
894 __mmplayer_gst_check_useful_message(mmplayer_t *player, GstMessage *message)
895 {
896         gboolean retval = FALSE;
897
898         if (!(player->pipeline && player->pipeline->mainbin)) {
899                 LOGE("player pipeline handle is null");
900                 return TRUE;
901         }
902
903         switch (GST_MESSAGE_TYPE(message)) {
904         case GST_MESSAGE_TAG:
905         case GST_MESSAGE_EOS:
906         case GST_MESSAGE_ERROR:
907         case GST_MESSAGE_WARNING:
908         case GST_MESSAGE_CLOCK_LOST:
909         case GST_MESSAGE_NEW_CLOCK:
910         case GST_MESSAGE_ELEMENT:
911         case GST_MESSAGE_DURATION_CHANGED:
912         case GST_MESSAGE_ASYNC_START:
913         case GST_MESSAGE_STREAM_COLLECTION:
914                 retval = TRUE;
915                 break;
916         case GST_MESSAGE_ASYNC_DONE:
917         case GST_MESSAGE_STATE_CHANGED:
918                 /* we only handle messages from pipeline */
919                 if ((message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) && (!player->gapless.reconfigure))
920                         retval = TRUE;
921                 else
922                         retval = FALSE;
923                 break;
924         case GST_MESSAGE_BUFFERING:
925         {
926                 gint buffer_percent = 0;
927
928                 retval = TRUE;
929                 gst_message_parse_buffering(message, &buffer_percent);
930                 if (buffer_percent != MAX_BUFFER_PERCENT) {
931                         LOGD("[%s] buffering msg %d%%!!", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), buffer_percent);
932                         break;
933                 }
934
935                 if (!MMPLAYER_CMD_TRYLOCK(player)) {
936                         LOGW("can't get cmd lock, send msg to bus");
937                         break;
938                 }
939
940                 if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
941                         LOGD("[%s] Buffering DONE is detected !", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)));
942                         player->streamer->buffering_state |= MM_PLAYER_BUFFERING_COMPLETE;
943                 }
944
945                 MMPLAYER_CMD_UNLOCK(player);
946
947                 break;
948         }
949         case GST_MESSAGE_STREAMS_SELECTED:
950         {
951                 if (MMPLAYER_USE_DECODEBIN(player))
952                         break; /* drop msg */
953
954                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
955                         (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
956                         (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
957
958                         gint64 dur_bytes = 0L;
959
960                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
961                                 LOGE("fail to get duration.");
962
963                         /* there is no mq, enable use-buffering on queue2 (ex) wav streaming
964                          * use file information was already set on Q2 when it was created. */
965                         _mm_player_streaming_set_queue2(player->streamer,
966                                                         player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
967                                                         TRUE,                                                           /* use_buffering */
968                                                         MUXED_BUFFER_TYPE_MAX,                          /* use previous buffer type setting */
969                                                         ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
970                 }
971
972                 LOGD("GST_MESSAGE_STREAMS_SELECTED");
973                 player->no_more_pad = TRUE;
974                 _mmplayer_set_reconfigure_state(player, FALSE);
975                 if (!MMPLAYER_IS_ADAPTIVE_STREAMING(player))
976                         _mmplayer_pipeline_complete(NULL, player);
977                 retval = TRUE;
978                 break;
979         }
980         default:
981                 retval = FALSE;
982                 break;
983         }
984
985         return retval;
986 }
987
988 static void
989 __mmplayer_update_buffer_setting(mmplayer_t *player, GstMessage *buffering_msg)
990 {
991         guint64 data_size = 0;
992         gint64 pos_nsec = 0;
993
994         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
995
996         _mmplayer_gst_get_position(player, &pos_nsec);  /* to update player->last_position */
997
998         if (MMPLAYER_IS_HTTP_STREAMING(player))
999                 data_size = player->http_content_size;
1000
1001         _mm_player_streaming_buffering(player->streamer, buffering_msg, data_size, player->last_position, player->duration);
1002         if (!player->streamer->is_adaptive_streaming) {
1003                 _mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
1004                 return;
1005         }
1006
1007         /* adaptivedemux2 is used for buffering in uridecodebin3 */
1008         if (!player->streamer->buffering_req.is_pre_buffering) {
1009                 LOGD("adaptive> set rebuffer time : %d ms", player->streamer->buffering_req.rebuffer_time);
1010                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
1011                         "low-watermark-time", (guint64)(player->streamer->buffering_req.rebuffer_time * GST_MSECOND),
1012                         NULL);
1013         }
1014 }
1015
1016 static int
1017 __mmplayer_handle_buffering_playback(mmplayer_t *player)
1018 {
1019         int ret = MM_ERROR_NONE;
1020         mmplayer_state_e prev_state = MM_PLAYER_STATE_NONE;
1021         mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
1022         mmplayer_state_e target_state = MM_PLAYER_STATE_NONE;
1023         mmplayer_state_e pending_state = MM_PLAYER_STATE_NONE;
1024
1025         if (!player || !player->streamer || (MMPLAYER_IS_LIVE_STREAMING(player) && MMPLAYER_IS_RTSP_STREAMING(player))) {
1026                 LOGW("do nothing for buffering msg");
1027                 ret = MM_ERROR_PLAYER_INVALID_STATE;
1028                 goto exit;
1029         }
1030
1031         prev_state = MMPLAYER_PREV_STATE(player);
1032         current_state = MMPLAYER_CURRENT_STATE(player);
1033         target_state = MMPLAYER_TARGET_STATE(player);
1034         pending_state = MMPLAYER_PENDING_STATE(player);
1035
1036         LOGD("player state : prev %s, current %s, pending %s, target %s, buffering state 0x%X",
1037                 MMPLAYER_STATE_GET_NAME(prev_state),
1038                 MMPLAYER_STATE_GET_NAME(current_state),
1039                 MMPLAYER_STATE_GET_NAME(pending_state),
1040                 MMPLAYER_STATE_GET_NAME(target_state),
1041                 player->streamer->buffering_state);
1042
1043         if (!(player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
1044                 /* NOTE : if buffering has done, player has to go to target state. */
1045                 switch (target_state) {
1046                 case MM_PLAYER_STATE_PAUSED:
1047                         {
1048                                 switch (pending_state) {
1049                                 case MM_PLAYER_STATE_PLAYING:
1050                                         _mmplayer_gst_pause(player, TRUE);
1051                                         break;
1052
1053                                 case MM_PLAYER_STATE_PAUSED:
1054                                         LOGD("player is already going to paused state, there is nothing to do.");
1055                                         break;
1056
1057                                 case MM_PLAYER_STATE_NONE:
1058                                 case MM_PLAYER_STATE_NULL:
1059                                 case MM_PLAYER_STATE_READY:
1060                                 default:
1061                                         LOGW("invalid pending state [%s].", MMPLAYER_STATE_GET_NAME(pending_state));
1062                                         break;
1063                                 }
1064                         }
1065                         break;
1066
1067                 case MM_PLAYER_STATE_PLAYING:
1068                         {
1069                                 switch (pending_state) {
1070                                 case MM_PLAYER_STATE_NONE:
1071                                         {
1072                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1073                                                         _mmplayer_gst_resume(player, TRUE);
1074                                         }
1075                                         break;
1076
1077                                 case MM_PLAYER_STATE_PAUSED:
1078                                         /* NOTE: It should be worked as asynchronously.
1079                                          * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1080                                          */
1081                                         if (current_state == MM_PLAYER_STATE_PLAYING) {
1082                                                 /* NOTE: If the current state is PLAYING, it means, async _mmplayer_gst_pause() is not completed yet.
1083                                                  * The current state should be changed to paused purposely to prevent state conflict.
1084                                                  */
1085                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
1086                                         }
1087                                         _mmplayer_gst_resume(player, TRUE);
1088                                         break;
1089
1090                                 case MM_PLAYER_STATE_PLAYING:
1091                                         LOGD("player is already going to playing state, there is nothing to do.");
1092                                         break;
1093
1094                                 case MM_PLAYER_STATE_NULL:
1095                                 case MM_PLAYER_STATE_READY:
1096                                 default:
1097                                         LOGW("invalid pending state [%s].", MMPLAYER_STATE_GET_NAME(pending_state));
1098                                         break;
1099                                 }
1100                         }
1101                         break;
1102
1103                 case MM_PLAYER_STATE_NULL:
1104                 case MM_PLAYER_STATE_READY:
1105                 case MM_PLAYER_STATE_NONE:
1106                 default:
1107                         LOGW("invalid target state [%s].", MMPLAYER_STATE_GET_NAME(target_state));
1108                         break;
1109                 }
1110         } else {
1111                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1112                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1113                  */
1114                 switch (pending_state) {
1115                 case MM_PLAYER_STATE_NONE:
1116                         {
1117                                 if (current_state != MM_PLAYER_STATE_PAUSED) {
1118                                         /* rtsp streaming pause makes rtsp server stop sending data. */
1119                                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
1120                                                 LOGD("set pause state during buffering");
1121                                                 _mmplayer_gst_pause(player, TRUE);
1122                                         }
1123                                 }
1124                         }
1125                         break;
1126
1127                 case MM_PLAYER_STATE_PLAYING:
1128                         /* rtsp streaming pause makes rtsp server stop sending data. */
1129                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
1130                                 _mmplayer_gst_pause(player, TRUE);
1131                         break;
1132
1133                 case MM_PLAYER_STATE_PAUSED:
1134                         break;
1135
1136                 case MM_PLAYER_STATE_NULL:
1137                 case MM_PLAYER_STATE_READY:
1138                 default:
1139                         LOGW("invalid pending state [%s].", MMPLAYER_STATE_GET_NAME(pending_state));
1140                         break;
1141                 }
1142         }
1143
1144 exit:
1145         return ret;
1146 }
1147
1148 static stream_variant_t *
1149 __mmplayer_adaptive_var_info(const stream_variant_t *self, gpointer user_data)
1150 {
1151         stream_variant_t *var_info = NULL;
1152         g_return_val_if_fail(self != NULL, NULL);
1153
1154         var_info = g_new0(stream_variant_t, 1);
1155         if (!var_info) return NULL;
1156         var_info->bandwidth = self->bandwidth;
1157         var_info->width = self->width;
1158         var_info->height = self->height;
1159         return var_info;
1160 }
1161
1162 static gboolean
1163 __mmplayer_gst_handle_duration(mmplayer_t *player, GstMessage *msg)
1164 {
1165         gint64 bytes = 0;
1166
1167         MMPLAYER_FENTER();
1168
1169         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
1170         MMPLAYER_RETURN_VAL_IF_FAIL(msg, FALSE);
1171
1172         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1173                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)) {
1174                 LOGD("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
1175
1176                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes)) {
1177                         LOGD("data total size of http content: %"G_GINT64_FORMAT, bytes);
1178                         player->http_content_size = (bytes > 0) ? bytes : 0;
1179                 }
1180         } else {
1181                 /* handling audio clip which has vbr. means duration is keep changing */
1182                 _mmplayer_update_content_attrs(player, ATTR_DURATION);
1183         }
1184
1185         MMPLAYER_FLEAVE();
1186
1187         return TRUE;
1188 }
1189
1190 static gboolean
1191 __mmplayer_eos_timer_cb(gpointer u_data)
1192 {
1193         mmplayer_t *player = NULL;
1194         MMHandleType attrs = 0;
1195         int count = 0;
1196
1197         MMPLAYER_RETURN_VAL_IF_FAIL(u_data, FALSE);
1198
1199         player = (mmplayer_t *)u_data;
1200         attrs = MMPLAYER_GET_ATTRS(player);
1201
1202         mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1203
1204         if (count == -1) {
1205                 gint ret_value = 0;
1206                 ret_value = _mmplayer_gst_set_position(player, 0, TRUE);
1207                 if (ret_value != MM_ERROR_NONE)
1208                         LOGE("seeking to 0 failed in repeat play");
1209         } else {
1210                 /* posting eos */
1211                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
1212         }
1213
1214         /* we are returning FALSE as we need only one posting */
1215         return FALSE;
1216 }
1217
1218 static void
1219 __mmplayer_handle_eos_delay(mmplayer_t *player, int delay_in_ms)
1220 {
1221         MMPLAYER_RETURN_IF_FAIL(player);
1222
1223         /* post now if delay is zero */
1224         if (delay_in_ms == 0 || player->audio_decoded_cb) {
1225                 LOGD("eos delay is zero. posting EOS now");
1226                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
1227
1228                 if (player->audio_decoded_cb)
1229                         _mmplayer_cancel_eos_timer(player);
1230
1231                 return;
1232         }
1233
1234         /* cancel if existing */
1235         _mmplayer_cancel_eos_timer(player);
1236
1237         /* init new timeout */
1238         /* NOTE : consider give high priority to this timer */
1239         LOGD("posting EOS message after [%d] msec", delay_in_ms);
1240
1241         player->eos_timer = g_timeout_add(delay_in_ms,
1242                 __mmplayer_eos_timer_cb, player);
1243
1244         player->context.global_default = g_main_context_default();
1245         LOGD("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
1246
1247         /* check timer is valid. if not, send EOS now */
1248         if (player->eos_timer == 0) {
1249                 LOGW("creating timer for delayed EOS has failed. sending EOS now");
1250                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
1251         }
1252 }
1253
1254 static int
1255 __mmplayer_gst_pending_seek(mmplayer_t *player)
1256 {
1257         mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
1258         int ret = MM_ERROR_NONE;
1259
1260         MMPLAYER_FENTER();
1261
1262         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
1263
1264         if (!player->pending_seek.is_pending) {
1265                 LOGD("pending seek is not reserved. nothing to do.");
1266                 return ret;
1267         }
1268
1269         /* check player state if player could pending seek or not. */
1270         current_state = MMPLAYER_CURRENT_STATE(player);
1271
1272         if (current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING) {
1273                 LOGW("try to pending seek in %s state, try next time. ",
1274                         MMPLAYER_STATE_GET_NAME(current_state));
1275                 return ret;
1276         }
1277
1278         LOGD("trying to play from(%"G_GINT64_FORMAT") pending position", player->pending_seek.pos);
1279
1280         ret = _mmplayer_gst_set_position(player, player->pending_seek.pos, FALSE);
1281         if (ret != MM_ERROR_NONE)
1282                 LOGE("failed to seek pending position. just keep staying current position.");
1283
1284         player->pending_seek.is_pending = false;
1285
1286         MMPLAYER_FLEAVE();
1287
1288         return ret;
1289 }
1290
1291 static void
1292 __mmplayer_gst_set_async(mmplayer_t *player, gboolean async, enum mmplayer_sink_type  type)
1293 {
1294         mmplayer_gst_element_t *videobin = NULL, *audiobin = NULL, *textbin = NULL;
1295
1296         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline);
1297
1298         audiobin = player->pipeline->audiobin; /* can be null */
1299         videobin = player->pipeline->videobin; /* can be null */
1300         textbin = player->pipeline->textbin;   /* can be null */
1301
1302         LOGD("Async will be set to %d about 0x%X type sink", async, type);
1303
1304         if ((type & MMPLAYER_AUDIO_SINK) && audiobin && audiobin[MMPLAYER_A_SINK].gst)
1305                 g_object_set(audiobin[MMPLAYER_A_SINK].gst, "async", async, NULL);
1306
1307         if ((type & MMPLAYER_VIDEO_SINK) && videobin && videobin[MMPLAYER_V_SINK].gst)
1308                 g_object_set(videobin[MMPLAYER_V_SINK].gst, "async", async, NULL);
1309
1310         if ((type & MMPLAYER_TEXT_SINK) && textbin && textbin[MMPLAYER_T_FAKE_SINK].gst)
1311                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", async, NULL);
1312
1313         return;
1314 }
1315
1316 static void
1317 __mmplayer_drop_subtitle(mmplayer_t *player, gboolean is_drop)
1318 {
1319         mmplayer_gst_element_t *textbin;
1320         MMPLAYER_FENTER();
1321
1322         MMPLAYER_RETURN_IF_FAIL(player &&
1323                                         player->pipeline &&
1324                                         player->pipeline->textbin);
1325
1326         MMPLAYER_RETURN_IF_FAIL(player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
1327
1328         textbin = player->pipeline->textbin;
1329
1330         if (is_drop) {
1331                 LOGD("Drop subtitle text after getting EOS");
1332
1333                 __mmplayer_gst_set_async(player, FALSE, MMPLAYER_TEXT_SINK);
1334                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
1335
1336                 player->is_subtitle_force_drop = TRUE;
1337         } else {
1338                 if (player->is_subtitle_force_drop == TRUE) {
1339                         LOGD("Enable subtitle data path without drop");
1340
1341                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
1342                         __mmplayer_gst_set_async(player, TRUE, MMPLAYER_TEXT_SINK);
1343
1344                         LOGD("non-connected with external display");
1345
1346                         player->is_subtitle_force_drop = FALSE;
1347                 }
1348         }
1349 }
1350
1351 static void
1352 __mmplayer_gst_handle_eos_message(mmplayer_t *player, GstMessage *msg)
1353 {
1354         MMHandleType attrs = 0;
1355         gint count = 0;
1356
1357         MMPLAYER_FENTER();
1358
1359         /* NOTE : EOS event is coming multiple time. watch out it */
1360         /* check state. we only process EOS when pipeline state goes to PLAYING */
1361         if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)) {
1362                 LOGD("EOS received on non-playing state. ignoring it");
1363                 return;
1364         }
1365
1366         if (player->pipeline && player->pipeline->textbin)
1367                 __mmplayer_drop_subtitle(player, TRUE);
1368
1369         if ((player->audio_decoded_cb) && (player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_NO_SYNC_WITH_CLOCK))
1370                 _mmplayer_audio_stream_clear_buffer(player, TRUE);
1371
1372         /* rewind if repeat count is greater then zero */
1373         /* get play count */
1374         attrs = MMPLAYER_GET_ATTRS(player);
1375         if (attrs) {
1376                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1377
1378                 LOGD("play count: %d, playback rate: %f", count, player->playback_rate);
1379
1380                 if (count == -1 || player->playback_rate < 0.0) /* default value is 1 */ {
1381                         if (player->playback_rate < 0.0) {
1382                                 player->resumed_by_rewind = TRUE;
1383                                 _mmplayer_set_mute((MMHandleType)player, false);
1384                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_RESUMED_BY_REW, NULL);
1385                         }
1386
1387                         __mmplayer_handle_eos_delay(player, player->ini.delay_before_repeat);
1388
1389                         /* initialize */
1390                         player->sent_bos = FALSE;
1391
1392                         LOGD("do not post eos msg for repeating");
1393                         return;
1394                 }
1395         }
1396
1397         if (player->pipeline)
1398                 MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-eos");
1399
1400         /* post eos message to application */
1401         __mmplayer_handle_eos_delay(player, player->ini.eos_delay);
1402
1403         /* reset last position */
1404         player->last_position = 0;
1405
1406         MMPLAYER_FLEAVE();
1407         return;
1408 }
1409
1410 static void
1411 __mmplayer_gst_handle_error_message(mmplayer_t *player, GstMessage *msg)
1412 {
1413         GError *error = NULL;
1414         gchar *debug = NULL;
1415
1416         MMPLAYER_FENTER();
1417
1418         /* generating debug info before returning error */
1419         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-error");
1420
1421         /* get error code */
1422         gst_message_parse_error(msg, &error, &debug);
1423
1424         if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
1425                 /* Note : the streaming error from the streaming source is handled
1426                  *       using __mmplayer_handle_streaming_error.
1427                  */
1428                 __mmplayer_handle_streaming_error(player, msg, error);
1429
1430                 /* dump state of all element */
1431                 _mmplayer_dump_pipeline_state(player);
1432         } else {
1433                 /* translate gst error code to msl error code. then post it
1434                  * to application if needed
1435                  */
1436                 __mmplayer_handle_gst_error(player, msg, error);
1437
1438                 if (debug)
1439                         LOGE("error debug : %s", debug);
1440         }
1441
1442         MMPLAYER_FREEIF(debug);
1443         g_error_free(error);
1444
1445         MMPLAYER_FLEAVE();
1446         return;
1447 }
1448
1449 static void
1450 __mmplayer_gst_handle_buffering_message(mmplayer_t *player, GstMessage *msg)
1451 {
1452         MMMessageParamType msg_param = {0, };
1453         int bRet = MM_ERROR_NONE;
1454
1455         MMPLAYER_FENTER();
1456         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
1457
1458         if (!MMPLAYER_IS_STREAMING(player)) {
1459                 LOGW("this is not streaming playback.");
1460                 return;
1461         }
1462
1463         MMPLAYER_CMD_LOCK(player);
1464
1465         if (!player->streamer) {
1466                 LOGW("Pipeline is shutting down");
1467                 MMPLAYER_CMD_UNLOCK(player);
1468                 return;
1469         }
1470
1471         /* ignore the remained buffering message till getting 100% msg */
1472         if (player->streamer->buffering_state == MM_PLAYER_BUFFERING_COMPLETE) {
1473                 gint buffer_percent = 0;
1474
1475                 gst_message_parse_buffering(msg, &buffer_percent);
1476
1477                 if (buffer_percent == MAX_BUFFER_PERCENT) {
1478                         LOGD("Ignored all the previous buffering msg!(got %d%%)", buffer_percent);
1479                         __mmplayer_update_buffer_setting(player, NULL); /* update buffering size for next buffering */
1480                         player->streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
1481                 }
1482                 MMPLAYER_CMD_UNLOCK(player);
1483                 return;
1484         }
1485
1486         /* ignore the remained buffering message */
1487         if (player->streamer->buffering_state == MM_PLAYER_BUFFERING_ABORT) {
1488                 gint buffer_percent = 0;
1489
1490                 gst_message_parse_buffering(msg, &buffer_percent);
1491
1492                 LOGD("interrupted buffering -last posted %d %%, new per %d %%",
1493                                         player->streamer->buffering_percent, buffer_percent);
1494
1495                 if (player->streamer->buffering_percent > buffer_percent || buffer_percent <= 0) {
1496                         player->streamer->buffering_state = MM_PLAYER_BUFFERING_DEFAULT;
1497                         player->streamer->buffering_req.is_pre_buffering = FALSE;
1498
1499                         LOGD("interrupted buffering - need to enter the buffering mode again - %d %%", buffer_percent);
1500                 } else {
1501                         LOGD("interrupted buffering - ignored the remained buffering msg!");
1502                         MMPLAYER_CMD_UNLOCK(player);
1503                         return;
1504                 }
1505         }
1506
1507         __mmplayer_update_buffer_setting(player, msg);
1508
1509         bRet = __mmplayer_handle_buffering_playback(player); /* playback control */
1510
1511         if (bRet == MM_ERROR_NONE) {
1512                 msg_param.connection.buffering = player->streamer->buffering_percent;
1513                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1514
1515                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1516                         player->pending_resume &&
1517                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1518
1519                         player->is_external_subtitle_added_now = FALSE;
1520                         player->pending_resume = FALSE;
1521                         _mmplayer_resume((MMHandleType)player);
1522                 }
1523
1524                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1525                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1526
1527                         if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS) {
1528                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1529                                         player->seek_state = MMPLAYER_SEEK_NONE;
1530                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1531                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1532                                         /* Considering the async state transition in case of RTSP.
1533                                            After getting state change gst msg, seek completed msg will be posted. */
1534                                         player->seek_state = MMPLAYER_SEEK_COMPLETED;
1535                                 }
1536                         }
1537                 }
1538         } else if (bRet == MM_ERROR_PLAYER_INVALID_STATE) {
1539                 if (!player->streamer) {
1540                         LOGW("player->streamer is NULL, so discarding the buffering percent update");
1541                         MMPLAYER_CMD_UNLOCK(player);
1542                         return;
1543                 }
1544
1545                 if ((MMPLAYER_IS_LIVE_STREAMING(player)) && (MMPLAYER_IS_RTSP_STREAMING(player))) {
1546
1547                         LOGD("player->last_position=%"G_GINT64_FORMAT" , player->streamer->buffering_percent=%d",
1548                                         GST_TIME_AS_SECONDS(player->last_position), player->streamer->buffering_percent);
1549
1550                         if ((GST_TIME_AS_SECONDS(player->last_position) <= 0) && (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)) {
1551                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1552                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1553                         } else {
1554                                 LOGD("Not updating Buffering Message for Live RTSP case !!!");
1555                         }
1556                 } else {
1557                         msg_param.connection.buffering = player->streamer->buffering_percent;
1558                         MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1559                 }
1560         }
1561         MMPLAYER_CMD_UNLOCK(player);
1562
1563         MMPLAYER_FLEAVE();
1564         return;
1565
1566 }
1567
1568 static void
1569 __mmplayer_gst_handle_state_message(mmplayer_t *player, GstMessage *msg)
1570 {
1571         mmplayer_gst_element_t *mainbin;
1572         GstState oldstate = GST_STATE_NULL;
1573         GstState newstate = GST_STATE_NULL;
1574         GstState pending = GST_STATE_NULL;
1575
1576         MMPLAYER_FENTER();
1577         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
1578
1579         mainbin = player->pipeline->mainbin;
1580
1581         /* we only handle messages from pipeline */
1582         if (msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst)
1583                 return;
1584
1585         gst_message_parse_state_changed(msg, &oldstate, &newstate, &pending);
1586
1587         LOGD("state changed [%s] : %s ---> %s     final : %s",
1588                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1589                 gst_element_state_get_name((GstState)oldstate),
1590                 gst_element_state_get_name((GstState)newstate),
1591                 gst_element_state_get_name((GstState)pending));
1592
1593         if (newstate == GST_STATE_PLAYING) {
1594                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (player->pending_seek.is_pending)) {
1595
1596                         int retVal = MM_ERROR_NONE;
1597                         LOGD("trying to play from (%"G_GINT64_FORMAT") pending position", player->pending_seek.pos);
1598
1599                         retVal = _mmplayer_gst_set_position(player, player->pending_seek.pos, TRUE);
1600
1601                         if (MM_ERROR_NONE != retVal)
1602                                 LOGE("failed to seek pending position. just keep staying current position.");
1603
1604                         player->pending_seek.is_pending = false;
1605                 }
1606         }
1607
1608         if (oldstate == newstate) {
1609                 LOGD("pipeline reports state transition to old state");
1610                 return;
1611         }
1612
1613         switch (newstate) {
1614         case GST_STATE_PAUSED:
1615                 {
1616                         gboolean prepare_async = FALSE;
1617
1618                         if (!player->sent_bos && oldstate == GST_STATE_READY) {
1619                                 // managed prepare async case
1620                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1621                                 LOGD("checking prepare mode for async transition - %d", prepare_async);
1622                         }
1623
1624                         if (MMPLAYER_IS_STREAMING(player) || MMPLAYER_IS_MS_BUFF_SRC(player) || prepare_async) {
1625                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
1626
1627                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
1628                                         _mm_player_streaming_set_content_bitrate(player->streamer,
1629                                                 player->total_maximum_bitrate, player->total_bitrate);
1630
1631                                 if (player->pending_seek.is_pending) {
1632                                         LOGW("trying to do pending seek");
1633                                         MMPLAYER_CMD_LOCK(player);
1634                                         __mmplayer_gst_pending_seek(player);
1635                                         MMPLAYER_CMD_UNLOCK(player);
1636                                 }
1637                         }
1638                 }
1639                 break;
1640
1641         case GST_STATE_PLAYING:
1642                 {
1643                         if (MMPLAYER_IS_STREAMING(player)) {
1644                                 // managed prepare async case when buffering is completed
1645                                 // pending state should be reset otherwise, it's still playing even though it's resumed after buffering.
1646                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
1647                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
1648                                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
1649
1650                                 if (MMPLAYER_IS_RTSP_STREAMING(player) && (MMPLAYER_IS_LIVE_STREAMING(player))) {
1651
1652                                         LOGD("Current Buffering Percent = %d", player->streamer->buffering_percent);
1653                                         if (player->streamer->buffering_percent < 100) {
1654
1655                                                 MMMessageParamType msg_param = {0, };
1656                                                 LOGW("Posting Buffering Completed Message to Application !!!");
1657
1658                                                 msg_param.connection.buffering = 100;
1659                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1660                                         }
1661                                 }
1662                         }
1663
1664                         if (player->gapless.stream_changed) {
1665                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
1666                                 player->gapless.stream_changed = FALSE;
1667                         }
1668
1669                         if (player->seek_state == MMPLAYER_SEEK_COMPLETED) {
1670                                 player->seek_state = MMPLAYER_SEEK_NONE;
1671                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1672                         }
1673                 }
1674                 break;
1675         case GST_STATE_VOID_PENDING:
1676         case GST_STATE_NULL:
1677         case GST_STATE_READY:
1678         default:
1679                 break;
1680         }
1681
1682         MMPLAYER_FLEAVE();
1683         return;
1684 }
1685
1686 static void
1687 __mmplayer_gst_handle_element_message(mmplayer_t *player, GstMessage *msg)
1688 {
1689         const gchar *structure_name;
1690         gint count = 0, idx = 0;
1691
1692         MMPLAYER_FENTER();
1693         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
1694
1695         if (gst_message_get_structure(msg) == NULL)
1696                 return;
1697
1698         structure_name = gst_structure_get_name(gst_message_get_structure(msg));
1699         if (!structure_name)
1700                 return;
1701
1702         LOGD("GST_MESSAGE_ELEMENT %s from %s", structure_name, GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)));
1703
1704         if (!strcmp(structure_name, "adaptive-streaming-variant")) {
1705                 const GValue *var_info = NULL;
1706
1707                 var_info = gst_structure_get_value(gst_message_get_structure(msg), "video-variant-info");
1708                 if (var_info != NULL) {
1709                         if (player->adaptive_info.var_list)
1710                                 g_list_free_full(player->adaptive_info.var_list, g_free);
1711
1712                         /* share addr or copy the list */
1713                         player->adaptive_info.var_list =
1714                                 g_list_copy_deep((GList *)g_value_get_pointer(var_info), (GCopyFunc)__mmplayer_adaptive_var_info, NULL);
1715
1716                         count = g_list_length(player->adaptive_info.var_list);
1717                         if (count > 0) {
1718                                 stream_variant_t *temp = NULL;
1719
1720                                 /* print out for debug */
1721                                 LOGD("num of variant_info %d", count);
1722                                 for (idx = 0; idx < count; idx++) {
1723                                         temp = g_list_nth_data(player->adaptive_info.var_list, idx);
1724                                         if (temp)
1725                                                 LOGD("variant(%d) [b]%d [w]%d [h]%d ", idx, temp->bandwidth, temp->width, temp->height);
1726                                 }
1727                         }
1728                 }
1729         }
1730
1731         if (!strcmp(structure_name, "prepare-decode-buffers")) {
1732                 gint num_buffers = 0;
1733                 gint extra_num_buffers = 0;
1734
1735                 if (gst_structure_get_int(gst_message_get_structure(msg), "num_buffers", &num_buffers)) {
1736                         LOGD("video_num_buffers : %d", num_buffers);
1737                         mm_player_set_attribute((MMHandleType)player, NULL,
1738                                         MM_PLAYER_VIDEO_BUFFER_TOTAL_SIZE, num_buffers, NULL);
1739                 }
1740
1741                 if (gst_structure_get_int(gst_message_get_structure(msg), "extra_num_buffers", &extra_num_buffers)) {
1742                         LOGD("num_of_vout_extra num buffers : %d", extra_num_buffers);
1743                         mm_player_set_attribute((MMHandleType)player, NULL,
1744                                         MM_PLAYER_VIDEO_BUFFER_EXTRA_SIZE, extra_num_buffers, NULL);
1745                 }
1746                 return;
1747         }
1748
1749         if (!strcmp(structure_name, "Ext_Sub_Language_List"))
1750                 _mmplayer_track_update_text_attr_info(player, msg);
1751
1752         /* custom message */
1753         if (!strcmp(structure_name, "audio_codec_not_supported")) {
1754                 MMMessageParamType msg_param = {0,};
1755                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
1756                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
1757         }
1758
1759         /* custom message for RTSP attribute :
1760                 RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state changed.
1761                 sdp which has contents info is received when rtsp connection is opened.
1762                 extract duration ,codec info , resolution from sdp and get it by GstMessage */
1763         if (!strcmp(structure_name, "rtspsrc_properties")) {
1764                 g_autofree gchar *audio_codec = NULL;
1765                 g_autofree gchar *video_codec = NULL;
1766                 g_autofree gchar *video_frame_size = NULL;
1767
1768                 gst_structure_get(gst_message_get_structure(msg),
1769                                         "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
1770                 LOGD("rtsp duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(player->duration));
1771                 player->streaming_type = _mmplayer_get_stream_service_type(player);
1772
1773                 gst_structure_get(gst_message_get_structure(msg),
1774                                         "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL);
1775                 LOGD("rtsp_audio_codec : %s", audio_codec);
1776                 if (audio_codec)
1777                         mm_player_set_attribute((MMHandleType)player, NULL,
1778                                         "content_audio_codec", audio_codec, strlen(audio_codec), NULL);
1779
1780                 gst_structure_get(gst_message_get_structure(msg),
1781                                         "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL);
1782                 LOGD("rtsp_video_codec : %s", video_codec);
1783                 if (video_codec)
1784                         mm_player_set_attribute((MMHandleType)player, NULL,
1785                                         "content_video_codec", video_codec, strlen(video_codec), NULL);
1786
1787                 gst_structure_get(gst_message_get_structure(msg),
1788                                         "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
1789                 LOGD("rtsp_video_frame_size : %s", video_frame_size);
1790                 if (video_frame_size) {
1791                         gchar **res_str = g_strsplit(video_frame_size, "-", 0);
1792                         mm_player_set_attribute((MMHandleType)player, NULL,
1793                                 MM_PLAYER_VIDEO_WIDTH, atoi(res_str[0]),
1794                                 MM_PLAYER_VIDEO_HEIGHT, atoi(res_str[1]),
1795                                 NULL);
1796                         g_strfreev(res_str);
1797                 }
1798         }
1799
1800         MMPLAYER_FLEAVE();
1801         return;
1802 }
1803
1804 static void
1805 __mmplayer_gst_handle_async_done_message(mmplayer_t *player, GstMessage *msg)
1806 {
1807         mmplayer_gst_element_t *mainbin;
1808
1809         MMPLAYER_FENTER();
1810         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
1811
1812         mainbin = player->pipeline->mainbin;
1813
1814         LOGD("GST_MESSAGE_ASYNC_DONE : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1815
1816         /* we only handle messages from pipeline */
1817         if (msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst)
1818                 return;
1819
1820         if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS) {
1821                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1822                         player->seek_state = MMPLAYER_SEEK_NONE;
1823                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1824                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1825                         if (mainbin[MMPLAYER_M_AUTOPLUG].gst) {
1826                                 LOGD("sync %s state(%s) with parent state(%s)",
1827                                         GST_ELEMENT_NAME(mainbin[MMPLAYER_M_AUTOPLUG].gst),
1828                                         gst_element_state_get_name(GST_STATE(mainbin[MMPLAYER_M_AUTOPLUG].gst)),
1829                                         gst_element_state_get_name(GST_STATE(mainbin[MMPLAYER_M_PIPE].gst)));
1830
1831                                 /* In case of streaming, pause is required before finishing seeking by buffering.
1832                                    After completing the seek(during buffering), the player and sink elems has paused state but others in playing state.
1833                                    Because the buffering state is controlled according to the state transition for force resume,
1834                                    the decodebin state should be paused as player state. */
1835                                 gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_AUTOPLUG].gst);
1836                         }
1837
1838                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1839                                 (player->streamer) &&
1840                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
1841                                 !(player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
1842                                 GstQuery *query = NULL;
1843                                 gboolean busy = FALSE;
1844                                 gint percent = 0;
1845
1846                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer) {
1847                                         query = gst_query_new_buffering(GST_FORMAT_PERCENT);
1848                                         if (gst_element_query(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query))
1849                                                 gst_query_parse_buffering_percent(query, &busy, &percent);
1850                                         gst_query_unref(query);
1851
1852                                         LOGD("buffered percent(%s): %d",
1853                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
1854                                 }
1855
1856                                 if (percent >= 100)
1857                                         __mmplayer_handle_buffering_playback(player);
1858                         }
1859
1860                         player->seek_state = MMPLAYER_SEEK_COMPLETED;
1861                 }
1862         }
1863
1864         MMPLAYER_FLEAVE();
1865         return;
1866 }
1867
1868 #ifdef __DEBUG__
1869 static void
1870 __mmplayer_print_tag_foreach(const GstTagList *tags, const gchar *tag, gpointer user_data)
1871 {
1872         GValue val = { 0, };
1873         gchar *str = NULL;
1874         guint indent = GPOINTER_TO_UINT(user_data);
1875
1876         if (!gst_tag_list_copy_value(&val, tags, tag))
1877                 return;
1878
1879         if (G_VALUE_HOLDS_STRING(&val))
1880                 str = g_value_dup_string(&val);
1881         else
1882                 str = gst_value_serialize(&val);
1883
1884         LOGD("%*s%s: %s\n", 2 * indent, " ", gst_tag_get_nick(tag), str);
1885         g_free(str);
1886         g_value_unset(&val);
1887 }
1888 #endif
1889
1890 static void
1891 __mmplayer_dump_collection(GstStreamCollection * collection)
1892 {
1893         guint i = 0;
1894 #ifdef __DEBUG__
1895         GstTagList *tags = NULL;
1896 #endif
1897         GstCaps *caps = NULL;
1898
1899         for (i = 0; i < gst_stream_collection_get_size(collection); i++) {
1900                 GstStream *stream = gst_stream_collection_get_stream(collection, i);
1901                 LOGD ("collection: [%u] Stream, type: %s, flags 0x%x\n", i,
1902                                 gst_stream_type_get_name(gst_stream_get_stream_type(stream)),
1903                                 gst_stream_get_stream_flags(stream));
1904                 LOGD ("  ID: %s\n", gst_stream_get_stream_id(stream));
1905
1906                 caps = gst_stream_get_caps(stream);
1907                 if (caps) {
1908                         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
1909                         gst_caps_unref(caps);
1910                 }
1911
1912 #ifdef __DEBUG__
1913                 tags = gst_stream_get_tags(stream);
1914                 if (tags) {
1915                         LOGD ("  tags:\n");
1916                         gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(MMPLAYER_TAG_INDENT));
1917                         gst_tag_list_unref(tags);
1918                 }
1919 #endif
1920         }
1921 }
1922
1923 static void
1924 __mmplayer_stream_notify_cb(GstStreamCollection *collection,
1925                         GstStream *stream, GParamSpec *pspec, gpointer data)
1926 {
1927         LOGD ("Got stream-notify from stream %s for %s (collection %p)\n",
1928                                 gst_stream_get_stream_id(stream), pspec->name, collection);
1929         if (g_str_equal(pspec->name, "caps")) {
1930                 GstCaps *caps = gst_stream_get_caps(stream);
1931                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
1932                 gst_caps_unref(caps);
1933         }
1934
1935 #ifdef __DEBUG__
1936         if (g_str_equal (pspec->name, "tags")) {
1937                 GstTagList *tags = gst_stream_get_tags(stream);
1938                 if (tags) {
1939                         LOGD ("  tags:\n");
1940                         gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(MMPLAYER_TAG_INDENT));
1941                         gst_tag_list_unref(tags);
1942                 }
1943         }
1944 #endif
1945 }
1946
1947 static void
1948 __mmplayer_gst_bus_msg_callback(GstMessage *msg, gpointer data)
1949 {
1950         mmplayer_t *player = (mmplayer_t *)(data);
1951
1952         MMPLAYER_RETURN_IF_FAIL(player);
1953         MMPLAYER_RETURN_IF_FAIL(msg && GST_IS_MESSAGE(msg));
1954
1955         switch (GST_MESSAGE_TYPE(msg)) {
1956         case GST_MESSAGE_UNKNOWN:
1957                 LOGD("unknown message received");
1958                 break;
1959
1960         case GST_MESSAGE_EOS:
1961                 LOGD("GST_MESSAGE_EOS received");
1962                 __mmplayer_gst_handle_eos_message(player, msg);
1963                 break;
1964
1965         case GST_MESSAGE_ERROR:
1966                 _mmplayer_set_reconfigure_state(player, FALSE);
1967                 __mmplayer_gst_handle_error_message(player, msg);
1968                 break;
1969
1970         case GST_MESSAGE_WARNING:
1971                 {
1972                         char *debug = NULL;
1973                         GError *error = NULL;
1974
1975                         gst_message_parse_warning(msg, &error, &debug);
1976
1977                         LOGD("warning : %s", error->message);
1978                         LOGD("debug : %s", debug);
1979
1980                         MMPLAYER_POST_MSG(player, MM_MESSAGE_WARNING, NULL);
1981
1982                         MMPLAYER_FREEIF(debug);
1983                         g_error_free(error);
1984                 }
1985                 break;
1986
1987         case GST_MESSAGE_TAG:
1988                 {
1989                         LOGD("GST_MESSAGE_TAG");
1990                         if (!__mmplayer_gst_extract_tag_from_msg(player, msg))
1991                                 LOGW("failed to extract tags from gstmessage");
1992                 }
1993                 break;
1994
1995         case GST_MESSAGE_BUFFERING:
1996                 __mmplayer_gst_handle_buffering_message(player, msg);
1997                 break;
1998
1999         case GST_MESSAGE_STATE_CHANGED:
2000                 __mmplayer_gst_handle_state_message(player, msg);
2001                 break;
2002
2003         case GST_MESSAGE_CLOCK_LOST:
2004                         {
2005                                 GstClock *clock = NULL;
2006                                 gboolean need_new_clock = FALSE;
2007
2008                                 gst_message_parse_clock_lost(msg, &clock);
2009                                 LOGD("GST_MESSAGE_CLOCK_LOST : %s", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
2010
2011                                 if (!player->videodec_linked)
2012                                         need_new_clock = TRUE;
2013                                 else if (!player->ini.use_system_clock)
2014                                         need_new_clock = TRUE;
2015
2016                                 if (need_new_clock) {
2017                                         LOGD("Provide clock is TRUE, do pause->resume");
2018                                         _mmplayer_gst_pause(player, FALSE);
2019                                         _mmplayer_gst_resume(player, FALSE);
2020                                 }
2021                         }
2022                         break;
2023
2024         case GST_MESSAGE_NEW_CLOCK:
2025                         {
2026                                 GstClock *clock = NULL;
2027                                 gst_message_parse_new_clock(msg, &clock);
2028                                 LOGD("GST_MESSAGE_NEW_CLOCK : %s", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
2029                         }
2030                         break;
2031
2032         case GST_MESSAGE_ELEMENT:
2033                 __mmplayer_gst_handle_element_message(player, msg);
2034                         break;
2035
2036         case GST_MESSAGE_DURATION_CHANGED:
2037                 {
2038                         LOGD("GST_MESSAGE_DURATION_CHANGED");
2039                         if (!__mmplayer_gst_handle_duration(player, msg))
2040                                 LOGW("failed to update duration");
2041                 }
2042                 break;
2043
2044         case GST_MESSAGE_ASYNC_START:
2045                         LOGD("GST_MESSAGE_ASYNC_START : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2046                 break;
2047
2048         case GST_MESSAGE_ASYNC_DONE:
2049                 __mmplayer_gst_handle_async_done_message(player, msg);
2050                 break;
2051         case GST_MESSAGE_STREAM_COLLECTION:
2052         {
2053                 GstStreamCollection *collection = NULL;
2054                 LOGD("GST_MESSAGE_STREAM_COLLECTION : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2055
2056                 gst_message_parse_stream_collection(msg, &collection);
2057                 if (collection) {
2058                         __mmplayer_dump_collection(collection);
2059                         if (player->collection && player->stream_notify_id) {
2060                                 g_signal_handler_disconnect(player->collection, player->stream_notify_id);
2061                                 player->stream_notify_id = 0;
2062                         }
2063                         gst_object_replace((GstObject **)&player->collection, (GstObject *)collection);
2064                         if (player->collection) {
2065                                 player->stream_notify_id = g_signal_connect(player->collection, "stream-notify",
2066                                                         (GCallback)__mmplayer_stream_notify_cb, player);
2067                         }
2068                         gst_object_unref(collection);
2069                 }
2070         } break;
2071         case GST_MESSAGE_STREAMS_SELECTED:
2072         {
2073                 GstStreamCollection *collection = NULL;
2074                 LOGD("GST_MESSAGE_STREAMS_SELECTED : %s", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
2075
2076                 gst_message_parse_streams_selected(msg, &collection);
2077                 if (collection) {
2078                         guint len = gst_message_streams_selected_get_size(msg);
2079                         for (guint i = 0; i < len; i++) {
2080                                 GstStream *stream = gst_message_streams_selected_get_stream(msg, i);
2081                                 mmplayer_track_type_e type = __mmplayer_convert_gst_stream_type_to_track_type(
2082                                                         gst_stream_get_stream_type(stream));
2083                                 if (type == MM_PLAYER_TRACK_TYPE_MAX) {
2084                                         LOGD("not supported track type");
2085                                         gst_object_unref(stream);
2086                                         break;
2087                                 }
2088                                 LOGD ("  Stream #%d : %s\n", i, gst_stream_get_stream_id(stream));
2089                                 if (player->track[type].active_track_index == INVALID_TRACK_INDEX) {
2090                                         int stream_index = INVALID_TRACK_INDEX;
2091                                         if (_mmplayer_get_track_index(player, type, stream, &stream_index) == MM_ERROR_NONE) {
2092                                                 player->track[type].active_track_index = stream_index;
2093                                                 LOGD("selected this stream, update active idx : %d",
2094                                                                 player->track[type].active_track_index);
2095                                         }
2096                                 }
2097                                 gst_object_unref(stream);
2098                         }
2099                         gst_object_unref(collection);
2100                 }
2101         } break;
2102
2103 #ifdef __DEBUG__
2104         case GST_MESSAGE_REQUEST_STATE:         LOGD("GST_MESSAGE_REQUEST_STATE"); break;
2105         case GST_MESSAGE_STEP_START:            LOGD("GST_MESSAGE_STEP_START"); break;
2106         case GST_MESSAGE_QOS:                           LOGD("GST_MESSAGE_QOS"); break;
2107         case GST_MESSAGE_PROGRESS:                      LOGD("GST_MESSAGE_PROGRESS"); break;
2108         case GST_MESSAGE_ANY:                           LOGD("GST_MESSAGE_ANY"); break;
2109         case GST_MESSAGE_INFO:                          LOGD("GST_MESSAGE_STATE_DIRTY"); break;
2110         case GST_MESSAGE_STATE_DIRTY:           LOGD("GST_MESSAGE_STATE_DIRTY"); break;
2111         case GST_MESSAGE_STEP_DONE:                     LOGD("GST_MESSAGE_STEP_DONE"); break;
2112         case GST_MESSAGE_CLOCK_PROVIDE:         LOGD("GST_MESSAGE_CLOCK_PROVIDE"); break;
2113         case GST_MESSAGE_STRUCTURE_CHANGE:      LOGD("GST_MESSAGE_STRUCTURE_CHANGE"); break;
2114         case GST_MESSAGE_STREAM_STATUS:         LOGD("GST_MESSAGE_STREAM_STATUS"); break;
2115         case GST_MESSAGE_APPLICATION:           LOGD("GST_MESSAGE_APPLICATION"); break;
2116         case GST_MESSAGE_SEGMENT_START:         LOGD("GST_MESSAGE_SEGMENT_START"); break;
2117         case GST_MESSAGE_SEGMENT_DONE:          LOGD("GST_MESSAGE_SEGMENT_DONE"); break;
2118         case GST_MESSAGE_LATENCY:                       LOGD("GST_MESSAGE_LATENCY"); break;
2119 #endif
2120
2121         default:
2122                 break;
2123         }
2124
2125         /* should not call 'gst_message_unref(msg)' */
2126         return;
2127 }
2128
2129 static GstBusSyncReply
2130 __mmplayer_gst_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data)
2131 {
2132         mmplayer_t *player = (mmplayer_t *)data;
2133         GstBusSyncReply reply = GST_BUS_DROP;
2134
2135         if (!(player->pipeline && player->pipeline->mainbin)) {
2136                 LOGE("player pipeline handle is null");
2137                 return GST_BUS_PASS;
2138         }
2139
2140         if (!__mmplayer_gst_check_useful_message(player, message)) {
2141                 gst_message_unref(message);
2142                 return GST_BUS_DROP;
2143         }
2144
2145         switch (GST_MESSAGE_TYPE(message)) {
2146         case GST_MESSAGE_TAG:
2147                 __mmplayer_gst_extract_tag_from_msg(player, message);
2148
2149 #ifdef __DEBUG__
2150                 {
2151                         GstTagList *tags = NULL;
2152
2153                         gst_message_parse_tag(message, &tags);
2154                         if (tags) {
2155                                 LOGE("TAGS received from element \"%s\".",
2156                                 GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
2157
2158                                 gst_tag_list_foreach(tags, __mmplayer_print_tag_foreach, GUINT_TO_POINTER(MMPLAYER_TAG_INDENT));
2159                                 gst_tag_list_unref(tags);
2160                                 tags = NULL;
2161                         }
2162                         break;
2163                 }
2164 #endif
2165                 break;
2166
2167         case GST_MESSAGE_DURATION_CHANGED:
2168                 __mmplayer_gst_handle_duration(player, message);
2169                 break;
2170         case GST_MESSAGE_ELEMENT:
2171                 {
2172                         const gchar *klass = NULL;
2173                         klass = gst_element_factory_get_metadata
2174                                 (gst_element_get_factory((GstElement *)message->src), GST_ELEMENT_METADATA_KLASS);
2175                         if (!klass || !g_strrstr(klass, "Codec/Decoder")) {
2176                                 reply = GST_BUS_PASS;
2177                                 break;
2178                         }
2179                         __mmplayer_gst_handle_element_message(player, message);
2180                 }
2181                 break;
2182         case GST_MESSAGE_ASYNC_DONE:
2183                 /* NOTE:Don't call gst_callback directly
2184                  * because previous frame can be showed even though this message is received for seek.
2185                  */
2186         default:
2187                 reply = GST_BUS_PASS;
2188                 break;
2189         }
2190
2191         if (reply == GST_BUS_DROP)
2192                 gst_message_unref(message);
2193
2194         return reply;
2195 }
2196
2197 static void
2198 __mmplayer_gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data)
2199 {
2200         GstElement *appsrc = element;
2201         mmplayer_input_buffer_t *buf = (mmplayer_input_buffer_t *)user_data;
2202         GstBuffer *buffer = NULL;
2203         GstFlowReturn ret = GST_FLOW_OK;
2204         gint len = size;
2205
2206         MMPLAYER_RETURN_IF_FAIL(element);
2207         MMPLAYER_RETURN_IF_FAIL(buf);
2208
2209         buffer = gst_buffer_new();
2210
2211         if (buf->offset < 0 || buf->len < 0) {
2212                 LOGE("invalid buf info %d %d", buf->offset, buf->len);
2213                 return;
2214         }
2215
2216         if (buf->offset >= buf->len) {
2217                 LOGD("call eos appsrc");
2218                 g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
2219                 return;
2220         }
2221
2222         if (buf->len - buf->offset < size)
2223                 len = buf->len - buf->offset;
2224
2225         gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, NULL, NULL));
2226         GST_BUFFER_OFFSET(buffer) = (guint64)buf->offset;
2227         GST_BUFFER_OFFSET_END(buffer) = (guint64)(buf->offset + len);
2228
2229 #ifdef __DEBUG__
2230         LOGD("feed buffer %p, offset %u-%u length %u", buffer, buf->offset, (buf->offset+len), len);
2231 #endif
2232         g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
2233
2234         buf->offset += len;
2235 }
2236
2237 static gboolean
2238 __mmplayer_gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data)
2239 {
2240         mmplayer_input_buffer_t *buf = (mmplayer_input_buffer_t *)user_data;
2241
2242         MMPLAYER_RETURN_VAL_IF_FAIL(buf, FALSE);
2243
2244         buf->offset  = (int)size;
2245
2246         return TRUE;
2247 }
2248
2249 void
2250 __mmplayer_gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data)
2251 {
2252         mmplayer_t *player  = (mmplayer_t *)user_data;
2253         mmplayer_stream_type_e stream_type = MM_PLAYER_STREAM_TYPE_DEFAULT;
2254         MMMessageParamType msg_param = {0,};
2255         guint64 current_level_bytes = 0;
2256
2257         MMPLAYER_RETURN_IF_FAIL(player);
2258
2259         if (g_strrstr(GST_ELEMENT_NAME(element), "audio")) {
2260                 stream_type = MM_PLAYER_STREAM_TYPE_AUDIO;
2261         } else if (g_strrstr(GST_ELEMENT_NAME(element), "video")) {
2262                 stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
2263         } else {
2264                 LOGW("invalid feed-data signal from %s", GST_ELEMENT_NAME(element));
2265                 return;
2266         }
2267
2268         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
2269
2270         LOGI("stream type: %d, level: %"G_GUINT64_FORMAT, stream_type, current_level_bytes);
2271
2272         msg_param.union_type = MM_MSG_UNION_BUFFER_STATUS;
2273         msg_param.buffer_status.stream_type = stream_type;
2274         msg_param.buffer_status.status = MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN;
2275         msg_param.buffer_status.bytes = current_level_bytes;
2276
2277         MMPLAYER_POST_MSG(player, MM_MESSAGE_PUSH_BUFFER_STATUS, &msg_param);
2278 }
2279
2280 void
2281 __mmplayer_gst_appsrc_enough_data(GstElement *element, gpointer user_data)
2282 {
2283         mmplayer_t *player  = (mmplayer_t *)user_data;
2284         mmplayer_stream_type_e stream_type = MM_PLAYER_STREAM_TYPE_DEFAULT;
2285         MMMessageParamType msg_param = {0,};
2286         guint64 current_level_bytes = 0;
2287
2288         MMPLAYER_RETURN_IF_FAIL(player);
2289
2290         if (g_strrstr(GST_ELEMENT_NAME(element), "audio")) {
2291                 stream_type = MM_PLAYER_STREAM_TYPE_AUDIO;
2292         } else if (g_strrstr(GST_ELEMENT_NAME(element), "video")) {
2293                 stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
2294         } else {
2295                 LOGW("invalid enough-data signal from %s", GST_ELEMENT_NAME(element));
2296                 return;
2297         }
2298
2299         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
2300
2301         LOGI("stream type: %d, level: %"G_GUINT64_FORMAT, stream_type, current_level_bytes);
2302
2303         msg_param.union_type = MM_MSG_UNION_BUFFER_STATUS;
2304         msg_param.buffer_status.stream_type = stream_type;
2305         msg_param.buffer_status.status = MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW;
2306         msg_param.buffer_status.bytes = current_level_bytes;
2307
2308         MMPLAYER_POST_MSG(player, MM_MESSAGE_PUSH_BUFFER_STATUS, &msg_param);
2309 }
2310
2311 gboolean
2312 __mmplayer_gst_appsrc_seek_data(GstElement *element, guint64 position, gpointer user_data)
2313 {
2314         mmplayer_t *player  = (mmplayer_t *)user_data;
2315         mmplayer_stream_type_e stream_type = MM_PLAYER_STREAM_TYPE_DEFAULT;
2316         MMMessageParamType msg_param = {0,};
2317
2318         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
2319
2320         if (g_strrstr(GST_ELEMENT_NAME(element), "audio")) {
2321                 stream_type = MM_PLAYER_STREAM_TYPE_AUDIO;
2322         } else if (g_strrstr(GST_ELEMENT_NAME(element), "video")) {
2323                 stream_type = MM_PLAYER_STREAM_TYPE_VIDEO;
2324         } else {
2325                 LOGW("invalid seek-data signal from %s", GST_ELEMENT_NAME(element));
2326                 return TRUE;
2327         }
2328
2329         LOGD("stream type: %d, pos: %"G_GUINT64_FORMAT, stream_type, position);
2330
2331         msg_param.union_type = MM_MSG_UNION_SEEK_DATA;
2332         msg_param.seek_data.stream_type = stream_type;
2333         msg_param.seek_data.offset = position;
2334
2335         MMPLAYER_POST_MSG(player, MM_MESSAGE_PUSH_BUFFER_SEEK_DATA, &msg_param);
2336
2337         return TRUE;
2338 }
2339
2340 static gboolean
2341 __mmplayer_gst_create_es_decoder(mmplayer_t *player, mmplayer_stream_type_e type, GstPad *srcpad)
2342 {
2343 #define MAX_LEN_NAME 20
2344
2345         gboolean ret = FALSE;
2346         GstPad *sinkpad = NULL;
2347         gchar *prefix = NULL;
2348         gchar dec_name[MAX_LEN_NAME] = {0, };
2349         main_element_id_e elem_id = MMPLAYER_M_NUM;
2350
2351         mmplayer_gst_element_t *mainbin = NULL;
2352         GstElement *decodebin = NULL;
2353         GstCaps *dec_caps = NULL;
2354
2355         MMPLAYER_FENTER();
2356
2357         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
2358                                                 player->pipeline &&
2359                                                 player->pipeline->mainbin, FALSE);
2360         MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
2361
2362         mainbin = player->pipeline->mainbin;
2363         switch (type) {
2364         case MM_PLAYER_STREAM_TYPE_AUDIO:
2365                 prefix = "audio";
2366                 elem_id = MMPLAYER_M_AUTOPLUG_A_DEC;
2367         break;
2368         case MM_PLAYER_STREAM_TYPE_VIDEO:
2369                 prefix = "video";
2370                 elem_id = MMPLAYER_M_AUTOPLUG_V_DEC;
2371         break;
2372         default:
2373                 LOGE("invalid type %d", type);
2374                 return FALSE;
2375         }
2376
2377         if (mainbin[elem_id].gst) {
2378                 LOGE("elem(%d) is already created", elem_id);
2379                 return FALSE;
2380         }
2381
2382         snprintf(dec_name, sizeof(dec_name), "%s_decodebin", prefix);
2383
2384         /* create decodebin */
2385         decodebin = gst_element_factory_make("decodebin", dec_name);
2386         if (!decodebin) {
2387                 LOGE("failed to create %s", dec_name);
2388                 return FALSE;
2389         }
2390
2391         /* raw pad handling signal */
2392         _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
2393                                                                                 G_CALLBACK(_mmplayer_gst_decode_pad_added), (gpointer)player);
2394
2395         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
2396         before looking for any elements that can handle that stream.*/
2397         _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
2398                                                                                 G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
2399
2400         if (player->need_video_dec_sorting || player->need_audio_dec_sorting)
2401                 _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-sort",
2402                                                         G_CALLBACK(_mmplayer_gst_decode_autoplug_sort), (gpointer)player);
2403
2404         /* This signal is emitted when a element is added to the bin.*/
2405         _mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
2406                                                                                 G_CALLBACK(_mmplayer_gst_element_added), (gpointer)player);
2407
2408         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
2409                 LOGE("failed to add new decodebin");
2410                 return FALSE;
2411         }
2412
2413         dec_caps = gst_pad_query_caps(srcpad, NULL);
2414         if (dec_caps) {
2415 #ifdef __DEBUG__
2416                 LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
2417 #endif
2418                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
2419                 gst_caps_unref(dec_caps);
2420         }
2421
2422         sinkpad = gst_element_get_static_pad(decodebin, "sink");
2423
2424         if (!sinkpad || gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
2425                 LOGE("failed to link [%s:%s] to decoder", GST_DEBUG_PAD_NAME(srcpad));
2426                 goto ERROR;
2427         }
2428         gst_object_unref(GST_OBJECT(sinkpad));
2429
2430         gst_element_sync_state_with_parent(decodebin);
2431
2432         mainbin[elem_id].id = elem_id;
2433         mainbin[elem_id].gst = decodebin;
2434
2435         MMPLAYER_FLEAVE();
2436         return TRUE;
2437
2438 ERROR:
2439         if (sinkpad)
2440                 gst_object_unref(GST_OBJECT(sinkpad));
2441
2442         if (decodebin) {
2443                 gst_element_set_state(decodebin, GST_STATE_NULL);
2444                 if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin))
2445                         gst_object_unref(decodebin);
2446         }
2447
2448         MMPLAYER_FLEAVE();
2449         return ret;
2450 }
2451
2452 static gboolean
2453 __mmplayer_gst_create_es_path(mmplayer_t *player, mmplayer_stream_type_e type, GstCaps *caps)
2454 {
2455 #define MAX_LEN_NAME 20
2456         mmplayer_gst_element_t *mainbin = NULL;
2457         gchar *prefix = NULL;
2458         main_element_id_e src_id = MMPLAYER_M_NUM, queue_id = MMPLAYER_M_NUM;
2459
2460         gchar src_name[MAX_LEN_NAME] = {0, }, queue_name[MAX_LEN_NAME] = {0, };
2461         GstElement *src = NULL, *queue = NULL;
2462         GstPad *srcpad = NULL;
2463
2464         MMPLAYER_FENTER();
2465         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
2466                                 player->pipeline->mainbin, FALSE);
2467
2468         mainbin = player->pipeline->mainbin;
2469
2470         LOGD("type(%d) path is creating", type);
2471         switch (type) {
2472         case MM_PLAYER_STREAM_TYPE_AUDIO:
2473                 prefix = "audio";
2474                 if (mainbin[MMPLAYER_M_SRC].gst)
2475                         src_id = MMPLAYER_M_2ND_SRC;
2476                 else
2477                         src_id = MMPLAYER_M_SRC;
2478                 queue_id = MMPLAYER_M_A_BUFFER;
2479         break;
2480         case MM_PLAYER_STREAM_TYPE_VIDEO:
2481                 prefix = "video";
2482                 src_id = MMPLAYER_M_SRC;
2483                 queue_id = MMPLAYER_M_V_BUFFER;
2484         break;
2485         case MM_PLAYER_STREAM_TYPE_TEXT:
2486                 prefix = "subtitle";
2487                 src_id = MMPLAYER_M_SUBSRC;
2488                 queue_id = MMPLAYER_M_S_BUFFER;
2489         break;
2490         default:
2491                 LOGE("invalid type %d", type);
2492                 return FALSE;
2493         }
2494
2495         snprintf(src_name, sizeof(src_name), "%s_appsrc", prefix);
2496         snprintf(queue_name, sizeof(queue_name), "%s_queue", prefix);
2497
2498         /* create source */
2499         src = gst_element_factory_make("appsrc", src_name);
2500         if (!src) {
2501                 LOGF("failed to create %s", src_name);
2502                 goto ERROR;
2503         }
2504
2505         mainbin[src_id].id = src_id;
2506         mainbin[src_id].gst = src;
2507
2508         g_object_set(G_OBJECT(src), "format", GST_FORMAT_TIME,
2509                                                                 "caps", caps, NULL);
2510
2511         /* size of many video frames are larger than default blocksize as 4096 */
2512         if (type == MM_PLAYER_STREAM_TYPE_VIDEO)
2513                 g_object_set(G_OBJECT(src), "blocksize", (guint)1048576, NULL);
2514
2515         if (player->media_stream_buffer_max_size[type] > 0)
2516                 g_object_set(G_OBJECT(src), "max-bytes", player->media_stream_buffer_max_size[type], NULL);
2517
2518         if (player->media_stream_buffer_min_percent[type] > 0)
2519                 g_object_set(G_OBJECT(src), "min-percent", player->media_stream_buffer_min_percent[type], NULL);
2520
2521         /*Fix Seek External Demuxer: set audio and video appsrc as seekable */
2522         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(src), GST_APP_STREAM_TYPE_SEEKABLE);
2523
2524         _mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
2525                                                                                         G_CALLBACK(__mmplayer_gst_appsrc_seek_data), (gpointer)player);
2526         _mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
2527                                                                                         G_CALLBACK(__mmplayer_gst_appsrc_feed_data), (gpointer)player);
2528         _mmplayer_add_signal_connection(player, G_OBJECT(src), MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
2529                                                                                         G_CALLBACK(__mmplayer_gst_appsrc_enough_data), (gpointer)player);
2530
2531         /* create queue */
2532         queue = gst_element_factory_make("queue2", queue_name);
2533         if (!queue) {
2534                 LOGE("failed to create %s", queue_name);
2535                 goto ERROR;
2536         }
2537         g_object_set(G_OBJECT(queue), "max-size-buffers", 2, NULL);
2538
2539         mainbin[queue_id].id = queue_id;
2540         mainbin[queue_id].gst = queue;
2541
2542         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[src_id].gst)) {
2543                 LOGE("failed to add src");
2544                 goto ERROR;
2545         }
2546
2547         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[queue_id].gst)) {
2548                 LOGE("failed to add queue");
2549                 goto ERROR;
2550         }
2551
2552         if (!gst_element_link(mainbin[src_id].gst, mainbin[queue_id].gst)) {
2553                 LOGE("failed to link src and queue");
2554                 goto ERROR;
2555         }
2556
2557         /* create decoder */
2558         srcpad = gst_element_get_static_pad(mainbin[queue_id].gst, "src");
2559         if (!srcpad) {
2560                 LOGE("failed to get srcpad of queue");
2561                 goto ERROR;
2562         }
2563
2564         if (type == MM_PLAYER_STREAM_TYPE_TEXT) {
2565                 _mmplayer_gst_create_decoder(player, srcpad, caps);
2566         } else {
2567                 if (!__mmplayer_gst_create_es_decoder(player, type, srcpad)) {
2568                         LOGE("failed to create decoder");
2569                         gst_object_unref(GST_OBJECT(srcpad));
2570                         goto ERROR;
2571                 }
2572         }
2573         gst_object_unref(GST_OBJECT(srcpad));
2574         return TRUE;
2575
2576 ERROR:
2577         if (mainbin[src_id].gst) {
2578                 gst_element_set_state(mainbin[src_id].gst, GST_STATE_NULL);
2579                 if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[src_id].gst))
2580                         gst_object_unref(mainbin[src_id].gst);
2581                 mainbin[src_id].gst = NULL;
2582         }
2583
2584         if (mainbin[queue_id].gst) {
2585                 gst_element_set_state(mainbin[queue_id].gst, GST_STATE_NULL);
2586                 if (!gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[queue_id].gst))
2587                         gst_object_unref(mainbin[queue_id].gst);
2588                 mainbin[queue_id].gst = NULL;
2589         }
2590
2591         return FALSE;
2592 }
2593
2594 static void
2595 __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data)
2596 {
2597         GstPad *sinkpad = NULL;
2598         GstCaps *caps = NULL;
2599         GstElement *new_element = NULL;
2600         GstStructure *str = NULL;
2601         const gchar *name = NULL;
2602
2603         mmplayer_t *player = (mmplayer_t *)data;
2604
2605         MMPLAYER_FENTER();
2606
2607         MMPLAYER_RETURN_IF_FAIL(element && pad);
2608         MMPLAYER_RETURN_IF_FAIL(player &&
2609                                         player->pipeline &&
2610                                         player->pipeline->mainbin);
2611
2612         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2613          * num_dynamic_pad will decreased after creating a sinkbin.
2614          */
2615         player->num_dynamic_pad++;
2616         LOGD("stream count inc : %d", player->num_dynamic_pad);
2617
2618         caps = gst_pad_query_caps(pad, NULL);
2619         MMPLAYER_CHECK_NULL(caps);
2620
2621         str = gst_caps_get_structure(caps, 0);
2622         name = gst_structure_get_string(str, "media");
2623         if (!name) {
2624                 LOGE("cannot get mimetype from structure.");
2625                 goto ERROR;
2626         }
2627
2628         if (strstr(name, "video")) {
2629                 gint stype = 0;
2630                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2631
2632                 if ((stype == MM_DISPLAY_SURFACE_NULL) && (!player->set_mode.video_export)) {
2633                         if (player->v_stream_caps) {
2634                                 gst_caps_unref(player->v_stream_caps);
2635                                 player->v_stream_caps = NULL;
2636                         }
2637
2638                         new_element = gst_element_factory_make("fakesink", NULL);
2639                         player->num_dynamic_pad--;
2640                         goto NEW_ELEMENT;
2641                 }
2642         }
2643
2644         if (!_mmplayer_gst_create_decoder(player, pad, caps)) {
2645                 LOGE("failed to autoplug for caps");
2646                 goto ERROR;
2647         }
2648
2649         gst_caps_unref(caps);
2650         caps = NULL;
2651
2652 NEW_ELEMENT:
2653
2654         /* execute new_element if created*/
2655         if (new_element) {
2656                 LOGD("adding new element to pipeline");
2657
2658                 /* set state to READY before add to bin */
2659                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
2660
2661                 /* add new element to the pipeline */
2662                 if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
2663                         LOGE("failed to add autoplug element to bin");
2664                         goto ERROR;
2665                 }
2666
2667                 /* get pad from element */
2668                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
2669                 if (!sinkpad) {
2670                         LOGE("failed to get sinkpad from autoplug element");
2671                         goto ERROR;
2672                 }
2673
2674                 /* link it */
2675                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2676                         LOGE("failed to link autoplug element");
2677                         goto ERROR;
2678                 }
2679
2680                 gst_object_unref(sinkpad);
2681                 sinkpad = NULL;
2682
2683                 /* run. setting PLAYING here since streaming source is live source */
2684                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
2685         }
2686
2687         if (caps)
2688                 gst_caps_unref(caps);
2689
2690         MMPLAYER_FLEAVE();
2691
2692         return;
2693
2694 STATE_CHANGE_FAILED:
2695 ERROR:
2696         /* FIXIT : take care if new_element has already added to pipeline */
2697         if (new_element)
2698                 gst_object_unref(GST_OBJECT(new_element));
2699
2700         if (sinkpad)
2701                 gst_object_unref(GST_OBJECT(sinkpad));
2702
2703         if (caps)
2704                 gst_caps_unref(caps);
2705
2706         /* FIXIT : how to inform this error to MSL ????? */
2707         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2708          * then post an error to application
2709          */
2710 }
2711
2712 static void
2713 __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data)
2714 {
2715         mmplayer_t *player = (mmplayer_t *)data;
2716
2717         MMPLAYER_FENTER();
2718
2719         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2720          * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2721          * num_dynamic_pad. and this is no-more-pad situation which means no more pad will be added.
2722          * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2723
2724          * [1] audio and video will be dumped with filesink.
2725          * [2] autoplugging is done by just using pad caps.
2726          * [3] typefinding has happened in audio but audiosink is created already before no-more-pad signal
2727          * and the video will be dumped via filesink.
2728          */
2729         if (player->num_dynamic_pad == 0) {
2730                 LOGD("it seems pad caps is directly used for autoplugging. removing fakesink now");
2731
2732                 if (!_mmplayer_gst_remove_fakesink(player,
2733                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
2734                         /* NOTE : _mmplayer_pipeline_complete() can be called several time. because
2735                          * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
2736                          * source element are not same. To overcome this situation, this function will called
2737                          * several places and several times. Therefore, this is not an error case.
2738                          */
2739                         return;
2740         }
2741
2742         /* create dot before error-return. for debugging */
2743         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-no-more-pad");
2744
2745         player->no_more_pad = TRUE;
2746
2747         MMPLAYER_FLEAVE();
2748 }
2749
2750 static GstElement *
2751 __mmplayer_gst_make_rtsp_src(mmplayer_t *player)
2752 {
2753         GstElement *element = NULL;
2754         gchar *user_agent = NULL;
2755         MMHandleType attrs = 0;
2756
2757         MMPLAYER_FENTER();
2758         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
2759
2760         /* get profile attribute */
2761         attrs = MMPLAYER_GET_ATTRS(player);
2762         if (!attrs) {
2763                 LOGE("failed to get content attribute");
2764                 return NULL;
2765         }
2766
2767         element = gst_element_factory_make("rtspsrc", "rtsp source");
2768         if (!element) {
2769                 LOGE("failed to create rtspsrc element");
2770                 return NULL;
2771         }
2772
2773         /* get attribute */
2774         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
2775
2776         SECURE_LOGD("user_agent : %s", user_agent);
2777
2778         /* setting property to streaming source */
2779         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
2780         if (user_agent)
2781                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
2782
2783         _mmplayer_add_signal_connection(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
2784                                                                         G_CALLBACK(__mmplayer_gst_rtp_dynamic_pad), (gpointer)player);
2785         _mmplayer_add_signal_connection(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
2786                                                                         G_CALLBACK(__mmplayer_gst_rtp_no_more_pads), (gpointer)player);
2787
2788         MMPLAYER_FLEAVE();
2789         return element;
2790 }
2791
2792 static void __mmplayer_http_src_setup(GstElement *source, gpointer data)
2793 {
2794 #define HTTP_SOURCE_BLOCK_SIZE (64 * 1024)
2795
2796         mmplayer_t *player = (mmplayer_t *)data;
2797         MMHandleType attrs = 0;
2798         gchar *user_agent, *cookies, **cookie_list;
2799         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
2800         user_agent = cookies = NULL;
2801         cookie_list = NULL;
2802
2803         MMPLAYER_FENTER();
2804         MMPLAYER_RETURN_IF_FAIL(player);
2805
2806         LOGD("source element %s", GST_ELEMENT_NAME(source));
2807
2808         attrs = MMPLAYER_GET_ATTRS(player);
2809         if (!attrs) {
2810                 LOGE("failed to get content attribute");
2811                 return;
2812         }
2813
2814         mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
2815         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
2816
2817         if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT)
2818                 http_timeout = player->ini.http_timeout;
2819
2820         SECURE_LOGD("cookies : %s", cookies);
2821         SECURE_LOGD("user_agent :  %s", user_agent);
2822         LOGD("timeout : %d", http_timeout);
2823
2824         g_object_set(G_OBJECT(source), "timeout", http_timeout, "blocksize", (unsigned long)(HTTP_SOURCE_BLOCK_SIZE), NULL);
2825
2826         if ((cookie_list = _mmplayer_get_cookie_list((const char *)cookies))) {
2827                 g_object_set(G_OBJECT(source), "cookies", cookie_list, NULL);
2828                 g_strfreev(cookie_list);
2829         }
2830
2831         if (user_agent)
2832                 g_object_set(G_OBJECT(source), "user-agent", user_agent, NULL);
2833
2834         MMPLAYER_FLEAVE();
2835         return;
2836 }
2837
2838 static void __mmplayer_rtsp_src_setup(GstElement *source, gpointer data)
2839 {
2840         mmplayer_t *player = (mmplayer_t *)data;
2841         gchar *user_agent = NULL;
2842         MMHandleType attrs = 0;
2843
2844         MMPLAYER_FENTER();
2845         MMPLAYER_RETURN_IF_FAIL(player);
2846
2847         attrs = MMPLAYER_GET_ATTRS(player);
2848         if (!attrs) {
2849                 LOGE("failed to get content attribute");
2850                 return;
2851         }
2852
2853         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
2854
2855         SECURE_LOGD("user_agent : %s", user_agent);
2856
2857         if (user_agent)
2858                 g_object_set(G_OBJECT(source), "user-agent", user_agent, NULL);
2859
2860         MMPLAYER_FLEAVE();
2861 }
2862
2863 static void
2864 __mmplayer_gst_found_source(GObject *object, GObject *orig, GParamSpec *pspec, gpointer data)
2865 {
2866         mmplayer_t *player = (mmplayer_t *)data;
2867         GstElement *source = NULL;
2868
2869         MMPLAYER_FENTER();
2870         LOGD("%s >> %s", GST_ELEMENT_NAME(object), pspec->name);
2871
2872         g_object_get(orig, pspec->name, &source, NULL);
2873
2874         player->pipeline->mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
2875         player->pipeline->mainbin[MMPLAYER_M_SRC].gst = source;
2876
2877         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
2878                 __mmplayer_http_src_setup(source, data);
2879         } else if (MMPLAYER_IS_RTSP_STREAMING(player)) {
2880                 __mmplayer_rtsp_src_setup(source, data);
2881         } else if (MMPLAYER_IS_SMOOTH_STREAMING(player)) {
2882                 g_object_set(G_OBJECT(source), "timeout", DEFAULT_HTTP_TIMEOUT, NULL);
2883         } else if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) {
2884                 g_object_set(source, "stream-type", GST_APP_STREAM_TYPE_RANDOM_ACCESS,
2885                         "size", (gint64)player->profile.input_mem.len, "blocksize", 20480, NULL);
2886
2887                 _mmplayer_add_signal_connection(player, G_OBJECT(source), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
2888                                                 G_CALLBACK(__mmplayer_gst_appsrc_seek_data_mem), (gpointer)&player->profile.input_mem);
2889                 _mmplayer_add_signal_connection(player, G_OBJECT(source), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
2890                                                 G_CALLBACK(__mmplayer_gst_appsrc_feed_data_mem), (gpointer)&player->profile.input_mem);
2891         }
2892         gst_object_unref (source);
2893
2894         MMPLAYER_FLEAVE();
2895 }
2896
2897 static gint
2898 __mmplayer_gst_select_stream (GstElement * uridecodebin, GstStreamCollection * collection,
2899     GstStream * stream, gpointer data)
2900 {
2901 #define RET_SELECT 1
2902 #define RET_SKIP 0
2903 #define RET_DEPENDS_ON_DECODEBIN -1
2904
2905         GstStreamType stype = gst_stream_get_stream_type(stream);
2906         mmplayer_t *player = (mmplayer_t *)data;
2907         mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_MAX;
2908         g_autoptr(GstCaps) caps = gst_stream_get_caps(stream);
2909         g_autofree gchar *caps_str = NULL;
2910         GstStructure *caps_structure = NULL;
2911         int stream_index = INVALID_TRACK_INDEX;
2912         int ret = MM_ERROR_NONE;
2913
2914         LOGD("Stream type %s flags 0x%x",
2915                         gst_stream_type_get_name(stype),
2916                         gst_stream_get_stream_flags(stream));
2917         LOGD("  ID: %s", gst_stream_get_stream_id(stream));
2918
2919         type = __mmplayer_convert_gst_stream_type_to_track_type(stype);
2920
2921         if (caps) {
2922                 caps_str = gst_caps_to_string(caps);
2923                 caps_structure = gst_caps_get_structure(caps, 0);
2924                 const gchar *mime = gst_structure_get_name(caps_structure);
2925
2926                 LOGD("  caps: %s", caps_str);
2927
2928                 for (int idx = 0; player->ini.unsupported_codec_keyword[idx][0] != '\0'; idx++) {
2929                         if (caps_str && strstr(caps_str, player->ini.unsupported_codec_keyword[idx])) {
2930                                 LOGW("skip [%s] by unsupported codec keyword [%s]",
2931                                                 mime, player->ini.unsupported_codec_keyword[idx]);
2932
2933                                 _mmplayer_update_not_supported_codec_info(player, NULL, mime);
2934                                 return RET_SKIP;
2935                         }
2936                 }
2937         } else if (type == MM_PLAYER_TRACK_TYPE_AUDIO || type == MM_PLAYER_TRACK_TYPE_VIDEO) {
2938                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player) || MMPLAYER_IS_DASH_STREAMING(player)) {
2939                         LOGD("No caps info, depends on decodebin");
2940                         _mmplayer_track_update_stream(player, type, stream);
2941                         return RET_DEPENDS_ON_DECODEBIN;
2942                 }
2943
2944                 LOGD("No caps info, skip it");
2945                 return RET_SKIP;
2946         }
2947
2948         switch (stype) {
2949         case GST_STREAM_TYPE_AUDIO:
2950         {
2951                 if (caps_structure) {
2952                         gint samplerate = 0;
2953                         gint channels = 0;
2954
2955                         gst_structure_get_int(caps_structure, "rate", &samplerate);
2956                         gst_structure_get_int(caps_structure, "channels", &channels);
2957                         if (samplerate == 0 && channels > 0) {
2958                                 LOGW("Skip corrupted audio stream");
2959                                 return RET_SKIP;
2960                         }
2961
2962                         if (g_strrstr(caps_str, "mobile-xmf"))
2963                                 mm_player_set_attribute((MMHandleType)player, NULL,
2964                                         "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL);
2965                 }
2966                 break;
2967         }
2968         case GST_STREAM_TYPE_VIDEO:
2969         {
2970                 if (player->track[MM_PLAYER_TRACK_TYPE_VIDEO].total_track_num >= 1) {
2971                         LOGD("do not support muti track video");
2972                         break;
2973                 }
2974
2975                 // FIXME: it cause block during preparing
2976                 if ((!MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) && (!MMPLAYER_IS_DASH_STREAMING(player))) {
2977                         gint stype = 0;
2978
2979                         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2980                         /* don't make video because of not required */
2981                         if ((stype == MM_DISPLAY_SURFACE_NULL) &&
2982                                 (!player->set_mode.video_export)) {
2983                                 LOGD("no need video decoding, skip video stream");
2984                                 return RET_SKIP;
2985                         }
2986                 }
2987
2988                 if (caps_structure) {
2989                         gint width = 0;
2990
2991                         gst_structure_get_int(caps_structure, "width", &width);
2992                         if (width != 0) {
2993                                 if (player->v_stream_caps) {
2994                                         gst_caps_unref(player->v_stream_caps);
2995                                         player->v_stream_caps = NULL;
2996                                 }
2997
2998                                 player->v_stream_caps = gst_caps_copy(caps);
2999                                 MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
3000                         }
3001                 }
3002                 break;
3003         }
3004         case GST_STREAM_TYPE_TEXT:
3005                 break;
3006         default:
3007                 LOGW("Skip not supported stream type");
3008                 return RET_SKIP;
3009         }
3010
3011         _mmplayer_track_update_stream(player, type, stream);
3012
3013         ret = _mmplayer_get_track_index(player, type, stream, &stream_index);
3014
3015         if ((player->track[type].active_track_index == INVALID_TRACK_INDEX) &&
3016                 (ret == MM_ERROR_NONE)) {
3017                 player->track[type].active_track_index = stream_index;
3018                 LOGD("select this stream, active track idx : %d", player->track[type].active_track_index);
3019                 if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
3020                         _mmplayer_set_audio_attrs(player, caps);
3021                 return RET_SELECT;
3022         }
3023
3024         if (player->track[type].active_track_index == stream_index) {
3025                 LOGD("already activate track idx : %d", player->track[type].active_track_index);
3026                 return RET_SELECT;
3027         }
3028
3029         LOGD("Skip stream");
3030         return RET_SKIP;
3031 }
3032
3033 static gboolean
3034 __mmplayer_gst_decode_request_resource(GstElement * uridecodebin, GstStreamCollection * collection,
3035     GstStream * stream, gpointer data)
3036 {
3037         mmplayer_t *player = (mmplayer_t *)data;
3038         GstStreamType stype = gst_stream_get_stream_type(stream);
3039
3040         MMPLAYER_FENTER();
3041         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3042
3043         LOGD("stream type %s", gst_stream_type_get_name(stype));
3044
3045         /* public does not support audio hw decoder at the moment */
3046
3047         if (player->hw_resource[MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER] != NULL) {
3048                 LOGW("video decoder resource is already acquired, skip it.");
3049                 return TRUE;
3050         }
3051
3052         if (_mmplayer_acquire_hw_resource(player, MMPLAYER_RESOURCE_TYPE_VIDEO_DECODER) != MM_ERROR_NONE) {
3053                 LOGE("failed to acquire video decoder resource");
3054                 return FALSE;
3055         }
3056         player->interrupted_by_resource = FALSE;
3057         MMPLAYER_FLEAVE();
3058         return TRUE;
3059 }
3060
3061 static GstElement *
3062 __mmplayer_gst_find_child_element(GstBin *bin, const gchar *element_name)
3063 {
3064         GstIterator *iter = NULL;
3065         GValue item = {0, };
3066         GstElement *ch_element = NULL;
3067         GstElementFactory *ch_factory = NULL;
3068
3069         MMPLAYER_FENTER();
3070         MMPLAYER_RETURN_VAL_IF_FAIL(bin && element_name, NULL);
3071
3072         iter = gst_bin_iterate_recurse(bin);
3073         MMPLAYER_RETURN_VAL_IF_FAIL(iter, NULL);
3074
3075         while (gst_iterator_next(iter, &item) == GST_ITERATOR_OK) {
3076                 ch_element = g_value_get_object(&item);
3077                 ch_factory = gst_element_get_factory(ch_element);
3078                 LOGD("children factory %s", GST_OBJECT_NAME(ch_factory));
3079                 if (g_strrstr(GST_OBJECT_NAME(ch_factory), element_name)) {
3080                         LOGD("Find %s element", element_name);
3081                         break;
3082                 }
3083                 ch_element = NULL;
3084                 g_value_reset(&item);
3085         }
3086         gst_iterator_free(iter);
3087
3088         MMPLAYER_FLEAVE();
3089         return ch_element;
3090 }
3091
3092 static void __mmplayer_parsebin_setup(GstBin *bin, gpointer data)
3093 {
3094         mmplayer_t *player = (mmplayer_t *)data;
3095
3096         g_object_set(G_OBJECT(bin), "message-forward", TRUE, NULL);
3097
3098         _mmplayer_add_signal_connection(player, G_OBJECT(bin),
3099         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
3100                         G_CALLBACK(_mmplayer_gst_decode_unknown_type), (gpointer)player);
3101
3102         _mmplayer_add_signal_connection(player, G_OBJECT(bin),
3103         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
3104                         G_CALLBACK(_mmplayer_gst_decode_autoplug_select), (gpointer)player);
3105 }
3106
3107 static void __mmplayer_decodebin3_setup(GstBin *bin, gpointer data)
3108 {
3109         mmplayer_t *player = (mmplayer_t *)data;
3110         int video_codec_type = 0;
3111         int audio_codec_type = 0;
3112
3113         g_object_set(G_OBJECT(bin), "message-forward", TRUE, NULL);
3114
3115         mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_VIDEO_CODEC_TYPE, &video_codec_type);
3116         mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_CODEC_TYPE, &audio_codec_type);
3117
3118         LOGD("set codec type v(%d) a(%d)", video_codec_type, audio_codec_type);
3119
3120         if (video_codec_type == MM_PLAYER_CODEC_TYPE_SW)
3121                 g_object_set(G_OBJECT(bin), "force-sw-decoders-for-video", TRUE, NULL);
3122         if (audio_codec_type == MM_PLAYER_CODEC_TYPE_SW)
3123                 g_object_set(G_OBJECT(bin), "force-sw-decoders-for-audio", TRUE, NULL);
3124
3125         _mmplayer_add_signal_connection(player, G_OBJECT(bin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG,
3126                         "request-resource", G_CALLBACK(__mmplayer_gst_decode_request_resource), (gpointer)player);
3127 }
3128
3129 static void
3130 __mmplayer_gst_deep_element_added(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
3131 {
3132         gchar *factory_name = NULL;
3133         mmplayer_t *player = (mmplayer_t *)data;
3134
3135         MMPLAYER_FENTER();
3136         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
3137
3138         factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
3139
3140         LOGD("child: %s, elem: %s (%s)", GST_ELEMENT_NAME(child), factory_name, GST_ELEMENT_NAME(element));
3141
3142         if (g_strrstr(factory_name, "urisourcebin")) {
3143                 GstElement *dbin3 = __mmplayer_gst_find_child_element(child, "decodebin3");
3144                 if (dbin3) {
3145                         GstElement *mq = __mmplayer_gst_find_child_element(child, "multiqueue");
3146                         if (mq)
3147                                 g_object_set(G_OBJECT(mq), "use-interleave", FALSE, NULL);
3148
3149                         __mmplayer_decodebin3_setup(GST_BIN(dbin3), data);
3150                 } else {
3151                         LOGW("failed to find decodebin3");
3152                 }
3153         } else if (g_strrstr(factory_name, "parsebin")) {
3154                 g_object_set(G_OBJECT(child), "message-forward", TRUE, NULL); /* urisourcebin */
3155                 __mmplayer_parsebin_setup(GST_BIN(element), data);
3156         } else {
3157                 _mmplayer_gst_element_added(child, element, data);
3158         }
3159 }
3160
3161 static void
3162 __mmplayer_delete_signal_connection(mmplayer_t *player, GstElement *removed_element)
3163 {
3164         MMPLAYER_FENTER();
3165
3166         MMPLAYER_RETURN_IF_FAIL(player);
3167         MMPLAYER_RETURN_IF_FAIL(removed_element);
3168
3169         LOGD("delete signal on %s", GST_ELEMENT_NAME(removed_element));
3170
3171         for (int type = MM_PLAYER_SIGNAL_TYPE_AUTOPLUG; type < MM_PLAYER_SIGNAL_TYPE_ALL; type++) {
3172                 GList *node = player->signals[type];
3173                 while (node) {
3174                         GList *next_node = node->next;
3175                         mmplayer_signal_item_t *item = node->data;
3176                         if (item && item->obj == G_OBJECT(removed_element)) {
3177                                 player->signals[type] = g_list_delete_link(player->signals[type], node);
3178                                 MMPLAYER_FREEIF(item);
3179                         }
3180                         node = next_node;
3181                 }
3182         }
3183
3184         MMPLAYER_FLEAVE();
3185 }
3186
3187 void
3188 __mmplayer_gst_deep_element_removed(GstElement *bin, GstBin *child, GstElement *element, gpointer data)
3189 {
3190         mmplayer_t *player = (mmplayer_t *)data;
3191
3192         MMPLAYER_FENTER();
3193
3194         MMPLAYER_RETURN_IF_FAIL(player);
3195
3196         LOGD("%s > %s > %s", GST_ELEMENT_NAME(bin), GST_ELEMENT_NAME(child), GST_ELEMENT_NAME(element));
3197
3198         __mmplayer_delete_signal_connection(player, element);
3199
3200         MMPLAYER_FLEAVE();
3201 }
3202
3203 static GstElement *
3204 __mmplayer_gst_make_uridecodebin(mmplayer_t *player)
3205 {
3206         GstElement *uridecodebin3 = NULL;
3207
3208         MMPLAYER_FENTER();
3209         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
3210
3211         uridecodebin3 = gst_element_factory_make("uridecodebin3", "uridecodebin3");
3212         if (!uridecodebin3) {
3213                 LOGE("failed to create uridecodebin3");
3214                 return NULL;
3215         }
3216
3217         /* get attribute */
3218         SECURE_LOGD("uri : %s", player->profile.uri);
3219
3220         /* setting property to streaming source */
3221         g_object_set(G_OBJECT(uridecodebin3), "uri", player->profile.uri,
3222                         "message-forward", TRUE,
3223                         "buffer-size", DEFAULT_BUFFER_SIZE_BYTES,
3224                         "use-buffering", TRUE, NULL);
3225
3226         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3227                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-notify::source", G_CALLBACK(__mmplayer_gst_found_source), (gpointer)player);
3228
3229         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3230                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", G_CALLBACK(_mmplayer_gst_decode_pad_added), (gpointer)player);
3231
3232         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3233                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed", G_CALLBACK(_mmplayer_gst_decode_pad_removed), (gpointer)player);
3234
3235         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3236                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads", G_CALLBACK(_mmplayer_gst_decode_no_more_pads), (gpointer)player);
3237
3238         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3239                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "select-stream", G_CALLBACK(__mmplayer_gst_select_stream), (gpointer)player);
3240
3241         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3242                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "about-to-finish", G_CALLBACK(_mmplayer_gst_about_to_finish), (gpointer)player);
3243
3244         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3245                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-element-added", G_CALLBACK(__mmplayer_gst_deep_element_added), (gpointer)player);
3246
3247         _mmplayer_add_signal_connection(player, G_OBJECT(uridecodebin3),
3248                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "deep-element-removed", G_CALLBACK(__mmplayer_gst_deep_element_removed), (gpointer)player);
3249
3250         if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
3251                 LOGW("[DASH] this is still experimental feature");
3252
3253         MMPLAYER_FLEAVE();
3254         return uridecodebin3;
3255 }
3256
3257 static GstElement *
3258 __mmplayer_gst_make_http_src(mmplayer_t *player)
3259 {
3260 #define MAX_RETRY_COUNT 10
3261         GstElement *element = NULL;
3262         MMHandleType attrs = 0;
3263         gchar *user_agent, *cookies, **cookie_list;
3264         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
3265
3266         user_agent = cookies = NULL;
3267         cookie_list = NULL;
3268
3269         MMPLAYER_FENTER();
3270         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
3271
3272         /* get profile attribute */
3273         attrs = MMPLAYER_GET_ATTRS(player);
3274         if (!attrs) {
3275                 LOGE("failed to get content attribute");
3276                 return NULL;
3277         }
3278
3279         LOGD("using http streaming source [%s]", player->ini.httpsrc_element);
3280
3281         element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
3282         if (!element) {
3283                 LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
3284                 return NULL;
3285         }
3286
3287         /* get attribute */
3288         mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
3289         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
3290
3291         if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT)
3292                 http_timeout = player->ini.http_timeout;
3293
3294         /* get attribute */
3295         SECURE_LOGD("location : %s", player->profile.uri);
3296         SECURE_LOGD("cookies : %s", cookies);
3297         SECURE_LOGD("user_agent :  %s", user_agent);
3298         LOGD("timeout : %d", http_timeout);
3299
3300         /* setting property to streaming source */
3301         g_object_set(G_OBJECT(element), "location", player->profile.uri,
3302                                 "timeout", http_timeout, "blocksize", (unsigned long)(64 * 1024),
3303                                 "retries", MAX_RETRY_COUNT, NULL);
3304
3305         /* parsing cookies */
3306         if ((cookie_list = _mmplayer_get_cookie_list((const char *)cookies))) {
3307                 g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
3308                 g_strfreev(cookie_list);
3309         }
3310
3311         if (user_agent)
3312                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
3313
3314         if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
3315                 LOGW("[DASH] this is still experimental feature");
3316
3317         MMPLAYER_FLEAVE();
3318         return element;
3319 }
3320
3321 static GstElement *
3322 __mmplayer_gst_make_file_src(mmplayer_t *player)
3323 {
3324         GstElement *element = NULL;
3325
3326         MMPLAYER_FENTER();
3327         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
3328
3329         LOGD("using filesrc for 'file://' handler");
3330         if (!_mmplayer_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
3331                 LOGE("failed to get storage info");
3332                 return NULL;
3333         }
3334
3335         element = gst_element_factory_make("filesrc", "source");
3336         if (!element) {
3337                 LOGE("failed to create filesrc");
3338                 return NULL;
3339         }
3340
3341         g_object_set(G_OBJECT(element), "location", (player->profile.uri) + 7, NULL); /* uri+7 -> remove "file:// */
3342
3343         MMPLAYER_FLEAVE();
3344         return element;
3345 }
3346
3347 static gboolean
3348 __mmplayer_gst_msg_push(GstBus *bus, GstMessage *msg, gpointer data)
3349 {
3350         mmplayer_t *player = (mmplayer_t *)data;
3351
3352         g_return_val_if_fail(player, FALSE);
3353         g_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
3354         gst_message_ref(msg);
3355
3356         g_mutex_lock(&player->bus_msg_q_lock);
3357         g_queue_push_tail(player->bus_msg_q, msg);
3358         g_mutex_unlock(&player->bus_msg_q_lock);
3359
3360         MMPLAYER_BUS_MSG_THREAD_LOCK(player);
3361         MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
3362         MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
3363         return TRUE;
3364 }
3365
3366 static gpointer __mmplayer_gst_bus_msg_thread(gpointer data)
3367 {
3368         mmplayer_t *player = (mmplayer_t *)(data);
3369         GstMessage *msg = NULL;
3370
3371         MMPLAYER_FENTER();
3372         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
3373                                                 player->pipeline &&
3374                                                 player->pipeline->mainbin &&
3375                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
3376                                                 NULL);
3377
3378         MMPLAYER_BUS_MSG_THREAD_LOCK(player);
3379
3380         LOGD("[handle: %p] gst bus msg thread will be started.", player);
3381         while (!player->bus_msg_thread_exit) {
3382                 g_mutex_lock(&player->bus_msg_q_lock);
3383                 msg = g_queue_pop_head(player->bus_msg_q);
3384                 g_mutex_unlock(&player->bus_msg_q_lock);
3385                 if (msg == NULL) {
3386                         MMPLAYER_BUS_MSG_THREAD_WAIT(player);
3387                         continue;
3388                 }
3389                 MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
3390                 /* handle the gst msg */
3391                 __mmplayer_gst_bus_msg_callback(msg, player);
3392                 MMPLAYER_BUS_MSG_THREAD_LOCK(player);
3393                 gst_message_unref(msg);
3394         }
3395
3396         MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
3397         MMPLAYER_FLEAVE();
3398
3399         return NULL;
3400 }
3401
3402 static int
3403 __mmplayer_gst_check_position(mmplayer_t *player, gint64 position)
3404 {
3405         gint64 dur_nsec = 0;
3406         gint64 pos_nsec = 0;
3407
3408         MMPLAYER_FENTER();
3409         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3410
3411         if (MMPLAYER_IS_MS_BUFF_SRC(player))
3412                 return MM_ERROR_NONE;
3413
3414         /* NOTE : duration cannot be zero except live streaming.
3415          *              Since some element could have some timing problem with querying duration, try again.
3416          */
3417         if (player->duration == 0) {
3418                 if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
3419                         /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
3420                          * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
3421                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
3422                                 (_mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
3423                                 player->pending_seek.is_pending = true;
3424                                 player->pending_seek.pos = position;
3425                                 player->seek_state = MMPLAYER_SEEK_NONE;
3426                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
3427                                 return MM_ERROR_PLAYER_NO_OP;
3428                         } else {
3429                                 player->seek_state = MMPLAYER_SEEK_NONE;
3430                                 return MM_ERROR_PLAYER_SEEK;
3431                         }
3432                 }
3433                 player->duration = dur_nsec;
3434         }
3435
3436         if (player->duration > 0 && player->duration < position) {
3437                 LOGE("invalid pos %"G_GINT64_FORMAT", dur: %"G_GINT64_FORMAT, position, player->duration);
3438                 return MM_ERROR_INVALID_ARGUMENT;
3439         }
3440
3441         if (gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec)) {
3442                 if ((pos_nsec == player->duration) && /* current pos is end of stream  */
3443                         ((position / GST_MSECOND) == (player->duration / GST_MSECOND))) {
3444                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
3445                         player->seek_state = MMPLAYER_SEEK_NONE;
3446                         return MM_ERROR_PLAYER_NO_OP;
3447                 }
3448         }
3449
3450         MMPLAYER_FLEAVE();
3451         return MM_ERROR_NONE;
3452 }
3453
3454 static gboolean
3455 __mmplayer_gst_check_seekable(mmplayer_t *player)
3456 {
3457         GstQuery *query = NULL;
3458         gboolean seekable = FALSE;
3459
3460         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
3461                 return TRUE;
3462         }
3463
3464         query = gst_query_new_seeking(GST_FORMAT_TIME);
3465         if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
3466                 gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
3467                 gst_query_unref(query);
3468
3469                 if (!seekable) {
3470                         LOGW("non-seekable content");
3471                         player->seek_state = MMPLAYER_SEEK_NONE;
3472                         return FALSE;
3473                 }
3474         } else {
3475                 LOGW("failed to get seeking query");
3476                 gst_query_unref(query); /* keep seeking operation */
3477         }
3478
3479         return TRUE;
3480 }
3481
3482 int
3483 _mmplayer_gst_set_state(mmplayer_t *player, GstElement *element,  GstState state, gboolean async, gint timeout)
3484 {
3485         GstState element_state = GST_STATE_VOID_PENDING;
3486         GstState element_pending_state = GST_STATE_VOID_PENDING;
3487         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
3488
3489         MMPLAYER_FENTER();
3490
3491         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3492         MMPLAYER_RETURN_VAL_IF_FAIL(element, MM_ERROR_INVALID_ARGUMENT);
3493
3494         LOGD("setting [%s] element state to : %s", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
3495
3496         /* set state */
3497         ret = gst_element_set_state(element, state);
3498         if (ret == GST_STATE_CHANGE_FAILURE) {
3499                 LOGE("failed to set [%s] state", GST_ELEMENT_NAME(element));
3500
3501                 /* dump state of all element */
3502                 _mmplayer_dump_pipeline_state(player);
3503
3504                 return MM_ERROR_PLAYER_INTERNAL;
3505         }
3506
3507         /* return here so state transition to be done in async mode */
3508         if (async) {
3509                 LOGD("async state transition. not waiting for state complete.");
3510                 return MM_ERROR_NONE;
3511         }
3512
3513         /* wait for state transition */
3514         ret = gst_element_get_state(element, &element_state, &element_pending_state, timeout * GST_SECOND);
3515         if (ret == GST_STATE_CHANGE_FAILURE || (state != element_state)) {
3516                 LOGE("failed to change [%s] element state to [%s] within %d sec",
3517                         GST_ELEMENT_NAME(element),
3518                         gst_element_state_get_name(state), timeout);
3519
3520                 LOGE(" [%s] state : %s   pending : %s",
3521                         GST_ELEMENT_NAME(element),
3522                         gst_element_state_get_name(element_state),
3523                         gst_element_state_get_name(element_pending_state));
3524
3525                 /* dump state of all element */
3526                 _mmplayer_dump_pipeline_state(player);
3527
3528                 return MM_ERROR_PLAYER_INTERNAL;
3529         }
3530
3531         LOGD("[%s] element state has changed", GST_ELEMENT_NAME(element));
3532
3533         MMPLAYER_FLEAVE();
3534
3535         return MM_ERROR_NONE;
3536 }
3537
3538 int
3539 _mmplayer_gst_start(mmplayer_t *player)
3540 {
3541         int ret = MM_ERROR_NONE;
3542         gboolean async = FALSE;
3543
3544         MMPLAYER_FENTER();
3545
3546         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3547
3548         /* NOTE : if SetPosition was called before Start. do it now
3549          * streaming doesn't support it. so it should be always sync
3550          * !!create one more api to check if there is pending seek rather than checking variables
3551          */
3552         if (player->pending_seek.is_pending && !MMPLAYER_IS_STREAMING(player)) {
3553                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
3554                 ret = _mmplayer_gst_pause(player, FALSE);
3555                 if (ret != MM_ERROR_NONE) {
3556                         LOGE("failed to set state to PAUSED for pending seek");
3557                         return ret;
3558                 }
3559
3560                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
3561                 if (__mmplayer_gst_pending_seek(player) != MM_ERROR_NONE)
3562                                 LOGW("failed to seek pending position. starting from the begin of content");
3563         }
3564
3565         LOGD("current state before doing transition");
3566         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
3567         MMPLAYER_PRINT_STATE(player);
3568
3569         /* set pipeline state to PLAYING  */
3570         ret = _mmplayer_gst_set_state(player,
3571                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
3572         if (ret != MM_ERROR_NONE) {
3573                 LOGE("failed to set state to PLAYING");
3574                 return ret;
3575         }
3576
3577         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
3578
3579         /* generating debug info before returning error */
3580         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-start");
3581
3582         MMPLAYER_FLEAVE();
3583
3584         return ret;
3585 }
3586
3587 int
3588 _mmplayer_gst_stop(mmplayer_t *player)
3589 {
3590         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
3591         MMHandleType attrs = 0;
3592         gboolean rewind = FALSE;
3593         gint timeout = 0;
3594         int ret = MM_ERROR_NONE;
3595
3596         MMPLAYER_FENTER();
3597
3598         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3599         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
3600
3601         LOGD("current state before doing transition");
3602         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
3603         MMPLAYER_PRINT_STATE(player);
3604
3605         attrs = MMPLAYER_GET_ATTRS(player);
3606         if (!attrs) {
3607                 LOGE("cannot get content attribute");
3608                 return MM_ERROR_PLAYER_INTERNAL;
3609         }
3610
3611         /* Just set state to PAUSED and the rewind. it's usual player behavior. */
3612         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
3613
3614         if ((!MMPLAYER_IS_STREAMING(player) && !MMPLAYER_IS_MS_BUFF_SRC(player)) ||
3615                 (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked))
3616                 rewind = TRUE;
3617
3618         if (player->es_player_push_mode)
3619                 /* disable the async state transition because there could be no data in the pipeline */
3620                 __mmplayer_gst_set_async(player, FALSE, MMPLAYER_SINK_ALL);
3621
3622         /* set gst state */
3623         ret = _mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout);
3624
3625         if (player->es_player_push_mode) {
3626                 /* enable the async state transition as default operation */
3627                 __mmplayer_gst_set_async(player, TRUE, MMPLAYER_SINK_ALL);
3628         }
3629
3630         /* return if set_state has failed */
3631         if (ret != MM_ERROR_NONE) {
3632                 LOGE("failed to set state.");
3633                 return ret;
3634         }
3635
3636         /* rewind */
3637         if (rewind) {
3638                 if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
3639                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
3640                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
3641                         LOGW("failed to rewind");
3642                         ret = MM_ERROR_PLAYER_SEEK;
3643                 }
3644         }
3645
3646         /* initialize */
3647         player->sent_bos = FALSE;
3648
3649         if (player->es_player_push_mode) //for cloudgame
3650                 timeout = 0;
3651
3652         /* wait for seek to complete */
3653         change_ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
3654         if (change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL) {
3655                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
3656         } else {
3657                 LOGE("fail to stop player.");
3658                 ret = MM_ERROR_PLAYER_INTERNAL;
3659                 _mmplayer_dump_pipeline_state(player);
3660         }
3661
3662         /* generate dot file if enabled */
3663         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-stop");
3664
3665         MMPLAYER_FLEAVE();
3666
3667         return ret;
3668 }
3669
3670 int
3671 _mmplayer_gst_pause(mmplayer_t *player, gboolean async)
3672 {
3673         int ret = MM_ERROR_NONE;
3674
3675         MMPLAYER_FENTER();
3676
3677         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3678         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
3679
3680         LOGD("current state before doing transition");
3681         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
3682         MMPLAYER_PRINT_STATE(player);
3683
3684         /* set pipeline status to PAUSED */
3685         ret = _mmplayer_gst_set_state(player,
3686                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
3687
3688         if (async)
3689                 goto EXIT;
3690
3691         if (ret != MM_ERROR_NONE) {
3692                 GstMessage *msg = NULL;
3693                 GTimer *timer = NULL;
3694                 gdouble MAX_TIMEOUT_SEC = 3;
3695
3696                 LOGE("failed to set state to PAUSED");
3697
3698                 if (!player->bus_watcher) {
3699                         LOGE("there is no bus msg thread. pipeline is shutting down.");
3700                         return ret;
3701                 }
3702
3703                 if (player->msg_posted) {
3704                         LOGE("error msg is already posted.");
3705                         return ret;
3706                 }
3707
3708                 timer = g_timer_new();
3709                 g_timer_start(timer);
3710
3711                 GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
3712
3713                 do {
3714                         msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
3715                         if (msg) {
3716                                 if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
3717                                         GError *error = NULL;
3718
3719                                         /* parse error code */
3720                                         gst_message_parse_error(msg, &error, NULL);
3721
3722                                         if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
3723                                                 /* Note : the streaming error from the streaming source is handled
3724                                                         *   using __mmplayer_handle_streaming_error.
3725                                                         */
3726                                                 __mmplayer_handle_streaming_error(player, msg, error);
3727
3728                                         } else if (error) {
3729                                                 LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
3730
3731                                                 if (error->domain == GST_STREAM_ERROR)
3732                                                         ret = __mmplayer_gst_handle_stream_error(player, error, msg);
3733                                                 else if (error->domain == GST_RESOURCE_ERROR)
3734                                                         ret = __mmplayer_gst_handle_resource_error(player, error->code, NULL);
3735                                                 else if (error->domain == GST_LIBRARY_ERROR)
3736                                                         ret = __mmplayer_gst_handle_library_error(player, error->code);
3737                                                 else if (error->domain == GST_CORE_ERROR)
3738                                                         ret = __mmplayer_gst_handle_core_error(player, error->code);
3739
3740                                                 g_error_free(error);
3741                                         }
3742                                         player->msg_posted = TRUE;
3743                                 }
3744                                 gst_message_unref(msg);
3745                         }
3746                 } while (!player->msg_posted && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
3747                 /* clean */
3748                 gst_object_unref(bus);
3749                 g_timer_stop(timer);
3750                 g_timer_destroy(timer);
3751
3752                 return ret;
3753         }
3754
3755         if (MMPLAYER_USE_DECODEBIN(player)) {
3756                 if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_decoded_cb) &&
3757                         (!player->pipeline->videobin) && (!player->pipeline->audiobin))
3758                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
3759         }
3760
3761         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
3762
3763 EXIT:
3764         /* generate dot file before returning error */
3765         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-pause");
3766
3767         MMPLAYER_FLEAVE();
3768
3769         return ret;
3770 }
3771
3772 int
3773 _mmplayer_gst_resume(mmplayer_t *player, gboolean async)
3774 {
3775         int ret = MM_ERROR_NONE;
3776         gint timeout = 0;
3777
3778         MMPLAYER_FENTER();
3779
3780         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline,
3781                 MM_ERROR_PLAYER_NOT_INITIALIZED);
3782
3783         LOGD("current state before doing transition");
3784         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
3785         MMPLAYER_PRINT_STATE(player);
3786
3787         if (async)
3788                 LOGD("do async state transition to PLAYING");
3789
3790         /* set pipeline state to PLAYING */
3791         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
3792
3793         ret = _mmplayer_gst_set_state(player,
3794                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout);
3795         if (ret != MM_ERROR_NONE) {
3796                 LOGE("failed to set state to PLAYING");
3797                 goto EXIT;
3798         }
3799
3800         if (!async)
3801                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
3802
3803 EXIT:
3804         /* generate dot file */
3805         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
3806
3807         MMPLAYER_FLEAVE();
3808
3809         return ret;
3810 }
3811
3812 /* sending event to one of sinkelements */
3813 gboolean
3814 _mmplayer_gst_send_event_to_sink(mmplayer_t *player, GstEvent *event)
3815 {
3816         GstEvent *event2 = NULL;
3817         GList *sinks = NULL;
3818         gboolean res = FALSE;
3819         MMPLAYER_FENTER();
3820
3821         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3822         MMPLAYER_RETURN_VAL_IF_FAIL(event, FALSE);
3823
3824         /* While adding subtitles in live feeds seek is getting called.
3825            Adding defensive check in framework layer.*/
3826         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
3827                 if (MMPLAYER_IS_LIVE_STREAMING(player)) {
3828                         LOGE("Should not send seek event during live playback");
3829                         return TRUE;
3830                 }
3831         }
3832
3833         if (player->play_subtitle)
3834                 event2 = gst_event_copy((const GstEvent *)event);
3835
3836         sinks = player->sink_elements;
3837         while (sinks) {
3838                 GstElement *sink = GST_ELEMENT_CAST(sinks->data);
3839
3840                 if (GST_IS_ELEMENT(sink)) {
3841                         /* keep ref to the event */
3842                         gst_event_ref(event);
3843
3844                         if ((res = gst_element_send_event(sink, event))) {
3845                                 LOGD("sending event[%s] to sink element [%s] success!",
3846                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
3847
3848                                 /* rtsp case, async_done is not called after seek during pause state */
3849                                 if (MMPLAYER_IS_RTSP_STREAMING(player)) {
3850                                         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
3851                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
3852                                                         LOGD("RTSP seek completed, after pause state..");
3853                                                         player->seek_state = MMPLAYER_SEEK_NONE;
3854                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
3855                                                 }
3856
3857                                         }
3858                                 }
3859
3860                                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
3861                                         sinks = g_list_next(sinks);
3862                                         continue;
3863                                 } else {
3864                                         break;
3865                                 }
3866                         }
3867
3868                         LOGD("sending event[%s] to sink element [%s] failed. try with next one.",
3869                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
3870                 }
3871
3872                 sinks = g_list_next(sinks);
3873         }
3874
3875         /* Note : Textbin is not linked to the video or audio bin.
3876          * It needs to send the event to the text sink separately.
3877          */
3878         if (player->play_subtitle && player->pipeline) {
3879                 GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
3880
3881                 if (GST_IS_ELEMENT(text_sink)) {
3882                         /* keep ref to the event */
3883                         gst_event_ref(event2);
3884
3885                         if ((res = gst_element_send_event(text_sink, event2)))
3886                                 LOGD("sending event[%s] to subtitle sink element [%s] success!",
3887                                                 GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
3888                         else
3889                                 LOGE("sending event[%s] to subtitle sink element [%s] failed!",
3890                                                 GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
3891
3892                         gst_event_unref(event2);
3893                 }
3894         }
3895
3896         gst_event_unref(event);
3897
3898         MMPLAYER_FLEAVE();
3899
3900         return res;
3901 }
3902
3903 gboolean
3904 _mmplayer_gst_seek(mmplayer_t *player, GstElement *element, gdouble rate,
3905                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
3906                         gint64 cur, GstSeekType stop_type, gint64 stop)
3907 {
3908         GstEvent *event = NULL;
3909         gboolean result = FALSE;
3910
3911         MMPLAYER_FENTER();
3912
3913         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3914
3915         if (player->pipeline && player->pipeline->textbin)
3916                 __mmplayer_drop_subtitle(player, FALSE);
3917
3918         event = gst_event_new_seek(rate, format, flags, cur_type,
3919                 cur, stop_type, stop);
3920
3921         result = _mmplayer_gst_send_event_to_sink(player, event);
3922
3923         MMPLAYER_FLEAVE();
3924
3925         return result;
3926 }
3927
3928 int
3929 _mmplayer_gst_set_position(mmplayer_t *player, gint64 position, gboolean internal_called)
3930 {
3931         int ret = MM_ERROR_NONE;
3932         gint64 pos_nsec = 0;
3933         gboolean accurate = FALSE;
3934         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
3935
3936         MMPLAYER_FENTER();
3937         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3938         MMPLAYER_RETURN_VAL_IF_FAIL(!MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP);
3939
3940         if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING)
3941                 && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
3942                 goto PENDING;
3943
3944         ret = __mmplayer_gst_check_position(player, position);
3945         if (ret != MM_ERROR_NONE) {
3946                 LOGW("result of check position info 0x%X", ret);
3947                 return (ret == MM_ERROR_PLAYER_NO_OP) ? MM_ERROR_NONE : ret;
3948         }
3949
3950         if (!__mmplayer_gst_check_seekable(player))
3951                 return MM_ERROR_PLAYER_NO_OP;
3952
3953         LOGD("seeking to(%"G_GINT64_FORMAT") nsec, rate: %f, dur: %"G_GINT64_FORMAT" nsec",
3954                                 position, player->playback_rate, player->duration);
3955
3956         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
3957            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
3958            This causes problem is position calculation during normal pause resume scenarios also.
3959            Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
3960         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
3961                 (_mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
3962                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
3963                         LOGW("getting current position failed in seek");
3964
3965                 player->last_position = pos_nsec;
3966                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
3967         }
3968
3969         if (player->seek_state != MMPLAYER_SEEK_NONE) {
3970                 LOGD("not completed seek");
3971                 return MM_ERROR_PLAYER_DOING_SEEK;
3972         }
3973
3974         if (!internal_called)
3975                 player->seek_state = MMPLAYER_SEEK_IN_PROGRESS;
3976
3977         /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
3978                 that's why set position through property. */
3979         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
3980                 (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
3981                 (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
3982                 (!player->videodec_linked) && (!player->audiodec_linked)) {
3983
3984                 LOGD("[%s] set position =%"GST_TIME_FORMAT,
3985                                 GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(position));
3986
3987                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", position, NULL);
3988                 player->seek_state = MMPLAYER_SEEK_NONE;
3989                 MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
3990         } else {
3991                 mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurate);
3992                 if (accurate)
3993                         seek_flags |= GST_SEEK_FLAG_ACCURATE;
3994                 else
3995                         seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
3996
3997                 if (!_mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
3998                                                 GST_FORMAT_TIME, seek_flags,
3999                                                 GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
4000                         LOGE("failed to set position");
4001                         goto SEEK_ERROR;
4002                 }
4003         }
4004
4005         /* NOTE : store last seeking point to overcome some bad operation
4006          *     (returning zero when getting current position) of some elements
4007          */
4008         player->last_position = position;
4009
4010         /* MSL should guarantee playback rate when seek is selected during trick play of fast forward. */
4011         if (player->playback_rate > 1.0)
4012                 _mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
4013
4014         if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
4015                 LOGD("buffering should be reset after seeking");
4016                 player->streamer->buffering_state = MM_PLAYER_BUFFERING_ABORT;
4017                 player->streamer->buffering_percent = 100; /* after seeking, new per can be non-zero. */
4018         }
4019
4020         MMPLAYER_FLEAVE();
4021         return MM_ERROR_NONE;
4022
4023 PENDING:
4024         player->pending_seek.is_pending = true;
4025         player->pending_seek.pos = position;
4026
4027         LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%"G_GINT64_FORMAT")",
4028                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)),
4029                 MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)),
4030                 player->pending_seek.pos);
4031
4032         return MM_ERROR_NONE;
4033
4034 SEEK_ERROR:
4035         player->seek_state = MMPLAYER_SEEK_NONE;
4036         return MM_ERROR_PLAYER_SEEK;
4037 }
4038
4039 int
4040 _mmplayer_gst_get_position(mmplayer_t *player, gint64 *position)
4041 {
4042 #define TRICKPLAY_OFFSET GST_MSECOND
4043
4044         mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
4045         gint64 pos_nsec = 0;
4046         gboolean ret = TRUE;
4047
4048         MMPLAYER_RETURN_VAL_IF_FAIL(player && position && player->pipeline && player->pipeline->mainbin,
4049                 MM_ERROR_PLAYER_NOT_INITIALIZED);
4050
4051         current_state = MMPLAYER_CURRENT_STATE(player);
4052
4053         /* NOTE : query position except paused state to overcome some bad operation
4054          * please refer to below comments in details
4055          */
4056         if (current_state != MM_PLAYER_STATE_PAUSED)
4057                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec);
4058
4059         /* NOTE : get last point to overcome some bad operation of some elements
4060          *(returning zero when getting current position in paused state
4061          * and when failed to get position during seeking
4062          */
4063         if ((current_state == MM_PLAYER_STATE_PAUSED) || (!ret)) {
4064                 LOGD("pos_nsec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
4065
4066                 if (player->playback_rate < 0.0)
4067                         pos_nsec = player->last_position - TRICKPLAY_OFFSET;
4068                 else
4069                         pos_nsec = player->last_position;
4070
4071                 if (!ret)
4072                         pos_nsec = player->last_position;
4073                 else
4074                         player->last_position = pos_nsec;
4075
4076                 LOGD("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_nsec));
4077
4078         } else {
4079                 if (player->duration > 0 && pos_nsec > player->duration)
4080                         pos_nsec = player->duration;
4081
4082                 player->last_position = pos_nsec;
4083         }
4084
4085         *position = pos_nsec;
4086
4087         return MM_ERROR_NONE;
4088 }
4089
4090 int
4091 _mmplayer_gst_get_buffer_position(mmplayer_t *player, int *start_pos, int *end_pos)
4092 {
4093 #define STREAMING_IS_FINISHED   0
4094 #define BUFFERING_MAX_PER       100
4095 #define DEFAULT_PER_VALUE       -1
4096 #define CHECK_PERCENT_VALUE(a, min, max)(((a) > (min)) ? (((a) < (max)) ? (a) : (max)) : (min))
4097
4098         mmplayer_gst_element_t *mainbin = NULL;
4099         gint start_per = DEFAULT_PER_VALUE, end_per = DEFAULT_PER_VALUE;
4100         gint64 buffered_total = 0;
4101         gint64 position = 0;
4102         gint buffered_sec = -1;
4103         GstBufferingMode mode = GST_BUFFERING_STREAM;
4104         gint64 content_size_time = player->duration;
4105         guint64 content_size_bytes = player->http_content_size;
4106
4107         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
4108                                                 player->pipeline &&
4109                                                 player->pipeline->mainbin,
4110                                                 MM_ERROR_PLAYER_NOT_INITIALIZED);
4111
4112         MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && end_pos, MM_ERROR_INVALID_ARGUMENT);
4113
4114         *start_pos = 0;
4115         *end_pos = 0;
4116
4117         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
4118                 /* and rtsp is not ready yet. */
4119                 LOGW("it's only used for http streaming case");
4120                 return MM_ERROR_PLAYER_NO_OP;
4121         }
4122
4123         if (content_size_time <= 0 || content_size_bytes <= 0) {
4124                 LOGW("there is no content size");
4125                 return MM_ERROR_NONE;
4126         }
4127
4128         if (_mmplayer_gst_get_position(player, &position) != MM_ERROR_NONE) {
4129                 LOGW("fail to get current position");
4130                 return MM_ERROR_NONE;
4131         }
4132
4133         LOGD("pos %"G_GINT64_FORMAT" msec, dur %d sec, len %"G_GUINT64_FORMAT" bytes",
4134                 GST_TIME_AS_MSECONDS(position), (guint)GST_TIME_AS_SECONDS(content_size_time), content_size_bytes);
4135
4136         mainbin = player->pipeline->mainbin;
4137         start_per = (gint)(floor(100 * (gdouble)position / (gdouble)content_size_time));
4138
4139         if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
4140                 GstQuery *query = NULL;
4141                 gint byte_in_rate = 0, byte_out_rate = 0;
4142                 gint64 estimated_total = 0;
4143
4144                 query = gst_query_new_buffering(GST_FORMAT_BYTES);
4145                 if (!query || !gst_element_query(mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query)) {
4146                         LOGW("fail to get buffering query from queue2");
4147                         if (query)
4148                                 gst_query_unref(query);
4149                         return MM_ERROR_NONE;
4150                 }
4151
4152                 gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, NULL);
4153                 LOGD("mode %d, in_rate %d, out_rate %d", mode, byte_in_rate, byte_out_rate);
4154
4155                 if (mode == GST_BUFFERING_STREAM) {
4156                         /* using only queue in case of push mode(ts / mp3) */
4157                         if (gst_element_query_position(mainbin[MMPLAYER_M_SRC].gst,
4158                                 GST_FORMAT_BYTES, &buffered_total)) {
4159                                 LOGD("buffered_total %"G_GINT64_FORMAT, buffered_total);
4160                                 end_per = 100 * buffered_total / content_size_bytes;
4161                         }
4162                 } else {
4163                         /* GST_BUFFERING_TIMESHIFT or GST_BUFFERING_DOWNLOAD */
4164                         guint idx = 0;
4165                         guint num_of_ranges = 0;
4166                         gint64 start_byte = 0, stop_byte = 0;
4167
4168                         gst_query_parse_buffering_range(query, NULL, NULL, NULL, &estimated_total);
4169                         if (estimated_total != STREAMING_IS_FINISHED) {
4170                                 /* buffered size info from queue2 */
4171                                 num_of_ranges = gst_query_get_n_buffering_ranges(query);
4172                                 for (idx = 0; idx < num_of_ranges; idx++) {
4173                                         gst_query_parse_nth_buffering_range(query, idx, &start_byte, &stop_byte);
4174                                         LOGD("range %d, %"G_GINT64_FORMAT" ~ %"G_GUINT64_FORMAT, idx, start_byte, stop_byte);
4175
4176                                         buffered_total += (stop_byte - start_byte);
4177                                 }
4178                         } else {
4179                                 end_per = BUFFERING_MAX_PER;
4180                         }
4181                 }
4182                 gst_query_unref(query);
4183         }
4184
4185         if (end_per == DEFAULT_PER_VALUE) {
4186                 guint dur_sec = (guint)(content_size_time/GST_SECOND);
4187                 if (dur_sec > 0) {
4188                         guint avg_byterate = (guint)(content_size_bytes / dur_sec);
4189
4190                         /* buffered size info from multiqueue */
4191                         if (mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
4192                                 guint curr_size_bytes = 0;
4193                                 g_object_get(G_OBJECT(mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst),
4194                                         "curr-size-bytes", &curr_size_bytes, NULL);
4195                                 LOGD("curr_size_bytes of multiqueue = %d", curr_size_bytes);
4196                                 buffered_total += (gint64)curr_size_bytes;
4197                         }
4198
4199                         if (avg_byterate > 0)
4200                                 buffered_sec = (gint)(ceil((gdouble)buffered_total / (gdouble)avg_byterate));
4201                         else if (player->total_maximum_bitrate > 0)
4202                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total) / (gdouble)player->total_maximum_bitrate));
4203                         else if (player->total_bitrate > 0)
4204                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total) / (gdouble)player->total_bitrate));
4205
4206                         if (buffered_sec >= 0)
4207                                 end_per = start_per + (gint)(ceil)(100 * (gdouble)buffered_sec / (gdouble)dur_sec);
4208                 }
4209         }
4210
4211         *start_pos = CHECK_PERCENT_VALUE(start_per, 0, 100);
4212         *end_pos = CHECK_PERCENT_VALUE(end_per, *start_pos, 100);
4213
4214         LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %d~%d",
4215                 buffered_total, buffered_sec, *start_pos, *end_pos);
4216
4217         return MM_ERROR_NONE;
4218 }
4219
4220 GstElement *
4221 _mmplayer_gst_create_source(mmplayer_t *player)
4222 {
4223         GstElement *element = NULL;
4224
4225         MMPLAYER_FENTER();
4226         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
4227                                 player->pipeline->mainbin, NULL);
4228
4229         /* setup source for gapless play */
4230         switch (player->profile.uri_type) {
4231         /* file source */
4232         case MM_PLAYER_URI_TYPE_FILE:
4233                 element = __mmplayer_gst_make_file_src(player);
4234                 break;
4235         case MM_PLAYER_URI_TYPE_URL_HTTP:
4236                 element = __mmplayer_gst_make_http_src(player);
4237                 break;
4238         default:
4239                 LOGE("not support uri type %d", player->profile.uri_type);
4240                 break;
4241         }
4242
4243         if (!element) {
4244                 LOGE("failed to create source element");
4245                 return NULL;
4246         }
4247
4248         MMPLAYER_FLEAVE();
4249         return element;
4250 }
4251
4252 int
4253 _mmplayer_gst_build_es_pipeline(mmplayer_t *player)
4254 {
4255         MMPLAYER_FENTER();
4256         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
4257                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
4258
4259         SECURE_LOGD("uri : %s", player->profile.uri);
4260
4261         mm_player_set_attribute((MMHandleType)player, NULL, "profile_prepare_async", TRUE, NULL);
4262
4263         if ((player->v_stream_caps) &&
4264                 !(__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_VIDEO, player->v_stream_caps)))
4265                 return MM_ERROR_PLAYER_INTERNAL;
4266
4267         if ((player->a_stream_caps) &&
4268                 !(__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_AUDIO, player->a_stream_caps)))
4269                 return MM_ERROR_PLAYER_INTERNAL;
4270
4271         if ((player->s_stream_caps) &&
4272                 !(__mmplayer_gst_create_es_path(player, MM_PLAYER_STREAM_TYPE_TEXT, player->s_stream_caps)))
4273                 return MM_ERROR_PLAYER_INTERNAL;
4274
4275         MMPLAYER_FLEAVE();
4276         return MM_ERROR_NONE;
4277 }
4278
4279 int
4280 _mmplayer_gst_build_pipeline_with_src(mmplayer_t *player)
4281 {
4282         mmplayer_gst_element_t *mainbin = NULL;
4283         GstElement *autoplug_elem = NULL;
4284
4285         MMPLAYER_FENTER();
4286         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
4287                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
4288
4289         mainbin = player->pipeline->mainbin;
4290
4291         LOGD("uri type %d", player->profile.uri_type);
4292
4293         if ((player->profile.uri_type == MM_PLAYER_URI_TYPE_FILE) &&
4294                 (!_mmplayer_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD]))) {
4295                 return MM_ERROR_PLAYER_INTERNAL;
4296         }
4297
4298         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM) {
4299                 g_strlcpy(player->profile.uri, "appsrc://", MM_MAX_URL_LEN);
4300         }
4301
4302         autoplug_elem = __mmplayer_gst_make_uridecodebin(player);
4303         if (!autoplug_elem) {
4304                 LOGE("failed to create uridecodebin3 element");
4305                 goto ERROR;
4306         }
4307
4308         LOGD("autoplug elem is created %s", GST_ELEMENT_NAME(autoplug_elem));
4309         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
4310         mainbin[MMPLAYER_M_AUTOPLUG].gst = autoplug_elem;
4311
4312         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), autoplug_elem)) {
4313                 LOGE("failed to add uridecodebin to pipeline");
4314                 goto ERROR;
4315         }
4316
4317         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
4318         mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
4319         mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
4320
4321         if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
4322                 LOGE("failed to create fakesink");
4323                 goto ERROR;
4324         }
4325         GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
4326
4327         /* take ownership of fakesink. we are reusing it */
4328         gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
4329
4330         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
4331                 LOGE("failed to add fakesink to bin");
4332                 gst_object_unref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
4333                 goto ERROR;
4334         }
4335
4336         MMPLAYER_FLEAVE();
4337         return MM_ERROR_NONE;
4338
4339 ERROR:
4340
4341         if (mainbin[MMPLAYER_M_AUTOPLUG].gst)
4342                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_AUTOPLUG].gst));
4343
4344         if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
4345                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
4346
4347         mainbin[MMPLAYER_M_AUTOPLUG].gst = NULL;
4348         mainbin[MMPLAYER_M_SRC_FAKESINK].gst = NULL;
4349
4350         return MM_ERROR_PLAYER_INTERNAL;
4351 }
4352
4353 int
4354 _mmplayer_gst_build_pipeline(mmplayer_t *player)
4355 {
4356         mmplayer_gst_element_t *mainbin = NULL;
4357         GstElement *src_elem = NULL;
4358         GstElement *autoplug_elem = NULL;
4359         GList *element_bucket = NULL;
4360         main_element_id_e autoplug_elem_id = MMPLAYER_M_NUM;
4361
4362         MMPLAYER_FENTER();
4363         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
4364                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
4365
4366         LOGD("uri type %d", player->profile.uri_type);
4367
4368         /* create source element */
4369         switch (player->profile.uri_type) {
4370         case MM_PLAYER_URI_TYPE_URL_RTSP:
4371                 src_elem = __mmplayer_gst_make_rtsp_src(player);
4372                 break;
4373         case MM_PLAYER_URI_TYPE_URL_HTTP:
4374                 src_elem = __mmplayer_gst_make_http_src(player);
4375                 break;
4376         case MM_PLAYER_URI_TYPE_FILE:
4377                 src_elem = __mmplayer_gst_make_file_src(player);
4378                 break;
4379         case MM_PLAYER_URI_TYPE_SS:
4380                 {
4381                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
4382                         src_elem = gst_element_factory_make("souphttpsrc", "http streaming source");
4383                         if (!src_elem) {
4384                                 LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
4385                                 break;
4386                         }
4387
4388                         if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
4389                                 LOGD("get timeout from ini");
4390                                 http_timeout = player->ini.http_timeout;
4391                         }
4392
4393                         /* setting property to streaming source */
4394                         g_object_set(G_OBJECT(src_elem), "location", player->profile.uri, "timeout", http_timeout, NULL);
4395                 }
4396                 break;
4397         case MM_PLAYER_URI_TYPE_MEM:
4398                 {
4399                         GstAppStreamType stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
4400
4401                         src_elem = gst_element_factory_make("appsrc", "mem-source");
4402                         if (!src_elem) {
4403                                 LOGE("failed to create appsrc element");
4404                                 break;
4405                         }
4406
4407                         g_object_set(src_elem, "stream-type", stream_type,
4408                                 "size", (gint64)player->profile.input_mem.len, "blocksize", 20480, NULL);
4409
4410                         _mmplayer_add_signal_connection(player, G_OBJECT(src_elem), MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
4411                                                                                         G_CALLBACK(__mmplayer_gst_appsrc_seek_data_mem), (gpointer)&player->profile.input_mem);
4412                         _mmplayer_add_signal_connection(player, G_OBJECT(src_elem), MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
4413                                                                                         G_CALLBACK(__mmplayer_gst_appsrc_feed_data_mem), (gpointer)&player->profile.input_mem);
4414                 }
4415                 break;
4416         default:
4417                 LOGE("not support uri type");
4418                 break;
4419         }
4420
4421         if (!src_elem) {
4422                 LOGE("failed to create source element");
4423                 return MM_ERROR_PLAYER_INTERNAL;
4424         }
4425
4426         mainbin = player->pipeline->mainbin;
4427
4428         /* take source element */
4429         LOGD("source elem is created %s", GST_ELEMENT_NAME(src_elem));
4430
4431         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
4432         mainbin[MMPLAYER_M_SRC].gst = src_elem;
4433         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
4434
4435         /* create next element for auto-plugging */
4436         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
4437                 autoplug_elem_id = MMPLAYER_M_TYPEFIND;
4438                 autoplug_elem = gst_element_factory_make("typefind", "typefinder");
4439                 if (!autoplug_elem) {
4440                         LOGE("failed to create typefind element");
4441                         goto ERROR;
4442                 }
4443
4444                 _mmplayer_add_signal_connection(player, G_OBJECT(autoplug_elem), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
4445                                                                         G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
4446         } else if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
4447                 autoplug_elem_id = MMPLAYER_M_AUTOPLUG;
4448                 autoplug_elem = _mmplayer_gst_make_decodebin(player);
4449                 if (!autoplug_elem) {
4450                         LOGE("failed to create decodebin");
4451                         goto ERROR;
4452                 }
4453
4454                 /* default size of mq in decodebin is 2M
4455                  * but it can cause blocking issue during seeking depends on content. */
4456                 g_object_set(G_OBJECT(autoplug_elem), "max-size-bytes", (5 * 1024 * 1024), NULL);
4457         }
4458
4459         if (autoplug_elem) {
4460                 LOGD("autoplug elem is created %s", GST_ELEMENT_NAME(autoplug_elem));
4461                 mainbin[autoplug_elem_id].id = autoplug_elem_id;
4462                 mainbin[autoplug_elem_id].gst = autoplug_elem;
4463
4464                 element_bucket = g_list_append(element_bucket, &mainbin[autoplug_elem_id]);
4465         }
4466
4467         /* add elements to pipeline */
4468         if (!_mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
4469                 LOGE("failed to add elements to pipeline");
4470                 goto ERROR;
4471         }
4472
4473         /* linking elements in the bucket by added order. */
4474         if (_mmplayer_gst_element_link_bucket(element_bucket) == -1) {
4475                 LOGE("failed to link some elements");
4476                 goto ERROR;
4477         }
4478
4479         /* FIXME: need to check whether this is required or not. */
4480         if (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_RTSP_STREAMING(player) ||
4481                 (player->audio_extract_opt & MM_PLAYER_AUDIO_EXTRACT_DEINTERLEAVE)) {
4482                 /* create fakesink element for keeping the pipeline state PAUSED. if needed */
4483                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
4484                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
4485
4486                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
4487                         LOGE("failed to create fakesink");
4488                         goto ERROR;
4489                 }
4490                 GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
4491
4492                 /* take ownership of fakesink. we are reusing it */
4493                 gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
4494
4495                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
4496                         LOGE("failed to add fakesink to bin");
4497                         gst_object_unref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
4498                         goto ERROR;
4499                 }
4500         }
4501
4502         g_list_free(element_bucket);
4503
4504         MMPLAYER_FLEAVE();
4505         return MM_ERROR_NONE;
4506
4507 ERROR:
4508         g_list_free(element_bucket);
4509
4510         if (mainbin[MMPLAYER_M_SRC].gst)
4511                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC].gst));
4512
4513         if (mainbin[autoplug_elem_id].gst)
4514                 gst_object_unref(GST_OBJECT(mainbin[autoplug_elem_id].gst));
4515
4516         if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
4517                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
4518
4519         mainbin[MMPLAYER_M_SRC].gst = NULL;
4520         mainbin[autoplug_elem_id].gst = NULL;
4521         mainbin[MMPLAYER_M_SRC_FAKESINK].gst = NULL;
4522
4523         return MM_ERROR_PLAYER_INTERNAL;
4524 }
4525
4526 int
4527 _mmplayer_gst_add_bus_watch(mmplayer_t *player)
4528 {
4529         GstBus  *bus = NULL;
4530         mmplayer_gst_element_t *mainbin = NULL;
4531
4532         MMPLAYER_FENTER();
4533         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
4534                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
4535
4536         mainbin = player->pipeline->mainbin;
4537
4538         /* connect bus callback */
4539         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
4540         if (!bus) {
4541                 LOGE("cannot get bus from pipeline");
4542                 return MM_ERROR_PLAYER_INTERNAL;
4543         }
4544
4545         player->bus_watcher = gst_bus_add_watch_full(bus, G_PRIORITY_DEFAULT,
4546                                                         (GstBusFunc)__mmplayer_gst_msg_push, player,
4547                                                         (GDestroyNotify)_mmplayer_watcher_removed_notify);
4548         if (player->bus_watcher == 0) {
4549                 LOGE("failed to add bus watch");
4550                 return MM_ERROR_PLAYER_INTERNAL;
4551         }
4552
4553         g_mutex_init(&player->bus_watcher_mutex);
4554         g_cond_init(&player->bus_watcher_cond);
4555
4556         player->context.thread_default = g_main_context_get_thread_default();
4557         if (player->context.thread_default == NULL) {
4558                 player->context.thread_default = g_main_context_default();
4559                 LOGD("thread-default context is the global default context");
4560         }
4561         LOGW("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
4562
4563         /* set sync handler to get tag synchronously */
4564         gst_bus_set_sync_handler(bus, __mmplayer_gst_bus_sync_callback, player, NULL);
4565         gst_object_unref(GST_OBJECT(bus));
4566
4567         /* create gst bus_msb_cb thread */
4568         g_mutex_init(&player->bus_msg_thread_mutex);
4569         g_cond_init(&player->bus_msg_thread_cond);
4570         player->bus_msg_thread_exit = FALSE;
4571         player->bus_msg_thread =
4572                 g_thread_try_new("gst_bus_msg_thread", __mmplayer_gst_bus_msg_thread, (gpointer)player, NULL);
4573         if (!player->bus_msg_thread) {
4574                 LOGE("failed to create gst BUS msg thread");
4575                 g_mutex_clear(&player->bus_msg_thread_mutex);
4576                 g_cond_clear(&player->bus_msg_thread_cond);
4577                 return MM_ERROR_PLAYER_INTERNAL;
4578         }
4579
4580         MMPLAYER_FLEAVE();
4581         return MM_ERROR_NONE;
4582 }
4583
4584 void
4585 _mmplayer_activate_next_source(mmplayer_t *player, GstState target)
4586 {
4587         int ret = MM_ERROR_NONE;
4588         mmplayer_gst_element_t *mainbin = NULL;
4589         MMMessageParamType msg_param = {0,};
4590         GstElement *element = NULL;
4591         MMHandleType attrs = 0;
4592         char *uri = NULL;
4593         main_element_id_e elem_idx = MMPLAYER_M_NUM;
4594
4595         MMPLAYER_FENTER();
4596
4597         if (!player || !player->pipeline || !player->pipeline->mainbin) {
4598                 LOGE("player is not initialized");
4599                 goto ERROR;
4600         }
4601
4602         mainbin = player->pipeline->mainbin;
4603         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
4604
4605         attrs = MMPLAYER_GET_ATTRS(player);
4606         if (!attrs) {
4607                 LOGE("fail to get attributes");
4608                 goto ERROR;
4609         }
4610
4611         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
4612
4613         if (_mmplayer_parse_profile((const char *)uri, NULL, &player->profile) != MM_ERROR_NONE) {
4614                 LOGE("failed to parse profile");
4615                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
4616                 goto ERROR;
4617         }
4618
4619         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
4620                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
4621                 LOGE("dash or hls is not supportable");
4622                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
4623                 goto ERROR;
4624         }
4625
4626         if (!MMPLAYER_USE_DECODEBIN(player)) {
4627                 ret = _mmplayer_gst_build_pipeline_with_src(player);
4628                 if (ret != MM_ERROR_NONE)
4629                         goto ERROR;
4630
4631                 if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
4632                         LOGE("Failed to change state of uridecodebin3 element");
4633                         goto ERROR;
4634                 }
4635                 goto DONE;
4636         }
4637
4638         element = _mmplayer_gst_create_source(player);
4639         if (!element) {
4640                 LOGE("no source element was created");
4641                 goto ERROR;
4642         }
4643
4644         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
4645                 LOGE("failed to add source element to pipeline");
4646                 gst_object_unref(GST_OBJECT(element));
4647                 element = NULL;
4648                 goto ERROR;
4649         }
4650
4651         /* take source element */
4652         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
4653         mainbin[MMPLAYER_M_SRC].gst = element;
4654
4655         element = NULL;
4656
4657         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
4658                 if (player->streamer == NULL) {
4659                         player->streamer = _mm_player_streaming_create();
4660                         _mm_player_streaming_initialize(player->streamer, TRUE);
4661                 }
4662
4663                 elem_idx = MMPLAYER_M_TYPEFIND;
4664                 element = gst_element_factory_make("typefind", "typefinder");
4665                 _mmplayer_add_signal_connection(player, G_OBJECT(element),
4666                         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(_mmplayer_typefind_have_type), (gpointer)player);
4667         } else {
4668                 elem_idx = MMPLAYER_M_AUTOPLUG;
4669                 element = _mmplayer_gst_make_decodebin(player);
4670         }
4671
4672         /* check autoplug element is OK */
4673         if (!element) {
4674                 LOGE("can not create element(%d)", elem_idx);
4675                 goto ERROR;
4676         }
4677
4678         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
4679                 LOGE("failed to add %s to pipeline", GST_ELEMENT_NAME(element));
4680                 gst_object_unref(GST_OBJECT(element));
4681                 element = NULL;
4682                 goto ERROR;
4683         }
4684
4685         mainbin[elem_idx].id = elem_idx;
4686         mainbin[elem_idx].gst = element;
4687
4688         if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elem_idx].gst) == FALSE) {
4689                 LOGE("Failed to link src - autoplug(or typefind)");
4690                 goto ERROR;
4691         }
4692
4693         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
4694                 if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {  // ????
4695                         LOGE("Failed to change state of src element");
4696                         goto ERROR;
4697                 }
4698         } else {
4699                 if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
4700                         LOGE("Failed to change state of decodebin");
4701                         goto ERROR;
4702                 }
4703         }
4704
4705         if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
4706                 LOGE("Failed to change state of src element");
4707                 goto ERROR;
4708         }
4709
4710 DONE:
4711         player->gapless.stream_changed = TRUE;
4712         player->gapless.running = TRUE;
4713         MMPLAYER_FLEAVE();
4714         return;
4715
4716 ERROR:
4717         if (player) {
4718                 _mmplayer_set_reconfigure_state(player, FALSE);
4719                 if (!player->msg_posted) {
4720                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
4721                         player->msg_posted = TRUE;
4722                 }
4723         }
4724         return;
4725 }