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