8e1edccd18d7668acbb6db18941722c5defc2e0d
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.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 <glib.h>
29 #include <gst/gst.h>
30 #include <gst/video/videooverlay.h>
31 #include <gst/audio/gstaudiobasesink.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <string.h>
35 #include <sys/time.h>
36 #include <stdlib.h>
37 #include <dlog.h>
38
39 #include <mm_error.h>
40 #include <mm_attrs.h>
41 #include <mm_attrs_private.h>
42
43 #include "mm_player_priv.h"
44 #include "mm_player_ini.h"
45 #include "mm_player_attrs.h"
46 #include "mm_player_capture.h"
47 #include "mm_player_utils.h"
48 #include "mm_player_tracks.h"
49 #include "mm_player_360.h"
50 #include "mm_player_gst.h"
51
52 #include <system_info.h>
53 #include <sound_manager.h>
54 #include <gst/allocators/gsttizenmemory.h>
55 #include <tbm_surface_internal.h>
56
57 /*===========================================================================================
58 |                                                                                                                                                                                       |
59 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
60 |                                                                                                                                                                                       |
61 ========================================================================================== */
62
63 /*---------------------------------------------------------------------------
64 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
65 ---------------------------------------------------------------------------*/
66
67 /*---------------------------------------------------------------------------
68 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
69 ---------------------------------------------------------------------------*/
70
71 /*---------------------------------------------------------------------------
72 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
73 ---------------------------------------------------------------------------*/
74
75 /*---------------------------------------------------------------------------
76 |    LOCAL #defines:                                                                                                            |
77 ---------------------------------------------------------------------------*/
78 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
79 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
80
81 #define MM_VOLUME_FACTOR_DEFAULT                1.0
82 #define MM_VOLUME_FACTOR_MIN                    0
83 #define MM_VOLUME_FACTOR_MAX                    1.0
84
85 /* Don't need to sleep for sound fadeout
86  * fadeout related fucntion will be deleted(Deprecated)
87  */
88 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  0
89
90 #define DEFAULT_PLAYBACK_RATE                   1.0
91 #define DEFAULT_NUM_OF_V_OUT_BUFFER             3
92
93 #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) \
94         (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && \
95         (player->ini.http_use_file_buffer) && \
96         (player->http_file_buffering_path) && \
97         (strlen(player->http_file_buffering_path) > 0))
98
99 #define PLAYER_DISPLAY_MODE_DST_ROI             5
100
101 #define ADAPTIVE_VARIANT_DEFAULT_VALUE -1 /* auto */
102
103 /* For PD mode */
104 #define PLAYER_PD_EXT_MAX_SIZE_BYTE             1024 * 1024 * 3
105 #define PLAYER_PD_STATE_CHANGE_TIME             20 /* sec */
106
107 #define PLAYER_SPHERICAL_DEFAULT_YAW   0  /* sync from video360 plugin */
108 #define PLAYER_SPHERICAL_DEFAULT_PITCH 0
109 #define PLAYER_SPHERICAL_DEFAULT_H_FOV 120
110 #define PLAYER_SPHERICAL_DEFAULT_V_FOV 67
111
112 #define SPATIAL_AUDIO_CAPS             "audio/x-raw,format=S16LE,channels=4"
113 #define FEATURE_NAME_SPHERICAL_VIDEO   "http://tizen.org/feature/multimedia.player.spherical_video"
114
115 #define FAKE_SINK_MAX_LATENESS         G_GINT64_CONSTANT(20000000) /* set 20ms as waylandsink */
116
117 /*---------------------------------------------------------------------------
118 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
119 ---------------------------------------------------------------------------*/
120
121 /*---------------------------------------------------------------------------
122 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
123 ---------------------------------------------------------------------------*/
124
125 /*---------------------------------------------------------------------------
126 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
127 ---------------------------------------------------------------------------*/
128
129 /*---------------------------------------------------------------------------
130 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
131 ---------------------------------------------------------------------------*/
132 static sound_stream_info_h stream_info;
133
134 /*---------------------------------------------------------------------------
135 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
136 ---------------------------------------------------------------------------*/
137 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
138 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
139 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
140 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
141 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
142 static int              __mmplayer_gst_create_text_sink_bin(mm_player_t* player);
143
144 static GstPadProbeReturn        __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
145 static void             __mmplayer_gst_decode_no_more_pads(GstElement* elem, gpointer data);
146 static void             __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gpointer data);
147 static void             __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad, GstCaps *caps, gpointer data);
148 static gboolean __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad, GstCaps * caps,  gpointer data);
149 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
150 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
151 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
152 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
153 static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps);
154 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
155
156 static gboolean __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
157 static void             __mmplayer_release_misc(mm_player_t* player);
158 static void             __mmplayer_release_misc_post(mm_player_t* player);
159 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
160 static void __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
161 static void __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
162 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
163 static int __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index);
164
165 static gboolean __mmplayer_check_subtitle(mm_player_t* player);
166 static int              __mmplayer_handle_missed_plugin(mm_player_t* player);
167 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
168 static void             __mmplayer_add_sink(mm_player_t* player, GstElement* sink);
169 static void             __mmplayer_del_sink(mm_player_t* player, GstElement* sink);
170 static void             __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
171 static gpointer __mmplayer_gapless_play_thread(gpointer data);
172 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
173 static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data);
174 static void __mmplayer_release_dump_list(GList *dump_list);
175 static int              __mmplayer_gst_realize(mm_player_t* player);
176 static int              __mmplayer_gst_unrealize(mm_player_t* player);
177 static int              __mmplayer_gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
178 static int              __mmplayer_gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
179
180 /* util */
181 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
182 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
183 static int __mmplayer_start_streaming_ext(mm_player_t *player);
184 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
185 static gboolean __mmplayer_verify_gapless_play_path(mm_player_t *player);
186 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
187 static void __mmplayer_check_pipeline(mm_player_t* player);
188 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
189 static void __mmplayer_deactivate_old_path(mm_player_t *player);
190 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
191 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
192 static void             __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data);
193 static void             __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer);
194 static void             __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type);
195 static int              __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, void *user_data);
196 static gboolean __mmplayer_update_duration_attrs(mm_player_t *player, MMHandleType attrs);
197 static gboolean __mmplayer_update_audio_attrs(mm_player_t *player, MMHandleType attrs);
198 static gboolean __mmplayer_update_video_attrs(mm_player_t *player, MMHandleType attrs);
199 static gboolean __mmplayer_update_bitrate_attrs(mm_player_t *player, MMHandleType attrs);
200
201 static void __mmplayer_copy_uri_and_set_type(MMPlayerParseProfile* data, const char *uri, int uri_type);
202 static int __mmplayer_set_mem_uri(MMPlayerParseProfile* data, char *path, void *param);
203 static int __mmplayer_set_file_uri(MMPlayerParseProfile* data, const char *uri);
204
205 static MMPlayerVideoStreamDataType* __mmplayer_create_stream_from_pad(GstPad *pad);
206 static void __mmplayer_zerocopy_set_stride_elevation_bo(MMPlayerVideoStreamDataType *stream, GstMemory *mem);
207 static gboolean __mmplayer_swcodec_set_stride_elevation(MMPlayerVideoStreamDataType *stream);
208 static gboolean __mmplayer_swcodec_set_bo(mm_player_t *player, MMPlayerVideoStreamDataType *stream, GstMemory *mem);
209 /*===========================================================================================
210 |                                                                                                                                                                                       |
211 |  FUNCTION DEFINITIONS                                                                                                                                         |
212 |                                                                                                                                                                                       |
213 ========================================================================================== */
214
215 #if 0 //debug
216 static void
217 print_tag(const GstTagList * list, const gchar * tag, gpointer unused)
218 {
219         gint i, count;
220
221         count = gst_tag_list_get_tag_size(list, tag);
222
223         LOGD("count = %d", count);
224
225         for (i = 0; i < count; i++) {
226                 gchar *str;
227
228                 if (gst_tag_get_type(tag) == G_TYPE_STRING) {
229                         if (!gst_tag_list_get_string_index(list, tag, i, &str))
230                                 g_assert_not_reached();
231                 } else
232                         str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
233
234                 if (i == 0)
235                         g_print("  %15s: %s\n", gst_tag_get_nick(tag), str);
236                 else
237                         g_print("                 : %s\n", str);
238
239                 g_free(str);
240         }
241 }
242 #endif
243
244 /* This function should be called after the pipeline goes PAUSED or higher
245 state. */
246 gboolean
247 __mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag)
248 {
249         static gboolean has_duration = FALSE;
250         static gboolean has_video_attrs = FALSE;
251         static gboolean has_audio_attrs = FALSE;
252         static gboolean has_bitrate = FALSE;
253         gboolean missing_only = FALSE;
254         gboolean all = FALSE;
255         MMHandleType attrs = 0;
256
257         MMPLAYER_FENTER();
258
259         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
260
261         /* check player state here */
262         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
263                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) {
264                 /* give warning now only */
265                 LOGW("be careful. content attributes may not available in this state ");
266         }
267
268         /* get content attribute first */
269         attrs = MMPLAYER_GET_ATTRS(player);
270         if (!attrs) {
271                 LOGE("cannot get content attribute");
272                 return FALSE;
273         }
274
275         /* get update flag */
276
277         if (flag & ATTR_MISSING_ONLY) {
278                 missing_only = TRUE;
279                 LOGD("updating missed attr only");
280         }
281
282         if (flag & ATTR_ALL) {
283                 all = TRUE;
284                 has_duration = FALSE;
285                 has_video_attrs = FALSE;
286                 has_audio_attrs = FALSE;
287                 has_bitrate = FALSE;
288
289                 LOGD("updating all attrs");
290         }
291
292         if (missing_only && all) {
293                 LOGW("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
294                 missing_only = FALSE;
295         }
296
297         if ((flag & ATTR_DURATION) || (!has_duration && missing_only) || all)
298                 has_duration = __mmplayer_update_duration_attrs(player, attrs);
299
300         if ((flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all)
301                 has_audio_attrs = __mmplayer_update_audio_attrs(player, attrs);
302
303         if ((flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all)
304                 has_video_attrs = __mmplayer_update_video_attrs(player, attrs);
305
306         if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all)
307                 has_bitrate = __mmplayer_update_bitrate_attrs(player, attrs);
308
309         /* validate all */
310         if (mmf_attrs_commit(attrs)) {
311                 LOGE("failed to update attributes\n");
312                 return FALSE;
313         }
314
315         MMPLAYER_FLEAVE();
316
317         return TRUE;
318 }
319
320 MMStreamingType __mmplayer_get_stream_service_type(mm_player_t* player)
321 {
322         MMStreamingType streaming_type = STREAMING_SERVICE_NONE;
323
324         MMPLAYER_FENTER();
325
326         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
327                         player->pipeline &&
328                         player->pipeline->mainbin &&
329                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
330                         STREAMING_SERVICE_NONE);
331
332         /* streaming service type if streaming */
333         if (!MMPLAYER_IS_STREAMING(player))
334                 return STREAMING_SERVICE_NONE;
335
336         streaming_type = (player->duration == 0) ?
337                 STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
338
339         switch (streaming_type) {
340         case STREAMING_SERVICE_LIVE:
341                 LOGD("it's live streaming");
342                 break;
343         case STREAMING_SERVICE_VOD:
344                 LOGD("it's vod streaming");
345                 break;
346         default:
347                 LOGE("should not get here");
348                 break;
349         }
350
351         MMPLAYER_FLEAVE();
352
353         return streaming_type;
354 }
355
356
357 /* this function sets the player state and also report
358  * it to applicaton by calling callback function
359  */
360 void
361 __mmplayer_set_state(mm_player_t* player, int state)
362 {
363         MMMessageParamType msg = {0, };
364         gboolean post_bos = FALSE;
365
366         MMPLAYER_RETURN_IF_FAIL(player);
367
368         if (MMPLAYER_CURRENT_STATE(player) == state) {
369                 LOGW("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
370                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
371                 return;
372         }
373
374         /* update player states */
375         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
376         MMPLAYER_CURRENT_STATE(player) = state;
377
378         if (MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player))
379                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
380
381         /* print state */
382         MMPLAYER_PRINT_STATE(player);
383
384         switch (MMPLAYER_CURRENT_STATE(player)) {
385         case MM_PLAYER_STATE_NULL:
386         case MM_PLAYER_STATE_READY:
387                 break;
388
389         case MM_PLAYER_STATE_PAUSED:
390                 {
391                         if (!player->sent_bos) {
392                                 /* rtsp case, get content attrs by GstMessage */
393                                 if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
394                                         /* it's first time to update all content attrs. */
395                                         __mmplayer_update_content_attrs(player, ATTR_ALL);
396                                 }
397                         }
398                 }
399                 break;
400
401         case MM_PLAYER_STATE_PLAYING:
402                 {
403                         /* try to get content metadata */
404                         if (!player->sent_bos) {
405                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
406                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
407                                  * legacy mmfw-player api */
408                                 __mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
409                         }
410
411                         if ((player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME)) {
412                                 if (!player->sent_bos)
413                                         __mmplayer_handle_missed_plugin(player);
414                         }
415
416                         if (player->resumed_by_rewind && player->playback_rate < 0.0) {
417                                 /* initialize because auto resume is done well. */
418                                 player->resumed_by_rewind = FALSE;
419                                 player->playback_rate = 1.0;
420                         }
421
422                         if (!player->sent_bos) {
423                                 /* check audio codec field is set or not
424                                  * we can get it from typefinder or codec's caps.
425                                  */
426                                 gchar *audio_codec = NULL;
427                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
428
429                                 /* The codec format can't be sent for audio only case like amr, mid etc.
430                                  * Because, parser don't make related TAG.
431                                  * So, if it's not set yet, fill it with found data.
432                                  */
433                                 if (!audio_codec) {
434                                         if (g_strrstr(player->type, "audio/midi"))
435                                                 audio_codec = g_strdup("MIDI");
436                                         else if (g_strrstr(player->type, "audio/x-amr"))
437                                                 audio_codec = g_strdup("AMR");
438                                         else if (g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion= (int)1"))
439                                                 audio_codec = g_strdup("AAC");
440                                         else
441                                                 audio_codec = g_strdup("unknown");
442                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
443
444                                         MMPLAYER_FREEIF(audio_codec);
445                                         if (mmf_attrs_commit(player->attrs))
446                                                 LOGE("failed to update attributes\n");
447
448                                         LOGD("set audio codec type with caps\n");
449                                 }
450
451                                 post_bos = TRUE;
452                         }
453                 }
454                 break;
455
456         case MM_PLAYER_STATE_NONE:
457         default:
458                 LOGW("invalid target state, there is nothing to do.\n");
459                 break;
460         }
461
462
463         /* post message to application */
464         if (MMPLAYER_TARGET_STATE(player) == state) {
465                 /* fill the message with state of player */
466                 msg.union_type = MM_MSG_UNION_STATE;
467                 msg.state.previous = MMPLAYER_PREV_STATE(player);
468                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
469
470                 LOGD("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
471
472                 /* state changed by resource callback */
473                 if (player->interrupted_by_resource) {
474                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
475                 } else { /* state changed by usecase */
476                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_CHANGED, &msg);
477                 }
478         } else {
479                 LOGD("intermediate state, do nothing.\n");
480                 MMPLAYER_PRINT_STATE(player);
481                 return;
482         }
483
484         if (post_bos) {
485                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BEGIN_OF_STREAM, NULL);
486                 player->sent_bos = TRUE;
487         }
488
489         return;
490 }
491
492 int
493 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
494 {
495         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
496         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
497
498         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
499
500         //LOGD("incomming command : %d \n", command);
501
502         current_state = MMPLAYER_CURRENT_STATE(player);
503         pending_state = MMPLAYER_PENDING_STATE(player);
504
505         MMPLAYER_PRINT_STATE(player);
506
507         switch (command) {
508         case MMPLAYER_COMMAND_CREATE:
509         {
510                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
511
512                 if (current_state == MM_PLAYER_STATE_NULL ||
513                         current_state == MM_PLAYER_STATE_READY ||
514                         current_state == MM_PLAYER_STATE_PAUSED ||
515                         current_state == MM_PLAYER_STATE_PLAYING)
516                         goto NO_OP;
517         }
518         break;
519
520         case MMPLAYER_COMMAND_DESTROY:
521         {
522                 /* destroy can called anytime */
523
524                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
525         }
526         break;
527
528         case MMPLAYER_COMMAND_REALIZE:
529         {
530                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
531
532                 if (pending_state != MM_PLAYER_STATE_NONE) {
533                         goto INVALID_STATE;
534                 } else {
535                         /* need ready state to realize */
536                         if (current_state == MM_PLAYER_STATE_READY)
537                                 goto NO_OP;
538
539                         if (current_state != MM_PLAYER_STATE_NULL)
540                                 goto INVALID_STATE;
541                 }
542         }
543         break;
544
545         case MMPLAYER_COMMAND_UNREALIZE:
546         {
547                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
548
549                 if (current_state == MM_PLAYER_STATE_NULL)
550                         goto NO_OP;
551         }
552         break;
553
554         case MMPLAYER_COMMAND_START:
555         {
556                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
557
558                 if (pending_state == MM_PLAYER_STATE_NONE) {
559                         if (current_state == MM_PLAYER_STATE_PLAYING)
560                                 goto NO_OP;
561                         else if (current_state  != MM_PLAYER_STATE_READY &&
562                                 current_state != MM_PLAYER_STATE_PAUSED)
563                                 goto INVALID_STATE;
564                 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
565                         goto ALREADY_GOING;
566                 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
567                         LOGD("player is going to paused state, just change the pending state as playing");
568                 } else
569                         goto INVALID_STATE;
570         }
571         break;
572
573         case MMPLAYER_COMMAND_STOP:
574         {
575                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
576
577                 if (current_state == MM_PLAYER_STATE_READY)
578                         goto NO_OP;
579
580                 /* need playing/paused state to stop */
581                 if (current_state != MM_PLAYER_STATE_PLAYING &&
582                          current_state != MM_PLAYER_STATE_PAUSED)
583                         goto INVALID_STATE;
584         }
585         break;
586
587         case MMPLAYER_COMMAND_PAUSE:
588         {
589                 if (MMPLAYER_IS_LIVE_STREAMING(player))
590                         goto NO_OP;
591
592                 if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS)
593                         goto NOT_COMPLETED_SEEK;
594
595                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
596
597                 if (pending_state == MM_PLAYER_STATE_NONE) {
598                         if (current_state == MM_PLAYER_STATE_PAUSED)
599                                 goto NO_OP;
600                         else if (current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY) // support loading state of broswer
601                                 goto INVALID_STATE;
602                 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
603                         goto ALREADY_GOING;
604                 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
605                         if (current_state == MM_PLAYER_STATE_PAUSED)
606                                 LOGD("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
607                         else
608                                 goto INVALID_STATE;
609                 }
610         }
611         break;
612
613         case MMPLAYER_COMMAND_RESUME:
614         {
615                 if (player->seek_state == MMPLAYER_SEEK_IN_PROGRESS)
616                         goto NOT_COMPLETED_SEEK;
617
618                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
619
620                 if (pending_state == MM_PLAYER_STATE_NONE) {
621                         if (current_state == MM_PLAYER_STATE_PLAYING)
622                                 goto NO_OP;
623                         else if (current_state != MM_PLAYER_STATE_PAUSED)
624                                 goto INVALID_STATE;
625                 } else if (pending_state == MM_PLAYER_STATE_PLAYING) {
626                         goto ALREADY_GOING;
627                 } else if (pending_state == MM_PLAYER_STATE_PAUSED) {
628                         LOGD("player is going to paused state, just change the pending state as playing");
629                 } else
630                         goto INVALID_STATE;
631         }
632                 break;
633
634         default:
635                 break;
636         }
637         player->cmd = command;
638
639         return MM_ERROR_NONE;
640
641 INVALID_STATE:
642         LOGW("since player is in wrong state(%s). it's not able to apply the command(%d)",
643                 MMPLAYER_STATE_GET_NAME(current_state), command);
644         return MM_ERROR_PLAYER_INVALID_STATE;
645
646 NOT_COMPLETED_SEEK:
647         LOGW("not completed seek");
648         return MM_ERROR_PLAYER_DOING_SEEK;
649
650 NO_OP:
651         LOGW("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
652         return MM_ERROR_PLAYER_NO_OP;
653
654 ALREADY_GOING:
655         LOGW("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
656         return MM_ERROR_PLAYER_NO_OP;
657 }
658
659 static gpointer __mmplayer_gapless_play_thread(gpointer data)
660 {
661         mm_player_t* player = (mm_player_t*) data;
662         MMPlayerGstElement *mainbin = NULL;
663
664         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
665
666         MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(player);
667         while (!player->gapless_play_thread_exit) {
668                 LOGD("gapless play thread started. waiting for signal.\n");
669                 MMPLAYER_GAPLESS_PLAY_THREAD_WAIT(player);
670
671                 LOGD("reconfigure pipeline for gapless play.\n");
672
673                 if (player->gapless_play_thread_exit) {
674                         if (player->gapless.reconfigure) {
675                                 player->gapless.reconfigure = false;
676                                 MMPLAYER_PLAYBACK_UNLOCK(player);
677                         }
678                         LOGD("exiting gapless play thread\n");
679                         break;
680                 }
681
682                 mainbin = player->pipeline->mainbin;
683
684                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
685                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
686                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
687                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
688                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
689
690                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
691         }
692         MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
693
694         return NULL;
695 }
696
697 static void
698 __mmplayer_remove_g_source_from_context(GMainContext *context, guint source_id)
699 {
700         GSource *source = NULL;
701
702         MMPLAYER_FENTER();
703
704         source = g_main_context_find_source_by_id(context, source_id);
705
706         if (source != NULL) {
707                 LOGW("context: %p, source id: %d, source: %p", context, source_id, source);
708                 g_source_destroy(source);
709         }
710
711         MMPLAYER_FLEAVE();
712 }
713
714 void __mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
715 {
716         mm_player_t* player = (mm_player_t*)hplayer;
717         GstMessage *msg = NULL;
718         GQueue *queue = NULL;
719
720         MMPLAYER_FENTER();
721         MMPLAYER_RETURN_IF_FAIL(player);
722
723         /* disconnecting bus watch */
724         if (player->bus_watcher)
725                 __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
726         player->bus_watcher = 0;
727
728         /* destroy the gst bus msg thread */
729         if (player->bus_msg_thread) {
730                 MMPLAYER_BUS_MSG_THREAD_LOCK(player);
731                 player->bus_msg_thread_exit = TRUE;
732                 MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
733                 MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
734
735                 LOGD("gst bus msg thread exit.");
736                 g_thread_join(player->bus_msg_thread); /* can request cmd lock */
737                 player->bus_msg_thread = NULL;
738
739                 g_mutex_clear(&player->bus_msg_thread_mutex);
740                 g_cond_clear(&player->bus_msg_thread_cond);
741         }
742
743         g_mutex_lock(&player->bus_msg_q_lock);
744         queue = player->bus_msg_q;
745         while (!g_queue_is_empty(queue)) {
746                 msg = (GstMessage *)g_queue_pop_head(queue);
747                 if (!msg) {
748                         LOGW("msg is null");
749                         continue;
750                 }
751                 LOGW("remove remained %s msg", GST_MESSAGE_TYPE_NAME(msg));
752                 gst_message_unref(msg);
753         }
754         g_mutex_unlock(&player->bus_msg_q_lock);
755
756         MMPLAYER_FLEAVE();
757 }
758
759 gboolean
760 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink)
761 {
762         GstElement* parent = NULL;
763
764         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
765
766         /* if we have no fakesink. this meas we are using decodebin which doesn'
767         t need to add extra fakesink */
768         MMPLAYER_RETURN_VAL_IF_FAIL(fakesink, TRUE);
769
770         /* lock */
771         MMPLAYER_FSINK_LOCK(player);
772
773         if (!fakesink->gst)
774                 goto ERROR;
775
776         /* get parent of fakesink */
777         parent = (GstElement*)gst_object_get_parent((GstObject*)fakesink->gst);
778         if (!parent) {
779                 LOGD("fakesink already removed\n");
780                 goto ERROR;
781         }
782
783         gst_element_set_locked_state(fakesink->gst, TRUE);
784
785         /* setting the state to NULL never returns async
786          * so no need to wait for completion of state transiton
787          */
788         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL))
789                 LOGE("fakesink state change failure!\n");
790                 /* FIXIT : should I return here? or try to proceed to next? */
791                 /* return FALSE; */
792
793         /* remove fakesink from it's parent */
794         if (!gst_bin_remove(GST_BIN(parent), fakesink->gst)) {
795                 LOGE("failed to remove fakesink\n");
796
797                 gst_object_unref(parent);
798
799                 goto ERROR;
800         }
801
802         gst_object_unref(parent);
803
804         LOGD("state-holder removed\n");
805
806         gst_element_set_locked_state(fakesink->gst, FALSE);
807
808         MMPLAYER_FSINK_UNLOCK(player);
809         return TRUE;
810
811 ERROR:
812         if (fakesink->gst)
813                 gst_element_set_locked_state(fakesink->gst, FALSE);
814
815         MMPLAYER_FSINK_UNLOCK(player);
816         return FALSE;
817 }
818
819 static GstPadProbeReturn
820 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
821 {
822         LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
823         return GST_PAD_PROBE_OK;
824 }
825
826 static void
827 __mmplayer_gst_selector_update_start_time(mm_player_t* player, MMPlayerTrackType stream_type)
828 {
829         gint64 stop_running_time = 0;
830         gint64 position_running_time = 0;
831         gint64 position = 0;
832         gint idx = 0;
833
834         for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) {
835                 if ((player->gapless.update_segment[idx] == TRUE) ||
836                         !(player->selector[idx].event_probe_id)) {
837                         /* LOGW("[%d] skip", idx); */
838                         continue;
839                 }
840
841                 if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) {
842                         stop_running_time =
843                                 gst_segment_to_running_time(&player->gapless.segment[idx],
844                                                 GST_FORMAT_TIME, player->gapless.segment[idx].stop);
845                 } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) {
846                         stop_running_time =
847                                 gst_segment_to_running_time(&player->gapless.segment[idx],
848                                                 GST_FORMAT_TIME, player->gapless.segment[idx].duration);
849                 } else {
850                         LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration));
851                         stop_running_time =
852                                 gst_segment_to_running_time(&player->gapless.segment[idx],
853                                                 GST_FORMAT_TIME, player->duration);
854                 }
855
856                 position_running_time =
857                         gst_segment_to_running_time(&player->gapless.segment[idx],
858                         GST_FORMAT_TIME, player->gapless.segment[idx].position);
859
860                 LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %"
861                         GST_TIME_FORMAT" , %" GST_TIME_FORMAT,
862                         idx,
863                         GST_TIME_ARGS(stop_running_time),
864                         GST_TIME_ARGS(position_running_time),
865                         GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx],
866                         GST_FORMAT_TIME, player->gapless.segment[idx].start)));
867
868                 position_running_time = MAX(position_running_time, stop_running_time);
869                 position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx],
870                                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].start);
871                 position_running_time = MAX(0, position_running_time);
872                 position = MAX(position, position_running_time);
873         }
874
875         if (position != 0) {
876                 LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
877                         stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]),
878                         GST_TIME_ARGS(player->gapless.start_time[stream_type] + position));
879
880                 player->gapless.start_time[stream_type] += position;
881         }
882
883         return;
884 }
885
886 static GstPadProbeReturn
887 __mmplayer_gst_selector_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer data)
888 {
889         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
890         GstEvent *event = GST_PAD_PROBE_INFO_DATA(info);
891         mm_player_t *player = (mm_player_t*)data;
892         GstCaps *caps = NULL;
893         GstStructure *str = NULL;
894         const gchar *name = NULL;
895         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
896         gboolean caps_ret = TRUE;
897
898         if (GST_EVENT_IS_DOWNSTREAM(event) &&
899             GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START &&
900             GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP &&
901             GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT &&
902             GST_EVENT_TYPE(event) != GST_EVENT_EOS) {
903                 return ret;
904         } else if (GST_EVENT_IS_UPSTREAM(event) &&
905                            GST_EVENT_TYPE(event) != GST_EVENT_QOS) {
906                 return ret;
907         }
908
909         MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
910         if (!caps_ret)
911                 goto ERROR;
912
913         if (strstr(name, "audio")) {
914                 stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
915         } else if (strstr(name, "video")) {
916                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
917         } else {
918                 /* text track is not supportable */
919                 LOGE("invalid name %s", name);
920                 goto ERROR;
921         }
922
923         switch (GST_EVENT_TYPE(event)) {
924         case GST_EVENT_EOS:
925                 {
926                         /* in case of gapless, drop eos event not to send it to sink */
927                         if (player->gapless.reconfigure && !player->msg_posted) {
928                                 LOGD("[%d] %s:%s EOS received but will be drop", stream_type, GST_DEBUG_PAD_NAME(pad));
929                                 ret = GST_PAD_PROBE_DROP;
930                         }
931                         break;
932                 }
933         case GST_EVENT_STREAM_START:
934                 {
935                         __mmplayer_gst_selector_update_start_time(player, stream_type);
936                         break;
937                 }
938         case GST_EVENT_FLUSH_STOP:
939                 {
940                         LOGD("[%d] GST_EVENT_FLUSH_STOP", stream_type);
941                         gst_segment_init(&player->gapless.segment[stream_type], GST_FORMAT_UNDEFINED);
942                         player->gapless.start_time[stream_type] = 0;
943                         break;
944                 }
945         case GST_EVENT_SEGMENT:
946                 {
947                         GstSegment segment;
948                         GstEvent *tmpev;
949
950                         LOGD("[%d] GST_EVENT_SEGMENT", stream_type);
951                         gst_event_copy_segment(event, &segment);
952
953                         if (segment.format != GST_FORMAT_TIME)
954                                 break;
955
956                         LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT
957                                  ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
958                                  ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT,
959                                 GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset),
960                                 GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop),
961                                 GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration));
962
963                         /* keep the all the segment ev to cover the seeking */
964                         gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]);
965                         player->gapless.update_segment[stream_type] = TRUE;
966
967                         if (!player->gapless.running)
968                                 break;
969
970                         player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type];
971
972                         LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base));
973
974                         tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]);
975                         gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event));
976                         gst_event_unref(event);
977                         GST_PAD_PROBE_INFO_DATA(info) = tmpev;
978
979                         break;
980                 }
981         case GST_EVENT_QOS:
982                 {
983                         gdouble proportion = 0.0;
984                         GstClockTimeDiff diff = 0;
985                         GstClockTime timestamp = 0;
986                         gint64 running_time_diff = -1;
987                         GstQOSType type = 0;
988                         GstEvent *tmpev = NULL;
989
990                         running_time_diff = player->gapless.segment[stream_type].base;
991
992                         if (running_time_diff <= 0) /* don't need to adjust */
993                                 break;
994
995                         gst_event_parse_qos(event, &type, &proportion, &diff, &timestamp);
996                         gst_event_unref(event);
997
998                         if (timestamp < running_time_diff) {
999                                 LOGW("QOS event from previous group");
1000                                 ret = GST_PAD_PROBE_DROP;
1001                                 break;
1002                         }
1003
1004                         LOGD("[%d] Adjusting QOS event: %" GST_TIME_FORMAT
1005                                  " - %" GST_TIME_FORMAT " = %" GST_TIME_FORMAT,
1006                                                 stream_type, GST_TIME_ARGS(timestamp),
1007                                                 GST_TIME_ARGS(running_time_diff),
1008                                                 GST_TIME_ARGS(timestamp - running_time_diff));
1009
1010                         timestamp -= running_time_diff;
1011
1012                         /* That case is invalid for QoS events */
1013                         if (diff < 0 && -diff > timestamp) {
1014                                 LOGW("QOS event from previous group");
1015                                 ret = GST_PAD_PROBE_DROP;
1016                                 break;
1017                         }
1018
1019                         tmpev = gst_event_new_qos(GST_QOS_TYPE_UNDERFLOW, proportion, diff, timestamp);
1020                         GST_PAD_PROBE_INFO_DATA(info) = tmpev;
1021
1022                         break;
1023                 }
1024         default:
1025                 break;
1026         }
1027
1028 ERROR:
1029         if (caps)
1030                 gst_caps_unref(caps);
1031         return ret;
1032 }
1033
1034 /* create fakesink for audio or video path witout audiobin or videobin */
1035 static void
1036 __mmplayer_gst_make_fakesink(mm_player_t *player, GstPad *pad, const gchar *name)
1037 {
1038         GstElement *pipeline = NULL;
1039         GstElement *fakesink = NULL;
1040         GstPad *sinkpad = NULL;
1041
1042         MMPLAYER_FENTER();
1043         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
1044
1045         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
1046
1047         /* fake sink */
1048         fakesink = gst_element_factory_make("fakesink", NULL);
1049         if (fakesink == NULL) {
1050                 LOGE("failed to create fakesink");
1051                 goto EXIT;
1052         }
1053
1054         /* store it as it's sink element */
1055         __mmplayer_add_sink(player, fakesink);
1056
1057         gst_bin_add(GST_BIN(pipeline), fakesink);
1058
1059         /* link */
1060         sinkpad = gst_element_get_static_pad(fakesink, "sink");
1061
1062         LOGD("pad link %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad));
1063
1064         if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
1065                 LOGE("failed to link fakesink");
1066                 gst_object_unref(GST_OBJECT(fakesink));
1067                 goto EXIT;
1068         }
1069
1070         if (strstr(name, "video")) {
1071                 player->video_fakesink = fakesink;
1072
1073                 if (player->v_stream_caps) {
1074                         gst_caps_unref(player->v_stream_caps);
1075                         player->v_stream_caps = NULL;
1076                 }
1077
1078                 if (player->ini.set_dump_element_flag)
1079                         __mmplayer_add_dump_buffer_probe(player, fakesink);
1080
1081
1082                 if (player->set_mode.media_packet_video_stream) { /* export video decoded frame */
1083                         g_object_set(G_OBJECT(fakesink), "signal-handoffs", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL);
1084
1085                         __mmplayer_add_signal_connection(player,
1086                                                                         G_OBJECT(fakesink),
1087                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
1088                                                                         "handoff",
1089                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
1090                                                                         (gpointer)player);
1091
1092                         __mmplayer_add_signal_connection(player,
1093                                                                         G_OBJECT(fakesink),
1094                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
1095                                                                         "preroll-handoff",
1096                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
1097                                                                         (gpointer)player);
1098                 }
1099         }
1100
1101         g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
1102         gst_element_set_state(fakesink, GST_STATE_PAUSED);
1103
1104 EXIT:
1105         if (sinkpad)
1106                 gst_object_unref(GST_OBJECT(sinkpad));
1107
1108         MMPLAYER_FLEAVE();
1109         return;
1110 }
1111
1112 static GstElement*
1113 __mmplayer_gst_make_selector(mm_player_t *player, enum MainElementID elem_idx, MMPlayerTrackType stream_type)
1114 {
1115         GstElement *pipeline = NULL;
1116         GstElement *selector = NULL;
1117         GstPad *srcpad = NULL;
1118
1119         MMPLAYER_FENTER();
1120         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL);
1121
1122         selector = gst_element_factory_make("input-selector", NULL);
1123         if (!selector) {
1124                 LOGE("failed to create input-selector");
1125                 return NULL;
1126         }
1127         g_object_set(selector, "sync-streams", TRUE, NULL);
1128
1129         player->pipeline->mainbin[elem_idx].id = elem_idx;
1130         player->pipeline->mainbin[elem_idx].gst = selector;
1131
1132         /* player->selector[stream_type].active_pad_index = DEFAULT_TRACK; */
1133
1134         srcpad = gst_element_get_static_pad(selector, "src");
1135
1136         LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
1137         player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
1138                 __mmplayer_gst_selector_blocked, NULL, NULL);
1139         player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
1140                 __mmplayer_gst_selector_event_probe, player, NULL);
1141
1142         gst_element_set_state(selector, GST_STATE_PAUSED);
1143
1144         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
1145         gst_bin_add(GST_BIN(pipeline), selector);
1146
1147         MMPLAYER_FLEAVE();
1148         return selector;
1149 }
1150
1151 void
1152 __mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
1153 {
1154         mm_player_t *player = NULL;
1155         GstElement *selector = NULL;
1156         GstCaps *caps = NULL;
1157         GstStructure *str = NULL;
1158         const gchar *name = NULL;
1159         GstPad *sinkpad = NULL;
1160         GstPad *srcpad = NULL;
1161         gboolean first_track = FALSE;
1162         gboolean caps_ret = TRUE;
1163
1164         enum MainElementID elem_idx = MMPLAYER_M_NUM;
1165         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
1166
1167         /* check handles */
1168         player = (mm_player_t*)data;
1169
1170         MMPLAYER_FENTER();
1171         MMPLAYER_RETURN_IF_FAIL(elem && pad);
1172         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
1173
1174         LOGD("pad-added signal handling");
1175
1176         /* get mimetype from caps */
1177         MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
1178         if (!caps_ret)
1179                 goto ERROR;
1180
1181         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
1182         /* LOGD("detected mimetype : %s", name); */
1183
1184         if (strstr(name, "video")) {
1185                 gint stype = 0;
1186                 gchar *caps_str = NULL;
1187
1188                 caps_str = gst_caps_to_string(caps);
1189                 if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
1190                         strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
1191                         player->set_mode.video_zc = TRUE;
1192
1193                 MMPLAYER_FREEIF(caps_str);
1194
1195                 mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
1196                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
1197
1198                 LOGD("surface type : %d", stype);
1199
1200                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
1201                         __mmplayer_gst_decode_callback(elem, pad, player);
1202                         goto DONE;
1203                 }
1204
1205                 if (stype == MM_DISPLAY_SURFACE_NULL) {
1206                         __mmplayer_gst_make_fakesink(player, pad, name);
1207                         goto DONE;
1208                 }
1209
1210                 LOGD("video selector is required");
1211                 elem_idx = MMPLAYER_M_V_INPUT_SELECTOR;
1212                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
1213         } else if (strstr(name, "audio")) {
1214                 gint samplerate = 0;
1215                 gint channels = 0;
1216
1217                 gst_structure_get_int(str, "rate", &samplerate);
1218                 gst_structure_get_int(str, "channels", &channels);
1219
1220                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
1221                         __mmplayer_gst_decode_callback(elem, pad, player);
1222                         goto DONE;
1223                 }
1224
1225                 if ((channels > 0 && samplerate == 0)) { /* exclude audio decoding */
1226                         __mmplayer_gst_make_fakesink(player, pad, name);
1227                         goto DONE;
1228                 }
1229
1230                 LOGD("audio selector is required");
1231                 elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
1232                 stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
1233
1234         } else if (strstr(name, "text")) {
1235                 LOGD("text selector is required");
1236                 elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
1237                 stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
1238         } else {
1239                 LOGE("invalid caps info");
1240                 goto ERROR;
1241         }
1242
1243         /* check selector and create it */
1244         if (!(selector = player->pipeline->mainbin[elem_idx].gst)) {
1245                 selector = __mmplayer_gst_make_selector(player, elem_idx, stream_type);
1246                 if (!selector)
1247                         goto ERROR;
1248                 first_track = TRUE;
1249         } else {
1250                 LOGD("input-selector is already created.");
1251         }
1252
1253         /* link */
1254         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
1255
1256         LOGD("pad link: %s:%s - %s:%s", GST_DEBUG_PAD_NAME(pad), GST_DEBUG_PAD_NAME(sinkpad));
1257
1258         if (gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
1259                 LOGE("failed to link selector");
1260                 gst_object_unref(GST_OBJECT(selector));
1261                 goto ERROR;
1262         }
1263
1264         if (first_track) {
1265                 LOGD("this track will be activated");
1266                 g_object_set(selector, "active-pad", sinkpad, NULL);
1267         }
1268
1269         __mmplayer_track_update_info(player, stream_type, sinkpad);
1270
1271 DONE:
1272 ERROR:
1273
1274         if (caps)
1275                 gst_caps_unref(caps);
1276
1277         if (sinkpad) {
1278                 gst_object_unref(GST_OBJECT(sinkpad));
1279                 sinkpad = NULL;
1280         }
1281
1282         if (srcpad) {
1283                 gst_object_unref(GST_OBJECT(srcpad));
1284                 srcpad = NULL;
1285         }
1286
1287         return;
1288 }
1289
1290 static gboolean __mmplayer_create_decode_path(mm_player_t* player, GstElement* selector, MMPlayerTrackType type)
1291 {
1292         GstPad* srcpad = NULL;
1293
1294         MMPLAYER_FENTER();
1295         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
1296
1297         LOGD("type %d", type);
1298
1299         if (!selector) {
1300                 LOGD("there is no %d track", type);
1301                 return TRUE;
1302         }
1303
1304         srcpad = gst_element_get_static_pad(selector, "src");
1305         if (!srcpad) {
1306                 LOGE("failed to get srcpad from selector");
1307                 return FALSE;
1308         }
1309
1310         LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(srcpad));
1311
1312         __mmplayer_gst_decode_callback(selector, srcpad, player);
1313
1314         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
1315         if (player->selector[type].block_id) {
1316                 gst_pad_remove_probe(srcpad, player->selector[type].block_id);
1317                 player->selector[type].block_id = 0;
1318         }
1319
1320         if (srcpad) {
1321                 gst_object_unref(GST_OBJECT(srcpad));
1322                 srcpad = NULL;
1323         }
1324
1325         MMPLAYER_FLEAVE();
1326         return TRUE;
1327 }
1328
1329 static void __mmplayer_set_decode_track_info(mm_player_t* player, MMPlayerTrackType type)
1330 {
1331         MMHandleType attrs = 0;
1332         gint active_index = 0;
1333         gchar *attr_name = NULL;
1334
1335         MMPLAYER_FENTER();
1336         MMPLAYER_RETURN_IF_FAIL(player);
1337
1338         LOGD("type %d", type);
1339
1340         /* change track to active pad */
1341         active_index = player->selector[type].active_pad_index;
1342         if ((active_index != DEFAULT_TRACK) &&
1343                 (__mmplayer_change_selector_pad(player, type, active_index) != MM_ERROR_NONE)) {
1344                 LOGW("failed to change %d type track to %d", type, active_index);
1345                 player->selector[type].active_pad_index = DEFAULT_TRACK;
1346         }
1347
1348         LOGD("Total num of tracks = %d", player->selector[type].total_track_num);
1349
1350         if (type == MM_PLAYER_TRACK_TYPE_AUDIO) {
1351                 attr_name = "content_audio_track_num";
1352         } else if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
1353                 attr_name = "content_text_track_num";
1354         } else {
1355                 LOGE("invalid type info %d", type);
1356                 return;
1357         }
1358
1359         attrs = MMPLAYER_GET_ATTRS(player);
1360         if (attrs) {
1361                 mm_attrs_set_int_by_name(attrs, attr_name, (gint)player->selector[type].total_track_num);
1362                 if (mmf_attrs_commit(attrs))
1363                         LOGW("failed to commit attrs.");
1364         } else {
1365                 LOGW("cannot get content attribute");
1366         }
1367
1368         MMPLAYER_FLEAVE();
1369         return;
1370 }
1371
1372 static gboolean __mmplayer_create_audio_decode_path(mm_player_t* player, GstElement* audio_selector)
1373 {
1374         MMPLAYER_FENTER();
1375         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
1376
1377         if (!audio_selector) {
1378                 LOGD("there is no audio track");
1379
1380                 /* in case the source is changed, output can be changed. */
1381                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
1382                         LOGD("remove previous audiobin if it exist");
1383
1384                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
1385                         __mmplayer_del_sink(player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
1386
1387                         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->audiobin, MMPLAYER_A_BIN);
1388                         MMPLAYER_FREEIF(player->pipeline->audiobin);
1389                 }
1390
1391                 if (player->num_dynamic_pad == 0) /* FIXME: num_dynamic_pad is only for rtsp? */
1392                         __mmplayer_pipeline_complete(NULL, player);
1393
1394                 return TRUE;
1395         }
1396
1397         /* apply the audio track information */
1398         __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_AUDIO);
1399
1400         /* create audio decode path */
1401         if (!__mmplayer_create_decode_path(player, audio_selector, MM_PLAYER_TRACK_TYPE_AUDIO)) {
1402                 LOGE("failed to create audio decode path");
1403                 return FALSE;
1404         }
1405
1406         MMPLAYER_FLEAVE();
1407         return TRUE;
1408 }
1409
1410 static gboolean __mmplayer_create_text_decode_path(mm_player_t* player, GstElement* text_selector)
1411 {
1412         MMPLAYER_FENTER();
1413         MMPLAYER_RETURN_VAL_IF_FAIL(player && text_selector, FALSE);
1414
1415         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
1416                 LOGD("text path is not supproted");
1417                 return TRUE;
1418         }
1419
1420         /* apply the text track information */
1421         __mmplayer_set_decode_track_info(player, MM_PLAYER_TRACK_TYPE_TEXT);
1422
1423         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
1424                 player->has_closed_caption = TRUE;
1425
1426         /* create text decode path */
1427         player->no_more_pad = TRUE;
1428
1429         if (!__mmplayer_create_decode_path(player, text_selector, MM_PLAYER_TRACK_TYPE_TEXT)) {
1430                 LOGE("failed to create text decode path");
1431                 return FALSE;
1432         }
1433
1434         MMPLAYER_FLEAVE();
1435         return TRUE;
1436 }
1437
1438 static gboolean
1439 __mmplayer_gst_set_queue2_buffering(mm_player_t *player)
1440 {
1441 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
1442
1443         gint init_buffering_time = 0;
1444         guint buffer_bytes = 0;
1445         gint64 dur_bytes = 0L;
1446
1447         MMPLAYER_FENTER();
1448         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
1449                 player->pipeline->mainbin && player->streamer, FALSE);
1450
1451         init_buffering_time = player->streamer->buffering_req.prebuffer_time;
1452         buffer_bytes = (guint)(init_buffering_time/1000) * ESTIMATED_BUFFER_UNIT;
1453
1454         buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
1455         LOGD("pre buffer time: %d ms, buffer size : %d", init_buffering_time, buffer_bytes);
1456
1457         init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
1458
1459         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
1460                 LOGE("fail to get duration.");
1461
1462         /* there is no mq, enable use-buffering on queue2 (ex) wav streaming
1463          * use file information was already set on Q2 when it was created. */
1464         __mm_player_streaming_set_queue2(player->streamer,
1465                                         player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
1466                                         TRUE,                                                           /* use_buffering */
1467                                         buffer_bytes,
1468                                         init_buffering_time,
1469                                         1.0,                                                            /* low percent */
1470                                         player->ini.http_buffering_limit,       /* high percent */
1471                                         MUXED_BUFFER_TYPE_MAX,                          /* use previous buffer type setting */
1472                                         NULL,
1473                                         ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
1474
1475         MMPLAYER_FLEAVE();
1476         return TRUE;
1477 }
1478
1479 static void
1480 __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
1481 {
1482         mm_player_t *player = NULL;
1483         GstElement *video_selector = NULL;
1484         GstElement *audio_selector = NULL;
1485         GstElement *text_selector = NULL;
1486
1487         MMPLAYER_FENTER();
1488         player = (mm_player_t*) data;
1489
1490         LOGD("no-more-pad signal handling");
1491
1492         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
1493                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
1494                 LOGW("player is shutting down");
1495                 goto EXIT;
1496         }
1497
1498         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
1499                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
1500                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
1501                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
1502                 if (!__mmplayer_gst_set_queue2_buffering(player)) {
1503                         LOGE("failed to set queue2 buffering");
1504                         goto EXIT;
1505                 }
1506         }
1507
1508         video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
1509         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
1510         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
1511
1512         /* create video path followed by video-select */
1513         if (video_selector && !audio_selector && !text_selector)
1514                 player->no_more_pad = TRUE;
1515
1516         if (!__mmplayer_create_decode_path(player, video_selector, MM_PLAYER_TRACK_TYPE_VIDEO))
1517                 goto EXIT;
1518
1519         /* create audio path followed by audio-select */
1520         if (audio_selector && !text_selector)
1521                 player->no_more_pad = TRUE;
1522
1523         if (!__mmplayer_create_audio_decode_path(player, audio_selector))
1524                 goto EXIT;
1525
1526
1527         /* create text path followed by text-select */
1528         __mmplayer_create_text_decode_path(player, text_selector);
1529
1530 EXIT:
1531         if (player->gapless.reconfigure) {
1532                 player->gapless.reconfigure = FALSE;
1533                 MMPLAYER_PLAYBACK_UNLOCK(player);
1534         }
1535
1536         MMPLAYER_FENTER();
1537 }
1538
1539 static void
1540 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data)
1541 {
1542         mm_player_t *player = NULL;
1543         MMHandleType attrs = 0;
1544         GstElement *pipeline = NULL;
1545         GstCaps *caps = NULL;
1546         gchar *caps_str = NULL;
1547         GstStructure *str = NULL;
1548         const gchar *name = NULL;
1549         GstPad *sinkpad = NULL;
1550         GstElement *sinkbin = NULL;
1551         gboolean reusing = FALSE;
1552         GstElement *text_selector = NULL;
1553         gboolean caps_ret = TRUE;
1554
1555         /* check handles */
1556         player = (mm_player_t*) data;
1557
1558         MMPLAYER_RETURN_IF_FAIL(elem && pad);
1559         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
1560
1561         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
1562
1563         attrs = MMPLAYER_GET_ATTRS(player);
1564         if (!attrs) {
1565                 LOGE("cannot get content attribute\n");
1566                 goto ERROR;
1567         }
1568
1569         MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
1570         if (!caps_ret)
1571                 goto ERROR;
1572
1573         caps_str = gst_caps_to_string(caps);
1574
1575         /* LOGD("detected mimetype : %s", name); */
1576         if (strstr(name, "audio")) {
1577                 if (player->pipeline->audiobin == NULL) {
1578                         if (__mmplayer_gst_create_audio_pipeline(player) != MM_ERROR_NONE) {
1579                                 LOGE("failed to create audiobin. continuing without audio\n");
1580                                 goto ERROR;
1581                         }
1582
1583                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
1584                         LOGD("creating audiosink bin success");
1585                 } else {
1586                         reusing = TRUE;
1587                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
1588                         LOGD("reusing audiobin\n");
1589                         __mmplayer_update_content_attrs(player, ATTR_AUDIO);
1590                 }
1591
1592                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
1593                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
1594
1595                 player->audiosink_linked  = 1;
1596
1597                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
1598                 if (!sinkpad) {
1599                         LOGE("failed to get pad from sinkbin\n");
1600                         goto ERROR;
1601                 }
1602         } else if (strstr(name, "video")) {
1603                 if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
1604                         strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
1605                         player->set_mode.video_zc = TRUE;
1606
1607                 if (player->pipeline->videobin == NULL) {
1608                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
1609                         /* get video surface type */
1610                         int surface_type = 0;
1611                         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
1612                         LOGD("display_surface_type (%d)", surface_type);
1613
1614                         if (surface_type == MM_DISPLAY_SURFACE_NULL) {
1615                                 LOGD("surface_type is NULL");
1616                                 goto ERROR;
1617                         }
1618
1619                         if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
1620                                 /* mark video overlay for acquire */
1621                                 if (player->video_overlay_resource == NULL) {
1622                                         if (mm_resource_manager_mark_for_acquire(player->resource_manager,
1623                                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
1624                                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
1625                                                         &player->video_overlay_resource)
1626                                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
1627                                                 LOGE("could not mark video_overlay resource for acquire\n");
1628                                                 goto ERROR;
1629                                         }
1630                                 }
1631                         }
1632
1633                         player->interrupted_by_resource = FALSE;
1634                         /* acquire resources for video overlay */
1635                         if (mm_resource_manager_commit(player->resource_manager) !=
1636                                         MM_RESOURCE_MANAGER_ERROR_NONE) {
1637                                 LOGE("could not acquire resources for video playing\n");
1638                                 goto ERROR;
1639                         }
1640
1641                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type)) {
1642                                 LOGE("failed to create videobin. continuing without video\n");
1643                                 goto ERROR;
1644                         }
1645
1646                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
1647                         LOGD("creating videosink bin success\n");
1648                 } else {
1649                         reusing = TRUE;
1650                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
1651                         LOGD("re-using videobin\n");
1652                         __mmplayer_update_content_attrs(player, ATTR_VIDEO);
1653                 }
1654
1655                 player->videosink_linked  = 1;
1656
1657                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
1658                 if (!sinkpad) {
1659                         LOGE("failed to get pad from sinkbin\n");
1660                         goto ERROR;
1661                 }
1662         } else if (strstr(name, "text")) {
1663                 if (player->pipeline->textbin == NULL) {
1664                         MMPlayerGstElement* mainbin = NULL;
1665
1666                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_sink_bin(player)) {
1667                                 LOGE("failed to create text sink bin. continuing without text\n");
1668                                 goto ERROR;
1669                         }
1670
1671                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
1672                         LOGD("creating textsink bin success\n");
1673
1674                         /* FIXIT : track number shouldn't be hardcoded */
1675                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
1676
1677                         player->textsink_linked  = 1;
1678                         LOGI("player->textsink_linked set to 1\n");
1679
1680                         sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "text_sink");
1681                         if (!sinkpad) {
1682                                 LOGE("failed to get pad from sinkbin\n");
1683                                 goto ERROR;
1684                         }
1685
1686                         mainbin = player->pipeline->mainbin;
1687
1688                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst) {
1689                                 /* input selector */
1690                                 text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
1691                                 if (!text_selector) {
1692                                         LOGE("failed to create subtitle input selector element\n");
1693                                         goto ERROR;
1694                                 }
1695                                 g_object_set(text_selector, "sync-streams", TRUE, NULL);
1696
1697                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
1698                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
1699
1700                                 /* warm up */
1701                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_READY)) {
1702                                         LOGE("failed to set state(READY) to sinkbin\n");
1703                                         goto ERROR;
1704                                 }
1705
1706                                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector)) {
1707                                         LOGW("failed to add subtitle input selector\n");
1708                                         goto ERROR;
1709                                 }
1710
1711                                 LOGD("created element input-selector");
1712
1713                         } else {
1714                                 LOGD("already having subtitle input selector");
1715                                 text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
1716                         }
1717                 } else {
1718                         if (!player->textsink_linked) {
1719                                 LOGD("re-using textbin\n");
1720
1721                                 reusing = TRUE;
1722                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
1723
1724                                 player->textsink_linked  = 1;
1725                                 LOGI("player->textsink_linked set to 1\n");
1726                         } else
1727                                 LOGD("ignoring internal subtutle since external subtitle is available");
1728                 }
1729         } else {
1730                 LOGW("unknown type of elementary stream!ignoring it...\n");
1731                 goto ERROR;
1732         }
1733
1734         if (sinkbin) {
1735                 if (!reusing) {
1736                         /* warm up */
1737                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_READY)) {
1738                                 LOGE("failed to set state(READY) to sinkbin\n");
1739                                 goto ERROR;
1740                         }
1741
1742                         /* Added for multi audio support to avoid adding audio bin again*/
1743                         /* add */
1744                         if (FALSE == gst_bin_add(GST_BIN(pipeline), sinkbin)) {
1745                                 LOGE("failed to add sinkbin to pipeline\n");
1746                                 goto ERROR;
1747                         }
1748                 }
1749
1750                 /* link */
1751                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
1752                         LOGE("failed to get pad from sinkbin\n");
1753                         goto ERROR;
1754                 }
1755
1756                 if (!reusing) {
1757                         /* run */
1758                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_PAUSED)) {
1759                                 LOGE("failed to set state(PAUSED) to sinkbin\n");
1760                                 goto ERROR;
1761                         }
1762
1763                         if (text_selector) {
1764                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_PAUSED)) {
1765                                         LOGE("failed to set state(PAUSED) to sinkbin\n");
1766                                         goto ERROR;
1767                                 }
1768                         }
1769                 }
1770
1771                 gst_object_unref(sinkpad);
1772                 sinkpad = NULL;
1773         }
1774
1775         LOGD("[handle: %p] linking sink bin success", player);
1776
1777         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
1778          * streaming task. if the task blocked, then buffer will not flow to the next element
1779          *(autoplugging element). so this is special hack for streaming. please try to remove it
1780          */
1781         /* dec stream count. we can remove fakesink if it's zero */
1782         if (player->num_dynamic_pad)
1783                 player->num_dynamic_pad--;
1784
1785         LOGD("no more pads: %d stream count dec : %d(num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
1786
1787         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
1788                 __mmplayer_pipeline_complete(NULL, player);
1789
1790 ERROR:
1791
1792         MMPLAYER_FREEIF(caps_str);
1793
1794         if (caps)
1795                 gst_caps_unref(caps);
1796
1797         if (sinkpad)
1798                 gst_object_unref(GST_OBJECT(sinkpad));
1799
1800         /* flusing out new attributes */
1801         if (mmf_attrs_commit(attrs))
1802                 LOGE("failed to comit attributes\n");
1803
1804         return;
1805 }
1806
1807 static gboolean
1808 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int display_angle, int orientation, int *value)
1809 {
1810         int required_angle = 0; /* Angle required for straight view */
1811         int rotation_angle = 0;
1812
1813         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
1814         MMPLAYER_RETURN_VAL_IF_FAIL(value, FALSE);
1815
1816         /* Counter clockwise */
1817         switch (orientation) {
1818         case 0:
1819                 required_angle = 0;
1820                 break;
1821         case 90:
1822                 required_angle = 270;
1823                 break;
1824         case 180:
1825                 required_angle = 180;
1826                 break;
1827         case 270:
1828                 required_angle = 90;
1829                 break;
1830         }
1831
1832         rotation_angle = display_angle + required_angle;
1833         if (rotation_angle >= 360)
1834                 rotation_angle -= 360;
1835
1836         /* chech if supported or not */
1837         if (rotation_angle % 90) {
1838                 LOGD("not supported rotation angle = %d", rotation_angle);
1839                 return FALSE;
1840         }
1841
1842         switch (rotation_angle) {
1843         case 0:
1844                 *value = MM_DISPLAY_ROTATION_NONE;
1845                 break;
1846         case 90:
1847                 *value = MM_DISPLAY_ROTATION_90;
1848                 break;
1849         case 180:
1850                 *value = MM_DISPLAY_ROTATION_180;
1851                 break;
1852         case 270:
1853                 *value = MM_DISPLAY_ROTATION_270;
1854                 break;
1855         }
1856
1857         LOGD("setting rotation property value : %d", value);
1858
1859         return TRUE;
1860 }
1861
1862 int
1863 __mmplayer_video_param_check_video_sink_bin(mm_player_t* player)
1864 {
1865         /* check video sinkbin is created */
1866         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
1867                 player->pipeline &&
1868                 player->pipeline->videobin &&
1869                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
1870                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
1871                 MM_ERROR_PLAYER_NOT_INITIALIZED);
1872
1873         return MM_ERROR_NONE;
1874 }
1875
1876 int
1877 __mmplayer_get_video_angle(mm_player_t* player, int *display_angle, int *orientation)
1878 {
1879         int display_rotation = 0;
1880         gchar *org_orient = NULL;
1881         MMHandleType attrs = MMPLAYER_GET_ATTRS(player);
1882
1883         if (!attrs) {
1884                 LOGE("cannot get content attribute");
1885                 return MM_ERROR_PLAYER_INTERNAL;
1886         }
1887
1888         if (display_angle) {
1889                 /* update user roation */
1890                 mm_attrs_get_int_by_name(attrs, "display_rotation", &display_rotation);
1891
1892                 /* Counter clockwise */
1893                 switch (display_rotation) {
1894                 case MM_DISPLAY_ROTATION_NONE:
1895                         *display_angle = 0;
1896                         break;
1897                 case MM_DISPLAY_ROTATION_90:
1898                         *display_angle = 90;
1899                         break;
1900                 case MM_DISPLAY_ROTATION_180:
1901                         *display_angle = 180;
1902                         break;
1903                 case MM_DISPLAY_ROTATION_270:
1904                         *display_angle = 270;
1905                         break;
1906                 default:
1907                         LOGW("wrong angle type : %d", display_rotation);
1908                         break;
1909                 }
1910                 LOGD("check user angle: %d", *display_angle);
1911         }
1912
1913         if (orientation) {
1914                 /* Counter clockwise */
1915                 mm_attrs_get_string_by_name(attrs, "content_video_orientation", &org_orient);
1916
1917                 if (org_orient) {
1918                         if (!strcmp(org_orient, "rotate-90"))
1919                                 *orientation = 90;
1920                         else if (!strcmp(org_orient, "rotate-180"))
1921                                 *orientation = 180;
1922                         else if (!strcmp(org_orient, "rotate-270"))
1923                                 *orientation = 270;
1924                         else
1925                                 LOGD("original rotation is %s", org_orient);
1926                 } else {
1927                         LOGD("content_video_orientation get fail");
1928                 }
1929
1930                 LOGD("check orientation: %d", *orientation);
1931         }
1932
1933         return MM_ERROR_NONE;
1934 }
1935
1936 void
1937 __mmplayer_video_param_set_display_rotation(mm_player_t* player)
1938 {
1939         int rotation_value = 0;
1940         int orientations = 0; // current supported angle values are 0, 90, 180, 270
1941         int display_angle = 0;
1942         MMPLAYER_FENTER();
1943
1944         /* check video sinkbin is created */
1945         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
1946                 return;
1947
1948         __mmplayer_get_video_angle(player, &display_angle, &orientations);
1949
1950         /* get rotation value to set */
1951         __mmplayer_get_property_value_for_rotation(player, display_angle, orientations, &rotation_value);
1952         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotation_value, NULL);
1953         LOGD("set video param : rotate %d", rotation_value);
1954 }
1955
1956 void
1957 __mmplayer_video_param_set_display_visible(mm_player_t* player)
1958 {
1959         MMHandleType attrs = 0;
1960         int visible = 0;
1961         MMPLAYER_FENTER();
1962
1963         /* check video sinkbin is created */
1964         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
1965                 return;
1966
1967         attrs = MMPLAYER_GET_ATTRS(player);
1968         MMPLAYER_RETURN_IF_FAIL(attrs);
1969
1970         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
1971         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "visible", visible, NULL);
1972         LOGD("set video param : visible %d", visible);
1973 }
1974
1975 void
1976 __mmplayer_video_param_set_display_method(mm_player_t* player)
1977 {
1978         MMHandleType attrs = 0;
1979         int display_method = 0;
1980         MMPLAYER_FENTER();
1981
1982         /* check video sinkbin is created */
1983         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
1984                 return;
1985
1986         attrs = MMPLAYER_GET_ATTRS(player);
1987         MMPLAYER_RETURN_IF_FAIL(attrs);
1988
1989         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
1990         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "display-geometry-method", display_method, NULL);
1991         LOGD("set video param : method %d", display_method);
1992 }
1993 void
1994 __mmplayer_video_param_set_video_roi_area(mm_player_t* player)
1995 {
1996         MMHandleType attrs = 0;
1997         void *handle = NULL;
1998         MMPLAYER_FENTER();
1999
2000         /* check video sinkbin is created */
2001         if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) {
2002                 LOGW("There is no video sink");
2003                 return;
2004         }
2005
2006         attrs = MMPLAYER_GET_ATTRS(player);
2007         MMPLAYER_RETURN_IF_FAIL(attrs);
2008         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
2009         if (handle) {
2010                 gst_video_overlay_set_video_roi_area(
2011                          GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
2012                          player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height);
2013                 LOGD("set video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)",
2014                         player->video_roi.scale_x, player->video_roi.scale_y, player->video_roi.scale_width, player->video_roi.scale_height);
2015         }
2016 }
2017
2018 void
2019 __mmplayer_video_param_set_roi_area(mm_player_t* player)
2020 {
2021         MMHandleType attrs = 0;
2022         void *handle = NULL;
2023         /*set wl_display*/
2024         int win_roi_x = 0;
2025         int win_roi_y = 0;
2026         int win_roi_width = 0;
2027         int win_roi_height = 0;
2028         MMPLAYER_FENTER();
2029
2030         /* check video sinkbin is created */
2031         if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE) {
2032                 LOGW("There is no video sink");
2033                 return;
2034         }
2035
2036         attrs = MMPLAYER_GET_ATTRS(player);
2037         MMPLAYER_RETURN_IF_FAIL(attrs);
2038
2039         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
2040
2041         if (handle) {
2042                 /* It should be set after setting window */
2043                 mm_attrs_get_int_by_name(attrs, "display_win_roi_x", &win_roi_x);
2044                 mm_attrs_get_int_by_name(attrs, "display_win_roi_y", &win_roi_y);
2045                 mm_attrs_get_int_by_name(attrs, "display_win_roi_width", &win_roi_width);
2046                 mm_attrs_get_int_by_name(attrs, "display_win_roi_height", &win_roi_height);
2047
2048                 /* After setting window handle, set display roi area */
2049                 gst_video_overlay_set_display_roi_area(
2050                          GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
2051                          win_roi_x, win_roi_y, win_roi_width, win_roi_height);
2052                 LOGD("set video param : roi area : x(%d) y(%d) width(%d) height(%d)",
2053                         win_roi_x, win_roi_y, win_roi_width, win_roi_height);
2054         }
2055 }
2056 void
2057 __mmplayer_video_param_set_display_overlay(mm_player_t* player)
2058 {
2059         MMHandleType attrs = 0;
2060         void *handle = NULL;
2061
2062         /* check video sinkbin is created */
2063         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
2064                 return;
2065
2066         attrs = MMPLAYER_GET_ATTRS(player);
2067         MMPLAYER_RETURN_IF_FAIL(attrs);
2068
2069         /* common case if using overlay surface */
2070         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
2071
2072         if (handle) {
2073                 /* default is using wl_surface_id */
2074                 unsigned int wl_surface_id      = 0;
2075                 wl_surface_id = *(int*)handle;
2076                 LOGD("set video param : wl_surface_id %d %p", wl_surface_id, *(int*)handle);
2077                 gst_video_overlay_set_wl_window_wl_surface_id(
2078                                 GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
2079                                 *(int*)handle);
2080         } else
2081                 /* FIXIT : is it error case? */
2082                 LOGW("still we don't have a window handle on player attribute. create it's own surface.");
2083 }
2084
2085
2086 int
2087 __mmplayer_update_wayland_videosink_video_param(mm_player_t* player, char *param_name)
2088 {
2089         bool update_all_param = FALSE;
2090         MMPLAYER_FENTER();
2091
2092         /* check video sinkbin is created */
2093         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
2094                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
2095
2096         if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
2097                 LOGE("can not find tizenwlsink");
2098                 return MM_ERROR_PLAYER_INTERNAL;
2099         }
2100
2101         LOGD("param_name : %s", param_name);
2102         if (!g_strcmp0(param_name, "update_all_param"))
2103                 update_all_param = TRUE;
2104
2105         if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
2106                 __mmplayer_video_param_set_display_overlay(player);
2107         if (update_all_param || !g_strcmp0(param_name, "display_method"))
2108                 __mmplayer_video_param_set_display_method(player);
2109         if (update_all_param || !g_strcmp0(param_name, "display_visible"))
2110                 __mmplayer_video_param_set_display_visible(player);
2111         if (update_all_param || !g_strcmp0(param_name, "display_rotation"))
2112                 __mmplayer_video_param_set_display_rotation(player);
2113         if (update_all_param || !g_strcmp0(param_name, "display_win_roi_x"))
2114                 __mmplayer_video_param_set_roi_area(player);
2115         if (update_all_param)
2116                 __mmplayer_video_param_set_video_roi_area(player);
2117
2118         return MM_ERROR_NONE;
2119 }
2120
2121 int
2122 _mmplayer_update_video_param(mm_player_t* player, char *param_name)
2123 {
2124         MMHandleType attrs = 0;
2125         int surface_type = 0;
2126         int ret = MM_ERROR_NONE;
2127
2128         MMPLAYER_FENTER();
2129
2130         /* check video sinkbin is created */
2131         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
2132                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
2133
2134         attrs = MMPLAYER_GET_ATTRS(player);
2135         if (!attrs) {
2136                 LOGE("cannot get content attribute");
2137                 return MM_ERROR_PLAYER_INTERNAL;
2138         }
2139         LOGD("param_name : %s", param_name);
2140
2141         /* update display surface */
2142         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
2143         LOGD("check display surface type attribute: %d", surface_type);
2144
2145         /* configuring display */
2146         switch (surface_type) {
2147         case MM_DISPLAY_SURFACE_OVERLAY:
2148                 {
2149                         ret = __mmplayer_update_wayland_videosink_video_param(player, param_name);
2150                         if (ret != MM_ERROR_NONE)
2151                                 return ret;
2152                 }
2153                 break;
2154         }
2155
2156         MMPLAYER_FLEAVE();
2157
2158         return MM_ERROR_NONE;
2159 }
2160
2161 int
2162 _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
2163 {
2164         gboolean disable_overlay = FALSE;
2165         mm_player_t* player = (mm_player_t*) hplayer;
2166         int ret = MM_ERROR_NONE;
2167
2168         MMPLAYER_FENTER();
2169         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
2170         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
2171                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2172                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
2173
2174         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
2175                 LOGW("Display control is not supported");
2176                 return MM_ERROR_PLAYER_INTERNAL;
2177         }
2178
2179         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
2180
2181         if (audio_only == (bool)disable_overlay) {
2182                 LOGE("It's the same with current setting: (%d)", audio_only);
2183                 return MM_ERROR_NONE;
2184         }
2185
2186         if (audio_only) {
2187                 LOGE("disable overlay");
2188                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
2189
2190                 /* release overlay resource */
2191                 if (player->video_overlay_resource != NULL) {
2192                         ret = mm_resource_manager_mark_for_release(player->resource_manager,
2193                                         player->video_overlay_resource);
2194                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
2195                                 LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
2196                                 goto ERROR;
2197                         }
2198                         player->video_overlay_resource = NULL;
2199                 }
2200
2201                 ret = mm_resource_manager_commit(player->resource_manager);
2202                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
2203                         LOGE("failed to commit acquiring of overlay resource, ret(0x%x)\n", ret);
2204                         goto ERROR;
2205                 }
2206         } else {
2207                 /* mark video overlay for acquire */
2208                 if (player->video_overlay_resource == NULL) {
2209                         ret = mm_resource_manager_mark_for_acquire(player->resource_manager,
2210                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
2211                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
2212                                         &player->video_overlay_resource);
2213                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
2214                                 LOGE("could not prepare for video_overlay resource\n");
2215                                 goto ERROR;
2216                         }
2217                 }
2218
2219                 player->interrupted_by_resource = FALSE;
2220                 /* acquire resources for video overlay */
2221                 ret = mm_resource_manager_commit(player->resource_manager);
2222                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
2223                         LOGE("could not acquire resources for video playing\n");
2224                         goto ERROR;
2225                 }
2226
2227                 LOGD("enable overlay");
2228                 __mmplayer_video_param_set_display_overlay(player);
2229                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL);
2230         }
2231
2232 ERROR:
2233         MMPLAYER_FLEAVE();
2234         return MM_ERROR_NONE;
2235 }
2236
2237 int
2238 _mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
2239 {
2240         mm_player_t* player = (mm_player_t*) hplayer;
2241         gboolean disable_overlay = FALSE;
2242
2243         MMPLAYER_FENTER();
2244
2245         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
2246         MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT);
2247         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
2248                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2249                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
2250
2251         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
2252                 LOGW("Display control is not supported");
2253                 return MM_ERROR_PLAYER_INTERNAL;
2254         }
2255
2256         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
2257
2258         *paudio_only = (bool)(disable_overlay);
2259
2260         LOGD("audio_only : %d", *paudio_only);
2261
2262         MMPLAYER_FLEAVE();
2263
2264         return MM_ERROR_NONE;
2265 }
2266
2267 int
2268 __mmplayer_gst_element_link_bucket(GList* element_bucket)
2269 {
2270         GList* bucket = element_bucket;
2271         MMPlayerGstElement* element = NULL;
2272         MMPlayerGstElement* prv_element = NULL;
2273         gint successful_link_count = 0;
2274
2275         MMPLAYER_FENTER();
2276
2277         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, -1);
2278
2279         prv_element = (MMPlayerGstElement*)bucket->data;
2280         bucket = bucket->next;
2281
2282         for (; bucket; bucket = bucket->next) {
2283                 element = (MMPlayerGstElement*)bucket->data;
2284
2285                 if (element && element->gst) {
2286                         if (prv_element && prv_element->gst) {
2287                                 if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
2288                                         LOGD("linking [%s] to [%s] success\n",
2289                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
2290                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
2291                                         successful_link_count++;
2292                                 } else {
2293                                         LOGD("linking [%s] to [%s] failed\n",
2294                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
2295                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
2296                                         return -1;
2297                                 }
2298                         }
2299                 }
2300
2301                 prv_element = element;
2302         }
2303
2304         MMPLAYER_FLEAVE();
2305
2306         return successful_link_count;
2307 }
2308
2309 int
2310 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket)
2311 {
2312         GList* bucket = element_bucket;
2313         MMPlayerGstElement* element = NULL;
2314         int successful_add_count = 0;
2315
2316         MMPLAYER_FENTER();
2317
2318         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, 0);
2319         MMPLAYER_RETURN_VAL_IF_FAIL(bin, 0);
2320
2321         for (; bucket; bucket = bucket->next) {
2322                 element = (MMPlayerGstElement*)bucket->data;
2323
2324                 if (element && element->gst) {
2325                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
2326                                 LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
2327                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
2328                                         GST_ELEMENT_NAME(GST_ELEMENT(bin)));
2329                                 return 0;
2330                         }
2331                         successful_add_count++;
2332                 }
2333         }
2334
2335         MMPLAYER_FLEAVE();
2336
2337         return successful_add_count;
2338 }
2339
2340 static void __mmplayer_gst_caps_notify_cb(GstPad *pad, GParamSpec *unused, gpointer data)
2341 {
2342         mm_player_t *player = (mm_player_t*) data;
2343         GstCaps *caps = NULL;
2344         GstStructure *str = NULL;
2345         const char *name;
2346         gboolean caps_ret = TRUE;
2347
2348         MMPLAYER_FENTER();
2349
2350         MMPLAYER_RETURN_IF_FAIL(pad);
2351         MMPLAYER_RETURN_IF_FAIL(unused);
2352         MMPLAYER_RETURN_IF_FAIL(data);
2353
2354         caps = gst_pad_get_current_caps(pad);
2355         if (!caps)
2356                 return;
2357
2358         MMPLAYER_GST_GET_CAPS_INFO(pad, caps, str, name, caps_ret);
2359         if (!caps_ret)
2360                 goto ERROR;
2361
2362         LOGD("name = %s", name);
2363
2364         if (strstr(name, "audio")) {
2365                 __mmplayer_update_content_attrs(player, ATTR_AUDIO);
2366
2367                 if (player->audio_stream_changed_cb) {
2368                         LOGE("call the audio stream changed cb");
2369                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
2370                 }
2371         } else if (strstr(name, "video")) {
2372                 if ((name = gst_structure_get_string(str, "format")))
2373                         player->set_mode.video_zc = name[0] == 'S';
2374
2375                 __mmplayer_update_content_attrs(player, ATTR_VIDEO);
2376
2377                 if (player->video_stream_changed_cb) {
2378                         LOGE("call the video stream changed cb");
2379                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
2380                 }
2381         } else {
2382                 LOGW("invalid caps info");
2383         }
2384
2385 ERROR:
2386         if (caps)
2387                 gst_caps_unref(caps);
2388
2389         MMPLAYER_FLEAVE();
2390
2391         return;
2392 }
2393
2394
2395
2396 /**
2397  * This function is to create audio pipeline for playing.
2398  *
2399  * @param       player          [in]    handle of player
2400  *
2401  * @return      This function returns zero on success.
2402  * @remark
2403  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
2404  */
2405 /* macro for code readability. just for sinkbin-creation functions */
2406 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
2407 do {\
2408         x_bin[x_id].id = x_id;\
2409         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
2410         if (!x_bin[x_id].gst) {\
2411                 LOGE("failed to create %s \n", x_factory);\
2412                 goto ERROR;\
2413         } else {\
2414                 if (x_player->ini.set_dump_element_flag)\
2415                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
2416         } \
2417         if (x_add_bucket)\
2418                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
2419 } while (0);
2420
2421 void
2422 __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all)
2423 {
2424         GList *l = NULL;
2425
2426         MMPLAYER_FENTER();
2427         MMPLAYER_RETURN_IF_FAIL(player);
2428
2429         if (player->audio_stream_buff_list) {
2430                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
2431                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
2432                         if (tmp) {
2433                                 if (send_all) {
2434                                         LOGD("[%"G_GUINT64_FORMAT"] send remained data.", tmp->channel_mask);
2435                                         __mmplayer_audio_stream_send_data(player, tmp);
2436                                 }
2437                                 if (tmp->pcm_data)
2438                                         g_free(tmp->pcm_data);
2439                                 g_free(tmp);
2440                         }
2441                 }
2442                 g_list_free(player->audio_stream_buff_list);
2443                 player->audio_stream_buff_list = NULL;
2444         }
2445
2446         MMPLAYER_FLEAVE();
2447 }
2448
2449 static void
2450 __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer)
2451 {
2452         MMPlayerAudioStreamDataType audio_stream = { 0, };
2453
2454         MMPLAYER_FENTER();
2455         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb);
2456
2457         audio_stream.bitrate = a_buffer->bitrate;
2458         audio_stream.channel = a_buffer->channel;
2459         audio_stream.depth = a_buffer->depth;
2460         audio_stream.is_little_endian = a_buffer->is_little_endian;
2461         audio_stream.channel_mask = a_buffer->channel_mask;
2462         audio_stream.data_size = a_buffer->data_size;
2463         audio_stream.data = a_buffer->pcm_data;
2464
2465         /* LOGD("[%"G_GUINT64_FORMAT"] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); */
2466         player->audio_stream_render_cb(&audio_stream, player->audio_stream_cb_user_param);
2467
2468         MMPLAYER_FLEAVE();
2469 }
2470
2471 static void
2472 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
2473 {
2474         mm_player_t* player = (mm_player_t*) data;
2475
2476         gint channel = 0;
2477         gint rate = 0;
2478         gint depth = 0;
2479         gint endianness = 0;
2480         guint64 channel_mask = 0;
2481         void *a_data = NULL;
2482         gint a_size = 0;
2483         mm_player_audio_stream_buff_t *a_buffer = NULL;
2484         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
2485         GList *l = NULL;
2486
2487         MMPLAYER_FENTER();
2488         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb);
2489
2490         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
2491         a_data = mapinfo.data;
2492         a_size = mapinfo.size;
2493
2494         GstCaps *caps = gst_pad_get_current_caps(pad);
2495         GstStructure *structure = gst_caps_get_structure(caps, 0);
2496
2497         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
2498         gst_structure_get_int(structure, "rate", &rate);
2499         gst_structure_get_int(structure, "channels", &channel);
2500         gst_structure_get_int(structure, "depth", &depth);
2501         gst_structure_get_int(structure, "endianness", &endianness);
2502         gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
2503         gst_caps_unref(GST_CAPS(caps));
2504
2505         /* In case of the sync is false, use buffer list.              *
2506          * The num of buffer list depends on the num of audio channels */
2507         if (player->audio_stream_buff_list) {
2508                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
2509                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
2510                         if (tmp) {
2511                                 if (channel_mask == tmp->channel_mask) {
2512                                         /* LOGD("[%"G_GUINT64_FORMAT"] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */
2513                                         if (tmp->data_size + a_size < tmp->buff_size) {
2514                                                 memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size);
2515                                                 tmp->data_size += a_size;
2516                                         } else {
2517                                                 /* send data to client */
2518                                                 __mmplayer_audio_stream_send_data(player, tmp);
2519
2520                                                 if (a_size > tmp->buff_size) {
2521                                                         LOGD("[%"G_GUINT64_FORMAT"] adj buffer size %d -> %d", channel_mask, tmp->buff_size, a_size);
2522                                                         tmp->pcm_data = g_realloc(tmp->pcm_data, a_size);
2523                                                         if (tmp->pcm_data == NULL) {
2524                                                                 LOGE("failed to realloc data.");
2525                                                                 goto DONE;
2526                                                         }
2527                                                         tmp->buff_size = a_size;
2528                                                 }
2529                                                 memset(tmp->pcm_data, 0x00, tmp->buff_size);
2530                                                 memcpy(tmp->pcm_data, a_data, a_size);
2531                                                 tmp->data_size = a_size;
2532                                         }
2533                                         goto DONE;
2534                                 }
2535                         } else {
2536                                 LOGE("data is empty in list.");
2537                                 goto DONE;
2538                         }
2539                 }
2540         }
2541
2542         /* create new audio stream data */
2543         a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t));
2544         if (a_buffer == NULL) {
2545                 LOGE("failed to alloc data.");
2546                 goto DONE;
2547         }
2548         a_buffer->bitrate = rate;
2549         a_buffer->channel = channel;
2550         a_buffer->depth = depth;
2551         a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0);
2552         a_buffer->channel_mask = channel_mask;
2553         a_buffer->data_size = a_size;
2554
2555         if (!player->audio_stream_sink_sync) {
2556                 /* If sync is FALSE, use buffer list to reduce the IPC. */
2557                 a_buffer->buff_size = (a_size > player->ini.pcm_buffer_size) ? (a_size) : (player->ini.pcm_buffer_size);
2558                 a_buffer->pcm_data = g_malloc(a_buffer->buff_size);
2559                 if (a_buffer->pcm_data == NULL) {
2560                         LOGE("failed to alloc data.");
2561                         g_free(a_buffer);
2562                         goto DONE;
2563                 }
2564                 memcpy(a_buffer->pcm_data, a_data, a_size);
2565                 /* LOGD("new [%"G_GUINT64_FORMAT"] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */
2566                 player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer);
2567         } else {
2568                 /* If sync is TRUE, send data directly. */
2569                 a_buffer->pcm_data = a_data;
2570                 __mmplayer_audio_stream_send_data(player, a_buffer);
2571                 g_free(a_buffer);
2572         }
2573
2574 DONE:
2575         gst_buffer_unmap(buffer, &mapinfo);
2576         MMPLAYER_FLEAVE();
2577 }
2578
2579 static void
2580 __mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2581 {
2582         mm_player_t* player = (mm_player_t*)data;
2583         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
2584         GstPad* sinkpad = NULL;
2585         GstElement *queue = NULL, *sink = NULL;
2586
2587         MMPLAYER_FENTER();
2588         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2589
2590         queue = gst_element_factory_make("queue", NULL);
2591         if (queue == NULL) {
2592                 LOGD("fail make queue\n");
2593                 goto ERROR;
2594         }
2595
2596         sink = gst_element_factory_make("fakesink", NULL);
2597         if (sink == NULL) {
2598                 LOGD("fail make fakesink\n");
2599                 goto ERROR;
2600         }
2601
2602         gst_bin_add_many(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
2603
2604         if (!gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) {
2605                 LOGW("failed to link queue & sink\n");
2606                 goto ERROR;
2607         }
2608
2609         sinkpad = gst_element_get_static_pad(queue, "sink");
2610
2611         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2612                 LOGW("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
2613                 goto ERROR;
2614         }
2615
2616         LOGE("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
2617
2618         gst_object_unref(sinkpad);
2619         g_object_set(sink, "sync", player->audio_stream_sink_sync, NULL);
2620         g_object_set(sink, "signal-handoffs", TRUE, NULL);
2621
2622         gst_element_set_state(sink, GST_STATE_PAUSED);
2623         gst_element_set_state(queue, GST_STATE_PAUSED);
2624
2625         __mmplayer_add_signal_connection(player,
2626                 G_OBJECT(sink),
2627                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
2628                 "handoff",
2629                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
2630                 (gpointer)player);
2631
2632         MMPLAYER_FLEAVE();
2633         return;
2634
2635 ERROR:
2636         LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
2637         if (queue) {
2638                 gst_object_unref(GST_OBJECT(queue));
2639                 queue = NULL;
2640         }
2641         if (sink) {
2642                 gst_object_unref(GST_OBJECT(sink));
2643                 sink = NULL;
2644         }
2645         if (sinkpad) {
2646                 gst_object_unref(GST_OBJECT(sinkpad));
2647                 sinkpad = NULL;
2648         }
2649
2650         return;
2651 }
2652
2653 void __mmplayer_gst_set_pulsesink_property(mm_player_t* player, MMHandleType attrs)
2654 {
2655         #define MAX_PROPS_LEN 128
2656         gint latency_mode = 0;
2657         gchar *stream_type = NULL;
2658         gchar *latency = NULL;
2659         gint stream_id = 0;
2660         gchar stream_props[MAX_PROPS_LEN] = {0,};
2661         GstStructure *props = NULL;
2662
2663         /* set volume table
2664          * It should be set after player creation through attribute.
2665          * But, it can not be changed during playing.
2666          */
2667         MMPLAYER_FENTER();
2668         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin);
2669
2670         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
2671         mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
2672
2673         if (!stream_type) {
2674                 LOGE("stream_type is null.");
2675         } else {
2676                 if (player->sound.focus_id)
2677                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d, media.focus_id=%d",
2678                                         stream_type, stream_id, player->sound.focus_id);
2679                 else
2680                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d",
2681                                         stream_type, stream_id);
2682                 props = gst_structure_from_string(stream_props, NULL);
2683                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
2684                 LOGI("stream_type[%s], stream_id[%d], focus_id[%d], result[%s].",
2685                         stream_type, stream_id, player->sound.focus_id, stream_props);
2686                 gst_structure_free(props);
2687         }
2688
2689         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
2690
2691         switch (latency_mode) {
2692         case AUDIO_LATENCY_MODE_LOW:
2693                 latency = g_strndup("low", 3);
2694                 break;
2695         case AUDIO_LATENCY_MODE_MID:
2696                 latency = g_strndup("mid", 3);
2697                 break;
2698         case AUDIO_LATENCY_MODE_HIGH:
2699                 latency = g_strndup("high", 4);
2700                 break;
2701         };
2702
2703         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
2704                         "latency", latency,
2705                         NULL);
2706
2707         LOGD("audiosink property - latency=%s", latency);
2708
2709         g_free(latency);
2710
2711         MMPLAYER_FLEAVE();
2712 }
2713
2714 void __mmplayer_gst_set_openalsink_property(mm_player_t* player)
2715 {
2716         MMPlayerGstElement *audiobin = NULL;
2717
2718         MMPLAYER_FENTER();
2719         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->audiobin);
2720
2721         audiobin = player->pipeline->audiobin;
2722
2723         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL);
2724         sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
2725         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
2726
2727         if (player->video360_yaw_radians <= M_PI &&
2728                         player->video360_yaw_radians >= -M_PI &&
2729                         player->video360_pitch_radians <= M_PI_2 &&
2730                         player->video360_pitch_radians >= -M_PI_2) {
2731                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
2732                                 "source-orientation-y", (int) (player->video360_yaw_radians * 180.0 / M_PI),
2733                                 "source-orientation-x", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
2734         } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
2735                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
2736                                 "source-orientation-y", player->video360_metadata.init_view_heading,
2737                                 "source-orientation-x", player->video360_metadata.init_view_pitch, NULL);
2738         }
2739
2740         MMPLAYER_FLEAVE();
2741 }
2742
2743 static int
2744 __mmplayer_gst_fill_audio_bucket(mm_player_t *player, GList **bucket)
2745 {
2746         MMPlayerGstElement *audiobin = NULL;
2747         MMHandleType attrs = 0;
2748         GList *element_bucket = NULL;
2749         GstCaps *acaps = NULL;
2750         GstPad *sink_pad = NULL;
2751
2752         MMPLAYER_FENTER();
2753         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline &&
2754                                 player->pipeline->audiobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
2755
2756         audiobin = player->pipeline->audiobin;
2757         attrs = MMPLAYER_GET_ATTRS(player);
2758
2759         /* converter */
2760         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
2761
2762         /* replaygain volume */
2763         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RGVOL, "rgvolume", "audio rgvolume", TRUE, player);
2764         if (player->sound.rg_enable)
2765                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", TRUE, NULL);
2766         else
2767                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", FALSE, NULL);
2768
2769         /* resampler */
2770         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.audioresampler_element, "audio resampler", TRUE, player);
2771
2772         if (player->audio_stream_render_cb) { /* pcm extraction only, no sound output */
2773                 gchar *dst_format = NULL;
2774                 int dst_len = 0;
2775                 int dst_samplerate = 0;
2776                 int dst_channels = 0;
2777                 GstCaps *caps = NULL;
2778                 char *caps_str = NULL;
2779
2780                 /* get conf. values */
2781                 mm_attrs_multiple_get(player->attrs, NULL,
2782                                         "pcm_audioformat", &dst_format, &dst_len,
2783                                         "pcm_extraction_samplerate", &dst_samplerate,
2784                                         "pcm_extraction_channels", &dst_channels,
2785                                         NULL);
2786
2787                 LOGD("pcm info - format: %s(%d), samplerate : %d, channel: %d", dst_format, dst_len, dst_samplerate, dst_channels);
2788
2789                 /* capsfilter */
2790                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
2791                 caps = gst_caps_new_simple("audio/x-raw",
2792                                 "format", G_TYPE_STRING, dst_format,
2793                                 "rate", G_TYPE_INT, dst_samplerate,
2794                                 "channels", G_TYPE_INT, dst_channels,
2795                                 NULL);
2796
2797                 caps_str = gst_caps_to_string(caps);
2798                 LOGD("new caps : %s", caps_str);
2799
2800                 g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
2801
2802                 /* clean */
2803                 gst_caps_unref(caps);
2804                 MMPLAYER_FREEIF(caps_str);
2805
2806                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
2807
2808                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
2809
2810                 /* raw pad handling signal, audiosink will be added after getting signal */
2811                 __mmplayer_add_signal_connection(player, G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
2812                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added", G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), (gpointer)player);
2813
2814         } else {
2815
2816                 /* normal playback */
2817                 gint channels = 0;
2818
2819                 /* for logical volume control */
2820                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
2821                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
2822
2823                 if (player->sound.mute) {
2824                         LOGD("mute enabled");
2825                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
2826                 }
2827
2828                 /* check if multi-channels */
2829                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) {
2830                         GstPad *srcpad = NULL;
2831                         GstCaps *caps = NULL;
2832
2833                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src"))) {
2834                                 if ((caps = gst_pad_query_caps(srcpad, NULL))) {
2835                                         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
2836                                         GstStructure *str = gst_caps_get_structure(caps, 0);
2837                                         if (str)
2838                                                 gst_structure_get_int(str, "channels", &channels);
2839                                         gst_caps_unref(caps);
2840                                 }
2841                                 gst_object_unref(srcpad);
2842                         }
2843                 }
2844
2845                 /* audio effect element. if audio effect is enabled */
2846                 if ((strcmp(player->ini.audioeffect_element, ""))
2847                         && (channels <= 2)
2848                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
2849                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
2850
2851                         LOGD("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
2852
2853                         if ((!player->bypass_audio_effect)
2854                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
2855                                 if (player->audio_effect_info.effect_type == MM_AUDIO_EFFECT_TYPE_CUSTOM) {
2856                                         if (!_mmplayer_audio_effect_custom_apply(player))
2857                                                 LOGI("apply audio effect(custom) setting success");
2858                                 }
2859                         }
2860
2861                         if ((strcmp(player->ini.audioeffect_element_custom, ""))
2862                                 && (player->set_mode.rich_audio))
2863                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
2864                 }
2865
2866                 /* create audio sink */
2867                 LOGD("360 spherical %d, channels %d, ambisonic type %d, format %d, order %d",
2868                                 player->is_content_spherical, channels, player->video360_metadata.ambisonic_type,
2869                                 player->video360_metadata.ambisonic_format, player->video360_metadata.ambisonic_order);
2870
2871                 /* Note: qtdemux converts audio metadata defaults to openalsink defaults. */
2872                 if (player->is_360_feature_enabled &&
2873                         player->is_content_spherical &&
2874                         channels == 4 &&
2875                         player->video360_metadata.ambisonic_type == MMFILE_AMBISONIC_TYPE_PERIPHONIC &&
2876                         player->video360_metadata.ambisonic_format == MMFILE_AMBISONIC_FORMAT_AMB &&
2877                         player->video360_metadata.ambisonic_order == MMFILE_AMBISONIC_ORDER_FOA) {
2878
2879                         strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
2880
2881                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", TRUE, player);
2882
2883                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", TRUE, player);
2884                         acaps = gst_caps_from_string(SPATIAL_AUDIO_CAPS);
2885                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_CAPS_360].gst), "caps", acaps, NULL);
2886                         gst_caps_unref(acaps);
2887
2888                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", TRUE, player);
2889
2890                         player->is_openal_plugin_used = TRUE;
2891                 } else {
2892                         if (player->is_360_feature_enabled && player->is_content_spherical)
2893                                 LOGW("Audio track isn't of the ambisonic type and can't be played back as a spatial sound.");
2894                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", TRUE, player);
2895                 }
2896
2897                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
2898                         (player->videodec_linked && player->ini.use_system_clock)) {
2899                         LOGD("system clock will be used.");
2900                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE,  NULL);
2901                 }
2902
2903                 if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
2904                         __mmplayer_gst_set_pulsesink_property(player, attrs);
2905                 else if (g_strrstr(player->ini.audiosink_element, "openalsink"))
2906                         __mmplayer_gst_set_openalsink_property(player);
2907
2908                 /* qos on */
2909                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);       /* qos on */
2910                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
2911
2912                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
2913                 __mmplayer_add_signal_connection(player, G_OBJECT(sink_pad), MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
2914                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), (gpointer)player);
2915                 gst_object_unref(GST_OBJECT(sink_pad));
2916
2917                 __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
2918         }
2919
2920         *bucket = element_bucket;
2921
2922         MMPLAYER_FLEAVE();
2923         return MM_ERROR_NONE;
2924
2925 ERROR:
2926         g_list_free(element_bucket);
2927
2928         *bucket = NULL;
2929         MMPLAYER_FLEAVE();
2930         return MM_ERROR_PLAYER_INTERNAL;
2931 }
2932
2933 static int
2934 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
2935 {
2936         MMPlayerGstElement *first_element = NULL;
2937         MMPlayerGstElement *audiobin = NULL;
2938         GstPad *pad = NULL;
2939         GstPad *ghostpad = NULL;
2940         GList *element_bucket = NULL;
2941         int i = 0;
2942
2943         MMPLAYER_FENTER();
2944         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
2945
2946         /* alloc handles */
2947         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
2948         if (!audiobin) {
2949                 LOGE("failed to allocate memory for audiobin");
2950                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
2951         }
2952
2953         /* create bin */
2954         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
2955         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
2956         if (!audiobin[MMPLAYER_A_BIN].gst) {
2957                 LOGE("failed to create audiobin");
2958                 goto ERROR;
2959         }
2960
2961         /* take it */
2962         player->pipeline->audiobin = audiobin;
2963
2964         /* create audio filters and audiosink */
2965         if (__mmplayer_gst_fill_audio_bucket(player, &element_bucket) != MM_ERROR_NONE)
2966                 goto ERROR;
2967
2968         /* adding created elements to bin */
2969         LOGD("adding created elements to bin");
2970         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket))
2971                 goto ERROR;
2972
2973         /* linking elements in the bucket by added order. */
2974         LOGD("Linking elements in the bucket by added order.");
2975         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1)
2976                 goto ERROR;
2977
2978         /* get first element's sinkpad for creating ghostpad */
2979         first_element = (MMPlayerGstElement *)element_bucket->data;
2980         if (!first_element) {
2981                 LOGE("failed to get first elem");
2982                 goto ERROR;
2983         }
2984
2985         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
2986         if (!pad) {
2987                 LOGE("failed to get pad from first element of audiobin");
2988                 goto ERROR;
2989         }
2990
2991         ghostpad = gst_ghost_pad_new("sink", pad);
2992         if (!ghostpad) {
2993                 LOGE("failed to create ghostpad");
2994                 goto ERROR;
2995         }
2996
2997         if (!gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
2998                 LOGE("failed to add ghostpad to audiobin");
2999                 goto ERROR;
3000         }
3001
3002         gst_object_unref(pad);
3003
3004         g_list_free(element_bucket);
3005         MMPLAYER_FLEAVE();
3006
3007         return MM_ERROR_NONE;
3008
3009 ERROR:
3010         LOGD("ERROR : releasing audiobin");
3011
3012         if (pad)
3013                 gst_object_unref(GST_OBJECT(pad));
3014
3015         if (ghostpad)
3016                 gst_object_unref(GST_OBJECT(ghostpad));
3017
3018         if (element_bucket)
3019                 g_list_free(element_bucket);
3020
3021         /* release element which are not added to bin */
3022         for (i = 1; i < MMPLAYER_A_NUM; i++) {
3023                 /* NOTE : skip bin */
3024                 if (audiobin[i].gst) {
3025                         GstObject* parent = NULL;
3026                         parent = gst_element_get_parent(audiobin[i].gst);
3027
3028                         if (!parent) {
3029                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
3030                                 audiobin[i].gst = NULL;
3031                         } else
3032                                 gst_object_unref(GST_OBJECT(parent));
3033                 }
3034         }
3035
3036         /* release audiobin with it's childs */
3037         if (audiobin[MMPLAYER_A_BIN].gst)
3038                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
3039
3040         MMPLAYER_FREEIF(audiobin);
3041
3042         player->pipeline->audiobin = NULL;
3043
3044         return MM_ERROR_PLAYER_INTERNAL;
3045 }
3046
3047 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
3048 {
3049         return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
3050 }
3051
3052 int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
3053 {
3054         int ret = MM_ERROR_NONE;
3055         GList *l = NULL;
3056         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3057         MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_INVALID_ARGUMENT);
3058
3059         MMPLAYER_VIDEO_BO_LOCK(player);
3060
3061         if (player->video_bo_list) {
3062                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
3063                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
3064                         if (tmp && tmp->bo == bo) {
3065                                 tmp->used = FALSE;
3066                                 LOGD("release bo %p", bo);
3067                                 tbm_bo_unref(tmp->bo);
3068                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
3069                                 MMPLAYER_VIDEO_BO_SIGNAL(player);
3070                                 return ret;
3071                         }
3072                 }
3073         } else {
3074                 /* hw codec is running or the list was reset for DRC. */
3075                 LOGW("there is no bo list.");
3076         }
3077         MMPLAYER_VIDEO_BO_UNLOCK(player);
3078
3079         LOGW("failed to find bo %p", bo);
3080         return ret;
3081 }
3082
3083 static void
3084 __mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
3085 {
3086         GList *l = NULL;
3087
3088         MMPLAYER_FENTER();
3089         MMPLAYER_RETURN_IF_FAIL(player);
3090
3091         MMPLAYER_VIDEO_BO_LOCK(player);
3092         if (player->video_bo_list) {
3093                 LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
3094                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
3095                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
3096                         if (tmp) {
3097                                 if (tmp->bo)
3098                                         tbm_bo_unref(tmp->bo);
3099                                 g_free(tmp);
3100                         }
3101                 }
3102                 g_list_free(player->video_bo_list);
3103                 player->video_bo_list = NULL;
3104         }
3105         player->video_bo_size = 0;
3106         MMPLAYER_VIDEO_BO_UNLOCK(player);
3107
3108         MMPLAYER_FLEAVE();
3109         return;
3110 }
3111
3112 static void*
3113 __mmplayer_video_stream_get_bo(mm_player_t* player, int size)
3114 {
3115         GList *l = NULL;
3116         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
3117         gboolean ret = TRUE;
3118
3119         /* check DRC, if it is, destroy the prev bo list to create again */
3120         if (player->video_bo_size != size) {
3121                 LOGD("video size is changed: %d -> %d", player->video_bo_size, size);
3122                 __mmplayer_video_stream_destroy_bo_list(player);
3123                 player->video_bo_size = size;
3124         }
3125
3126         MMPLAYER_VIDEO_BO_LOCK(player);
3127
3128         if ((!player->video_bo_list) ||
3129                 (g_list_length(player->video_bo_list) < player->ini.num_of_video_bo)) {
3130
3131                 /* create bo list */
3132                 int idx = 0;
3133                 LOGD("Create bo list for decoded video stream(num:%d)", player->ini.num_of_video_bo);
3134
3135                 if (player->video_bo_list) {
3136                         /* if bo list did not created all, try it again. */
3137                         idx = g_list_length(player->video_bo_list);
3138                         LOGD("bo list exist(len: %d)", idx);
3139                 }
3140
3141                 for (; idx < player->ini.num_of_video_bo; idx++) {
3142                         mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
3143                         if (!bo_info) {
3144                                 LOGE("Fail to alloc bo_info.");
3145                                 break;
3146                         }
3147                         bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
3148                         if (!bo_info->bo) {
3149                                 LOGE("Fail to tbm_bo_alloc.");
3150                                 g_free(bo_info);
3151                                 break;
3152                         }
3153                         bo_info->used = FALSE;
3154                         player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
3155                 }
3156
3157                 /* update video num buffers */
3158                 player->video_num_buffers = idx;
3159                 if (idx == player->ini.num_of_video_bo)
3160                         player->video_extra_num_buffers = player->ini.num_of_video_bo/2;
3161
3162                 if (idx == 0) {
3163                         MMPLAYER_VIDEO_BO_UNLOCK(player);
3164                         return NULL;
3165                 }
3166
3167                 LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
3168         }
3169
3170         while (TRUE) {
3171                 /* get bo from list*/
3172                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
3173                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
3174                         if (tmp && (tmp->used == FALSE)) {
3175                                 LOGD("found bo %p to use", tmp->bo);
3176                                 tmp->used = TRUE;
3177                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
3178                                 return tbm_bo_ref(tmp->bo);
3179                         }
3180                 }
3181                 if (!ret) {
3182                         LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
3183                         MMPLAYER_VIDEO_BO_UNLOCK(player);
3184                         return NULL;
3185                 }
3186
3187                 if (player->ini.video_bo_timeout <= 0) {
3188                         MMPLAYER_VIDEO_BO_WAIT(player);
3189                 } else {
3190                         gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
3191                         ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
3192                 }
3193                 continue;
3194         }
3195 }
3196
3197 static void
3198 __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
3199 {
3200         mm_player_t* player = (mm_player_t*)data;
3201         MMPLAYER_FENTER();
3202         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
3203
3204         /* send prerolled pkt */
3205         player->video_stream_prerolled = FALSE;
3206
3207         __mmplayer_video_stream_decoded_render_cb(object, buffer, pad, data);
3208
3209         /* not to send prerolled pkt again */
3210         player->video_stream_prerolled = TRUE;
3211 }
3212
3213 static void
3214 __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
3215 {
3216         mm_player_t* player = (mm_player_t*)data;
3217         MMPlayerVideoStreamDataType *stream = NULL;
3218         GstMemory *mem = NULL;
3219
3220         MMPLAYER_FENTER();
3221         MMPLAYER_RETURN_IF_FAIL(player);
3222         MMPLAYER_RETURN_IF_FAIL(player->video_stream_cb);
3223
3224         if (player->video_stream_prerolled) {
3225                 player->video_stream_prerolled = FALSE;
3226                 LOGD("skip the prerolled pkt not to send it again");
3227                 return;
3228         }
3229
3230         /* clear stream data structure */
3231         stream = __mmplayer_create_stream_from_pad(pad);
3232         if (!stream) {
3233                 LOGE("failed to alloc stream");
3234                 return;
3235         }
3236
3237         __mmplayer_get_video_angle(player, NULL, &stream->orientation);
3238
3239         /* set size and timestamp */
3240         mem = gst_buffer_peek_memory(buffer, 0);
3241         stream->length_total = gst_memory_get_sizes(mem, NULL, NULL);
3242         stream->timestamp = (unsigned int)(GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer))); /* nano sec -> mili sec */
3243
3244         /* check zero-copy */
3245         if (player->set_mode.video_zc &&
3246                 player->set_mode.media_packet_video_stream &&
3247                 gst_is_tizen_memory(mem)) {
3248                 __mmplayer_zerocopy_set_stride_elevation_bo(stream, mem);
3249                 stream->internal_buffer = gst_buffer_ref(buffer);
3250         } else { /* sw codec */
3251                 if (!__mmplayer_swcodec_set_stride_elevation(stream))
3252                         goto ERROR;
3253
3254                 if (!__mmplayer_swcodec_set_bo(player, stream, mem))
3255                         goto ERROR;
3256         }
3257
3258         if (!player->video_stream_cb(stream, player->video_stream_cb_user_param)) {
3259                 LOGE("failed to send video stream data.");
3260                 goto ERROR;
3261         }
3262
3263         return;
3264
3265 ERROR:
3266         LOGE("release video stream resource.");
3267         if (gst_is_tizen_memory(mem)) {
3268                 int i = 0;
3269                 for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
3270                         if (stream->bo[i])
3271                                 tbm_bo_unref(stream->bo[i]);
3272                 }
3273
3274                 /* unref gst buffer */
3275                 if (stream->internal_buffer)
3276                         gst_buffer_unref(stream->internal_buffer);
3277         } else {
3278                 if (stream->bo[0])
3279                         _mmplayer_video_stream_release_bo(player, stream->bo[0]);
3280         }
3281         g_free(stream);
3282         return;
3283 }
3284
3285 static void
3286 __mmplayer_gst_set_video360_property(mm_player_t *player)
3287 {
3288         MMPlayerGstElement *videobin = NULL;
3289
3290         MMPLAYER_FENTER();
3291         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->videobin);
3292
3293         videobin = player->pipeline->videobin;
3294
3295         /* Set spatial media metadata and/or user settings to the element.
3296          * */
3297         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3298                         "projection-type", player->video360_metadata.projection_type, NULL);
3299
3300         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3301                         "stereo-mode", player->video360_metadata.stereo_mode, NULL);
3302
3303         if (player->video360_metadata.full_pano_width_pixels &&
3304                         player->video360_metadata.full_pano_height_pixels &&
3305                         player->video360_metadata.cropped_area_image_width &&
3306                         player->video360_metadata.cropped_area_image_height) {
3307                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3308                                 "projection-bounds-top", player->video360_metadata.cropped_area_top,
3309                                 "projection-bounds-bottom", player->video360_metadata.full_pano_height_pixels -
3310                                                 player->video360_metadata.cropped_area_top - player->video360_metadata.cropped_area_image_height,
3311                                 "projection-bounds-left", player->video360_metadata.cropped_area_left,
3312                                 "projection-bounds-right", player->video360_metadata.full_pano_width_pixels -
3313                                                 player->video360_metadata.cropped_area_left - player->video360_metadata.cropped_area_image_width,
3314                                 NULL);
3315         }
3316
3317         if (player->video360_horizontal_fov && player->video360_vertical_fov) {
3318                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3319                                 "horizontal-fov", player->video360_horizontal_fov,
3320                                 "vertical-fov", player->video360_vertical_fov, NULL);
3321         }
3322
3323         if (player->video360_zoom <= VIDEO360_MAX_ZOOM && player->video360_zoom > 1.0f) {
3324                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3325                                 "zoom", 1.0f / player->video360_zoom, NULL);
3326         }
3327
3328         if (player->video360_yaw_radians <= M_PI &&
3329                         player->video360_yaw_radians >= -M_PI &&
3330                         player->video360_pitch_radians <= M_PI_2 &&
3331                         player->video360_pitch_radians >= -M_PI_2) {
3332                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3333                                 "pose-yaw", (int) (player->video360_yaw_radians * 180.0 / M_PI),
3334                                 "pose-pitch", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
3335         } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
3336                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3337                                 "pose-yaw", player->video360_metadata.init_view_heading,
3338                                 "pose-pitch", player->video360_metadata.init_view_pitch, NULL);
3339         }
3340
3341         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
3342                         "passthrough", !player->is_video360_enabled, NULL);
3343
3344
3345         MMPLAYER_FLEAVE();
3346 }
3347
3348 static int
3349 __mmplayer_gst_create_video_filters(mm_player_t *player, MMDisplaySurfaceType surface_type, GList **bucket)
3350 {
3351         gchar *video_csc = "videoconvert"; /* default colorspace converter */
3352         GList *element_bucket = NULL;
3353
3354         MMPLAYER_FENTER();
3355         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
3356
3357         /* create video360 filter */
3358         if (player->is_360_feature_enabled && player->is_content_spherical) {
3359                 LOGD("create video360 element");
3360                 MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_360, "video360", "video-360", TRUE, player);
3361                 __mmplayer_gst_set_video360_property(player);
3362                 goto EXIT;
3363         }
3364
3365         if (surface_type != MM_DISPLAY_SURFACE_OVERLAY || player->set_mode.video_zc) {
3366                 LOGD("skip creating the videoconv and rotator");
3367                 return MM_ERROR_NONE;
3368         }
3369
3370         /* in case of sw codec & overlay surface type, except 360 playback.
3371          * if libav video decoder is selected, videoconvert is required to render the shm wl-buffer which support RGB only via tizenwlsink. */
3372         LOGD("create video converter: %s", video_csc);
3373         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
3374
3375         /* set video rotator */
3376         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
3377
3378 EXIT:
3379         *bucket = element_bucket;
3380         MMPLAYER_FLEAVE();
3381         return MM_ERROR_NONE;
3382
3383 ERROR: /* refer MMPLAYER_CREATE_ELEMENT */
3384         g_list_free(element_bucket);
3385
3386         *bucket = NULL;
3387         MMPLAYER_FLEAVE();
3388         return MM_ERROR_PLAYER_INTERNAL;
3389 }
3390
3391 static gchar*
3392 __mmplayer_get_videosink_factory_name(mm_player_t *player, MMDisplaySurfaceType surface_type)
3393 {
3394         gchar *factory_name = NULL;
3395
3396         switch (surface_type) {
3397         case MM_DISPLAY_SURFACE_OVERLAY:
3398                 if (strlen(player->ini.videosink_element_overlay) > 0)
3399                         factory_name = player->ini.videosink_element_overlay;
3400                 break;
3401         case MM_DISPLAY_SURFACE_NULL:
3402                 if (strlen(player->ini.videosink_element_fake) > 0)
3403                         factory_name = player->ini.videosink_element_fake;
3404                 break;
3405         case MM_DISPLAY_SURFACE_REMOTE:
3406                 if (strlen(player->ini.videosink_element_fake) > 0)
3407                         factory_name = player->ini.videosink_element_fake;
3408                 break;
3409         default:
3410                 LOGE("unidentified surface type");
3411                 break;
3412         }
3413
3414         LOGD("surface_type %d, videosink is %s", surface_type, factory_name);
3415         return factory_name;
3416 }
3417
3418 static int
3419 __mmplayer_gst_set_videosink_property(mm_player_t *player, MMDisplaySurfaceType surface_type)
3420 {
3421         gchar *factory_name = NULL;
3422         MMPlayerGstElement *videobin = NULL;
3423         MMHandleType attrs;
3424
3425         MMPLAYER_FENTER();
3426         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
3427
3428         videobin = player->pipeline->videobin;
3429         factory_name = GST_OBJECT_NAME(gst_element_get_factory(videobin[MMPLAYER_V_SINK].gst));
3430
3431         attrs = MMPLAYER_GET_ATTRS(player);
3432         if (!attrs) {
3433                 LOGE("cannot get content attribute");
3434                 return MM_ERROR_PLAYER_INTERNAL;
3435         }
3436
3437         if (surface_type == MM_DISPLAY_SURFACE_OVERLAY || surface_type == MM_DISPLAY_SURFACE_REMOTE) {
3438                 int gapless = 0;
3439
3440                 if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
3441                         bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
3442                         LOGD("OVERLAY: selected videosink is %s", factory_name);
3443
3444                         if (!use_tbm) {
3445                                 /* support shard memory with S/W codec on HawkP */
3446                                 if (strncmp(factory_name, "tizenwlsink", strlen(factory_name)) == 0) {
3447                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3448                                                 "use-tbm", use_tbm, NULL);
3449                                 }
3450                         }
3451                 } else {
3452                         LOGE("REMOTE : add data probe at videosink");
3453                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3454                                                                                         "sync", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL);
3455                 }
3456
3457                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
3458                 if (gapless > 0) {
3459                         LOGD("disable last-sample");
3460                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
3461                 }
3462
3463                 if (player->set_mode.media_packet_video_stream) {
3464                         int enable = 0;
3465                         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
3466                         if (enable || (surface_type == MM_DISPLAY_SURFACE_REMOTE))
3467                                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
3468
3469                         __mmplayer_add_signal_connection(player,
3470                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3471                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
3472                                                                         "handoff",
3473                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
3474                                                                         (gpointer)player);
3475
3476                         __mmplayer_add_signal_connection(player,
3477                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3478                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
3479                                                                         "preroll-handoff",
3480                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
3481                                                                         (gpointer)player);
3482                 }
3483         }
3484
3485         if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
3486                 return MM_ERROR_PLAYER_INTERNAL;
3487
3488         if (videobin[MMPLAYER_V_SINK].gst) {
3489                 GstPad *sink_pad = NULL;
3490                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
3491                 if (sink_pad) {
3492                         __mmplayer_add_signal_connection(player, G_OBJECT(sink_pad), MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
3493                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), (gpointer)player);
3494                         gst_object_unref(GST_OBJECT(sink_pad));
3495                 } else {
3496                         LOGE("failed to get sink pad from videosink");
3497                 }
3498         }
3499
3500         return MM_ERROR_NONE;
3501 }
3502
3503 /**
3504  * VIDEO PIPELINE
3505  * - video overlay surface(arm/x86) : tizenwlsink
3506  */
3507 static int
3508 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
3509 {
3510         GstPad *pad = NULL;
3511         GList *element_bucket = NULL;
3512         MMPlayerGstElement *first_element = NULL;
3513         MMPlayerGstElement *videobin = NULL;
3514         gchar *videosink_factory_name = NULL;
3515
3516         MMPLAYER_FENTER();
3517         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3518
3519         /* alloc handles */
3520         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
3521         if (!videobin)
3522                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3523
3524         player->pipeline->videobin = videobin;
3525
3526         /* create bin */
3527         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
3528         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
3529         if (!videobin[MMPLAYER_V_BIN].gst) {
3530                 LOGE("failed to create videobin");
3531                 goto ERROR;
3532         }
3533
3534         if (__mmplayer_gst_create_video_filters(player, surface_type, &element_bucket) != MM_ERROR_NONE)
3535                 goto ERROR;
3536
3537         videosink_factory_name = __mmplayer_get_videosink_factory_name(player, surface_type);
3538         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_factory_name, "videosink", TRUE, player);
3539
3540         /* additional setting for sink plug-in */
3541         if (__mmplayer_gst_set_videosink_property(player, surface_type) != MM_ERROR_NONE) {
3542                 LOGE("failed to set video property");
3543                 goto ERROR;
3544         }
3545
3546         /* store it as it's sink element */
3547         __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst);
3548
3549         /* adding created elements to bin */
3550         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
3551                 LOGE("failed to add elements");
3552                 goto ERROR;
3553         }
3554
3555         /* Linking elements in the bucket by added order */
3556         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
3557                 LOGE("failed to link elements");
3558                 goto ERROR;
3559         }
3560
3561         /* get first element's sinkpad for creating ghostpad */
3562         first_element = (MMPlayerGstElement *)element_bucket->data;
3563         if (!first_element) {
3564                 LOGE("failed to get first element from bucket");
3565                 goto ERROR;
3566         }
3567
3568         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
3569         if (!pad) {
3570                 LOGE("failed to get pad from first element");
3571                 goto ERROR;
3572         }
3573
3574         /* create ghostpad */
3575         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
3576         if (!gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
3577                 LOGE("failed to add ghostpad to videobin");
3578                 goto ERROR;
3579         }
3580         gst_object_unref(pad);
3581
3582         /* done. free allocated variables */
3583         g_list_free(element_bucket);
3584
3585         MMPLAYER_FLEAVE();
3586
3587         return MM_ERROR_NONE;
3588
3589 ERROR:
3590         LOGE("ERROR : releasing videobin");
3591         g_list_free(element_bucket);
3592
3593         if (pad)
3594                 gst_object_unref(GST_OBJECT(pad));
3595
3596         /* release videobin with it's childs */
3597         if (videobin[MMPLAYER_V_BIN].gst)
3598                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
3599
3600         MMPLAYER_FREEIF(videobin);
3601         player->pipeline->videobin = NULL;
3602
3603         return MM_ERROR_PLAYER_INTERNAL;
3604 }
3605
3606 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
3607 {
3608         GList *element_bucket = NULL;
3609         MMPlayerGstElement *textbin = player->pipeline->textbin;
3610
3611         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
3612         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
3613         g_object_set(G_OBJECT(textbin[MMPLAYER_T_IDENTITY].gst),
3614                                                         "signal-handoffs", FALSE,
3615                                                         NULL);
3616
3617         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
3618         __mmplayer_add_signal_connection(player,
3619                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
3620                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
3621                                                         "handoff",
3622                                                         G_CALLBACK(__mmplayer_update_subtitle),
3623                                                         (gpointer)player);
3624
3625         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE,
3626                                                 "signal-handoffs", TRUE, "max-lateness", FAKE_SINK_MAX_LATENESS, NULL);
3627
3628         if (!player->play_subtitle) {
3629                 LOGD("add textbin sink as sink element of whole pipeline.\n");
3630                 __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
3631         }
3632
3633         /* adding created elements to bin */
3634         LOGD("adding created elements to bin\n");
3635         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
3636                 LOGE("failed to add elements\n");
3637                 goto ERROR;
3638         }
3639
3640         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
3641         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
3642         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
3643
3644         /* linking elements in the bucket by added order. */
3645         LOGD("Linking elements in the bucket by added order.\n");
3646         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
3647                 LOGE("failed to link elements\n");
3648                 goto ERROR;
3649         }
3650
3651         /* done. free allocated variables */
3652         g_list_free(element_bucket);
3653
3654         if (textbin[MMPLAYER_T_QUEUE].gst) {
3655                 GstPad *pad = NULL;
3656                 GstPad *ghostpad = NULL;
3657
3658                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
3659                 if (!pad) {
3660                         LOGE("failed to get sink pad of text queue");
3661                         goto ERROR;
3662                 }
3663
3664                 ghostpad = gst_ghost_pad_new("text_sink", pad);
3665                 gst_object_unref(pad);
3666
3667                 if (!ghostpad) {
3668                         LOGE("failed to create ghostpad of textbin\n");
3669                         goto ERROR;
3670                 }
3671
3672                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) {
3673                         LOGE("failed to add ghostpad to textbin\n");
3674                         gst_object_unref(ghostpad);
3675                         goto ERROR;
3676                 }
3677         }
3678
3679         return MM_ERROR_NONE;
3680
3681 ERROR:
3682         g_list_free(element_bucket);
3683
3684         if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) {
3685                 LOGE("remove textbin sink from sink list");
3686                 __mmplayer_del_sink(player, textbin[MMPLAYER_T_FAKE_SINK].gst);
3687         }
3688
3689         /* release element at __mmplayer_gst_create_text_sink_bin */
3690         return MM_ERROR_PLAYER_INTERNAL;
3691 }
3692
3693 static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player)
3694 {
3695         MMPlayerGstElement *textbin = NULL;
3696         GList *element_bucket = NULL;
3697         int surface_type = 0;
3698         gint i = 0;
3699
3700         MMPLAYER_FENTER();
3701
3702         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3703
3704         /* alloc handles */
3705         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
3706         if (!textbin) {
3707                 LOGE("failed to allocate memory for textbin\n");
3708                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3709         }
3710
3711         /* create bin */
3712         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
3713         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
3714         if (!textbin[MMPLAYER_T_BIN].gst) {
3715                 LOGE("failed to create textbin\n");
3716                 goto ERROR;
3717         }
3718
3719         /* take it */
3720         player->pipeline->textbin = textbin;
3721
3722         /* fakesink */
3723         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3724         LOGD("surface type for subtitle : %d", surface_type);
3725         switch (surface_type) {
3726         case MM_DISPLAY_SURFACE_OVERLAY:
3727         case MM_DISPLAY_SURFACE_NULL:
3728         case MM_DISPLAY_SURFACE_REMOTE:
3729                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE) {
3730                         LOGE("failed to make plain text elements\n");
3731                         goto ERROR;
3732                 }
3733                 break;
3734         default:
3735                 goto ERROR;
3736                 break;
3737         }
3738
3739         MMPLAYER_FLEAVE();
3740
3741         return MM_ERROR_NONE;
3742
3743 ERROR:
3744
3745         LOGD("ERROR : releasing textbin\n");
3746
3747         g_list_free(element_bucket);
3748
3749         /* release signal */
3750         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
3751
3752         /* release element which are not added to bin */
3753         for (i = 1; i < MMPLAYER_T_NUM; i++) {
3754                 /* NOTE : skip bin */
3755                 if (textbin[i].gst) {
3756                         GstObject* parent = NULL;
3757                         parent = gst_element_get_parent(textbin[i].gst);
3758
3759                         if (!parent) {
3760                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
3761                                 textbin[i].gst = NULL;
3762                         } else {
3763                                 gst_object_unref(GST_OBJECT(parent));
3764                         }
3765                 }
3766         }
3767
3768         /* release textbin with it's childs */
3769         if (textbin[MMPLAYER_T_BIN].gst)
3770                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
3771
3772         MMPLAYER_FREEIF(player->pipeline->textbin);
3773         player->pipeline->textbin = NULL;
3774
3775         MMPLAYER_FLEAVE();
3776         return MM_ERROR_PLAYER_INTERNAL;
3777 }
3778
3779
3780 static int
3781 __mmplayer_gst_create_text_pipeline(mm_player_t* player)
3782 {
3783         MMPlayerGstElement* mainbin = NULL;
3784         MMPlayerGstElement* textbin = NULL;
3785         MMHandleType attrs = 0;
3786         GstElement *subsrc = NULL;
3787         GstElement *subparse = NULL;
3788         gchar *subtitle_uri = NULL;
3789         const gchar *charset = NULL;
3790         GstPad *pad = NULL;
3791
3792         MMPLAYER_FENTER();
3793
3794         /* get mainbin */
3795         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
3796                                                                 player->pipeline &&
3797                                                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
3798
3799         mainbin = player->pipeline->mainbin;
3800
3801         attrs = MMPLAYER_GET_ATTRS(player);
3802         if (!attrs) {
3803                 LOGE("cannot get content attribute\n");
3804                 return MM_ERROR_PLAYER_INTERNAL;
3805         }
3806
3807         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
3808         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
3809                 LOGE("subtitle uri is not proper filepath.\n");
3810                 return MM_ERROR_PLAYER_INVALID_URI;
3811         }
3812
3813         if (!util_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) {
3814                 LOGE("failed to get storage info of subtitle path");
3815                 return MM_ERROR_PLAYER_INVALID_URI;
3816         }
3817
3818         SECURE_LOGD("subtitle file path is [%s].\n", subtitle_uri);
3819
3820         MMPLAYER_SUBTITLE_INFO_LOCK(player);
3821         player->subtitle_language_list = NULL;
3822         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
3823
3824         /* create the subtitle source */
3825         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
3826         if (!subsrc) {
3827                 LOGE("failed to create filesrc element\n");
3828                 goto ERROR;
3829         }
3830         g_object_set(G_OBJECT(subsrc), "location", subtitle_uri, NULL);
3831
3832         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
3833         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
3834
3835         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) {
3836                 LOGW("failed to add queue\n");
3837                 gst_object_unref(mainbin[MMPLAYER_M_SUBSRC].gst);
3838                 mainbin[MMPLAYER_M_SUBSRC].gst = NULL;
3839                 mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_NUM;
3840                 goto ERROR;
3841         }
3842
3843         /* subparse */
3844         subparse = gst_element_factory_make("subparse", "subtitle_parser");
3845         if (!subparse) {
3846                 LOGE("failed to create subparse element\n");
3847                 goto ERROR;
3848         }
3849
3850         charset = util_get_charset(subtitle_uri);
3851         if (charset) {
3852                 LOGD("detected charset is %s\n", charset);
3853                 g_object_set(G_OBJECT(subparse), "subtitle-encoding", charset, NULL);
3854         }
3855
3856         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
3857         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
3858
3859         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) {
3860                 LOGW("failed to add subparse\n");
3861                 gst_object_unref(mainbin[MMPLAYER_M_SUBPARSE].gst);
3862                 mainbin[MMPLAYER_M_SUBPARSE].gst = NULL;
3863                 mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_NUM;
3864                 goto ERROR;
3865         }
3866
3867         if (!gst_element_link_pads(subsrc, "src", subparse, "sink")) {
3868                 LOGW("failed to link subsrc and subparse\n");
3869                 goto ERROR;
3870         }
3871
3872         player->play_subtitle = TRUE;
3873         player->adjust_subtitle_pos = 0;
3874
3875         LOGD("play subtitle using subtitle file\n");
3876
3877         if (player->pipeline->textbin == NULL) {
3878                 if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) {
3879                         LOGE("failed to create text sink bin. continuing without text\n");
3880                         goto ERROR;
3881                 }
3882
3883                 textbin = player->pipeline->textbin;
3884
3885                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(textbin[MMPLAYER_T_BIN].gst))) {
3886                         LOGW("failed to add textbin\n");
3887
3888                         /* release signal */
3889                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
3890
3891                         /* release textbin with it's childs */
3892                         gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
3893                         MMPLAYER_FREEIF(player->pipeline->textbin);
3894                         player->pipeline->textbin = textbin = NULL;
3895                         goto ERROR;
3896                 }
3897
3898                 LOGD("link text input selector and textbin ghost pad");
3899
3900                 player->textsink_linked = 1;
3901                 player->external_text_idx = 0;
3902                 LOGI("player->textsink_linked set to 1\n");
3903         } else {
3904                 textbin = player->pipeline->textbin;
3905                 LOGD("text bin has been created. reuse it.");
3906                 player->external_text_idx = 1;
3907         }
3908
3909         if (!gst_element_link_pads(subparse, "src", textbin[MMPLAYER_T_BIN].gst, "text_sink")) {
3910                 LOGW("failed to link subparse and textbin\n");
3911                 goto ERROR;
3912         }
3913
3914         pad = gst_element_get_static_pad(textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
3915         if (!pad) {
3916                 LOGE("failed to get sink pad from textsink to probe data");
3917                 goto ERROR;
3918         }
3919
3920         gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
3921                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
3922
3923         gst_object_unref(pad);
3924         pad = NULL;
3925
3926         /* create dot. for debugging */
3927         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-with-subtitle");
3928         MMPLAYER_FLEAVE();
3929
3930         return MM_ERROR_NONE;
3931
3932 ERROR:
3933         /* release text pipeline resource */
3934         player->textsink_linked = 0;
3935
3936         /* release signal */
3937         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
3938
3939         if (player->pipeline->textbin) {
3940                 LOGE("remove textbin");
3941
3942                 /* release textbin with it's childs */
3943                 MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
3944                 MMPLAYER_FREEIF(player->pipeline->textbin);
3945                 player->pipeline->textbin = NULL;
3946
3947         }
3948
3949         /* release subtitle elem */
3950         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
3951         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
3952
3953         return MM_ERROR_PLAYER_INTERNAL;
3954 }
3955
3956 gboolean
3957 __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
3958 {
3959         mm_player_t* player = (mm_player_t*) data;
3960         MMMessageParamType msg = {0, };
3961         GstClockTime duration = 0;
3962         gpointer text = NULL;
3963         guint text_size = 0;
3964         gboolean ret = TRUE;
3965         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
3966
3967         MMPLAYER_FENTER();
3968
3969         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3970         MMPLAYER_RETURN_VAL_IF_FAIL(buffer, FALSE);
3971
3972         if (player->is_subtitle_force_drop) {
3973                 LOGW("subtitle is dropped forcedly.");
3974                 return ret;
3975         }
3976
3977         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
3978         text = mapinfo.data;
3979         text_size = mapinfo.size;
3980         duration = GST_BUFFER_DURATION(buffer);
3981
3982         if (player->set_mode.subtitle_off) {
3983                 LOGD("subtitle is OFF.\n");
3984                 return TRUE;
3985         }
3986
3987         if (!text || (text_size == 0)) {
3988                 LOGD("There is no subtitle to be displayed.\n");
3989                 return TRUE;
3990         }
3991
3992         msg.data = (void *) text;
3993         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
3994
3995         LOGD("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data);
3996
3997         MMPLAYER_POST_MSG(player, MM_MESSAGE_UPDATE_SUBTITLE, &msg);
3998         gst_buffer_unmap(buffer, &mapinfo);
3999
4000         MMPLAYER_FLEAVE();
4001
4002         return ret;
4003 }
4004
4005 static GstPadProbeReturn
4006 __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
4007 {
4008         mm_player_t *player = (mm_player_t *) u_data;
4009         GstClockTime cur_timestamp = 0;
4010         gint64 adjusted_timestamp = 0;
4011         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
4012
4013         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
4014
4015         if (player->set_mode.subtitle_off) {
4016                 LOGD("subtitle is OFF.\n");
4017                 return TRUE;
4018         }
4019
4020         if (player->adjust_subtitle_pos == 0) {
4021                 LOGD("nothing to do");
4022                 return TRUE;
4023         }
4024
4025         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
4026         adjusted_timestamp = (gint64) cur_timestamp +((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
4027
4028         if (adjusted_timestamp < 0) {
4029                 LOGD("adjusted_timestamp under zero");
4030                 MMPLAYER_FLEAVE();
4031                 return FALSE;
4032         }
4033
4034         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
4035         LOGD("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
4036                                 GST_TIME_ARGS(cur_timestamp),
4037                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
4038
4039         return GST_PAD_PROBE_OK;
4040 }
4041 static int __mmplayer_gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
4042 {
4043         MMPLAYER_FENTER();
4044
4045         /* check player and subtitlebin are created */
4046         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4047         MMPLAYER_RETURN_VAL_IF_FAIL(player->play_subtitle, MM_ERROR_NOT_SUPPORT_API);
4048
4049         if (position == 0) {
4050                 LOGD("nothing to do\n");
4051                 MMPLAYER_FLEAVE();
4052                 return MM_ERROR_NONE;
4053         }
4054
4055         switch (format) {
4056         case MM_PLAYER_POS_FORMAT_TIME:
4057                 {
4058                         /* check current postion */
4059                         player->adjust_subtitle_pos = position;
4060
4061                         LOGD("save adjust_subtitle_pos in player") ;
4062                 }
4063                 break;
4064
4065         default:
4066                 {
4067                         LOGW("invalid format.\n");
4068                         MMPLAYER_FLEAVE();
4069                         return MM_ERROR_INVALID_ARGUMENT;
4070                 }
4071         }
4072
4073         MMPLAYER_FLEAVE();
4074
4075         return MM_ERROR_NONE;
4076 }
4077
4078 /**
4079  * This function is to create  audio or video pipeline for playing.
4080  *
4081  * @param       player          [in]    handle of player
4082  *
4083  * @return      This function returns zero on success.
4084  * @remark
4085  * @see
4086  */
4087 static int
4088 __mmplayer_gst_create_pipeline(mm_player_t* player)
4089 {
4090         int ret = MM_ERROR_NONE;
4091         MMPlayerGstElement *mainbin = NULL;
4092         MMHandleType attrs = 0;
4093         gint mode = MM_PLAYER_PD_MODE_NONE;
4094
4095         MMPLAYER_FENTER();
4096         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4097
4098         /* get profile attribute */
4099         attrs = MMPLAYER_GET_ATTRS(player);
4100         if (!attrs) {
4101                 LOGE("failed to get content attribute");
4102                 goto INIT_ERROR;
4103         }
4104
4105         /* create pipeline handles */
4106         if (player->pipeline) {
4107                 LOGE("pipeline should be released before create new one");
4108                 goto INIT_ERROR;
4109         }
4110
4111         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0(sizeof(MMPlayerGstPipelineInfo));
4112         if (player->pipeline == NULL)
4113                 goto INIT_ERROR;
4114
4115         /* create mainbin */
4116         mainbin = (MMPlayerGstElement*) g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
4117         if (mainbin == NULL)
4118                 goto INIT_ERROR;
4119
4120         /* create pipeline */
4121         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
4122         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
4123         if (!mainbin[MMPLAYER_M_PIPE].gst) {
4124                 LOGE("failed to create pipeline");
4125                 g_free(mainbin);
4126                 goto INIT_ERROR;
4127         }
4128
4129         player->pipeline->mainbin = mainbin;
4130
4131         /* check pd mode */
4132         mm_attrs_get_int_by_name(attrs, "pd_mode", &mode);
4133         player->pd_mode = mode;
4134
4135         /* create the source and decoder elements */
4136         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
4137                 ret = __mmplayer_gst_build_es_pipeline(player);
4138         } else if (MMPLAYER_IS_HTTP_STREAMING(player) && MMPLAYER_IS_HTTP_PD(player)) {
4139                 ret = __mmplayer_gst_build_pd_pipeline(player);
4140         } else {
4141                 ret = __mmplayer_gst_build_pipeline(player);
4142         }
4143
4144         if (ret != MM_ERROR_NONE) {
4145                 LOGE("failed to create some elements");
4146                 goto INIT_ERROR;
4147         }
4148
4149         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
4150         if (__mmplayer_check_subtitle(player)) {
4151                 if (__mmplayer_gst_create_text_pipeline(player) != MM_ERROR_NONE)
4152                         LOGE("failed to create text pipeline");
4153         }
4154
4155         /* add bus watch */
4156         ret = __mmplayer_gst_add_bus_watch(player);
4157         if (ret != MM_ERROR_NONE) {
4158                 LOGE("failed to add bus watch");
4159                 goto INIT_ERROR;
4160         }
4161
4162         MMPLAYER_FLEAVE();
4163         return MM_ERROR_NONE;
4164
4165 INIT_ERROR:
4166         __mmplayer_gst_destroy_pipeline(player);
4167         return MM_ERROR_PLAYER_INTERNAL;
4168 }
4169
4170 static void
4171 __mmplayer_reset_gapless_state(mm_player_t* player)
4172 {
4173         MMPLAYER_FENTER();
4174         MMPLAYER_RETURN_IF_FAIL(player
4175                 && player->pipeline
4176                 && player->pipeline->audiobin
4177                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
4178
4179         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
4180
4181         MMPLAYER_FLEAVE();
4182         return;
4183 }
4184
4185 static int
4186 __mmplayer_gst_destroy_pipeline(mm_player_t* player)
4187 {
4188         gint timeout = 0;
4189         int ret = MM_ERROR_NONE;
4190
4191         MMPLAYER_FENTER();
4192
4193         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_INVALID_HANDLE);
4194
4195         /* cleanup stuffs */
4196         MMPLAYER_FREEIF(player->type);
4197         player->have_dynamic_pad = FALSE;
4198         player->no_more_pad = FALSE;
4199         player->num_dynamic_pad = 0;
4200         player->demux_pad_index = 0;
4201         player->video_hub_download_mode = 0;
4202
4203         MMPLAYER_SUBTITLE_INFO_LOCK(player);
4204         player->subtitle_language_list = NULL;
4205         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
4206
4207         __mmplayer_reset_gapless_state(player);
4208
4209         if (player->streamer) {
4210                 __mm_player_streaming_deinitialize(player->streamer);
4211                 __mm_player_streaming_destroy(player->streamer);
4212                 player->streamer = NULL;
4213         }
4214
4215         /* cleanup unlinked mime type */
4216         MMPLAYER_FREEIF(player->unlinked_audio_mime);
4217         MMPLAYER_FREEIF(player->unlinked_video_mime);
4218         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
4219
4220         /* cleanup running stuffs */
4221         __mmplayer_cancel_eos_timer(player);
4222
4223         /* cleanup gst stuffs */
4224         if (player->pipeline) {
4225                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
4226                 GstTagList* tag_list = player->pipeline->tag_list;
4227
4228                 /* first we need to disconnect all signal hander */
4229                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
4230
4231                 if (mainbin) {
4232                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4233                         MMPlayerGstElement* videobin = player->pipeline->videobin;
4234                         MMPlayerGstElement* textbin = player->pipeline->textbin;
4235                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
4236                         gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
4237                         gst_object_unref(bus);
4238
4239                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
4240                         ret = __mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout);
4241                         if (ret != MM_ERROR_NONE) {
4242                                 LOGE("fail to change state to NULL\n");
4243                                 return MM_ERROR_PLAYER_INTERNAL;
4244                         }
4245
4246                         LOGW("succeeded in changing state to NULL\n");
4247
4248                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
4249
4250                         /* free fakesink */
4251                         if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
4252                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
4253
4254                         /* free avsysaudiosink
4255                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
4256                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
4257                         */
4258                         MMPLAYER_FREEIF(audiobin);
4259                         MMPLAYER_FREEIF(videobin);
4260                         MMPLAYER_FREEIF(textbin);
4261                         MMPLAYER_FREEIF(mainbin);
4262                 }
4263
4264                 if (tag_list)
4265                         gst_tag_list_free(tag_list);
4266
4267                 MMPLAYER_FREEIF(player->pipeline);
4268         }
4269         MMPLAYER_FREEIF(player->album_art);
4270
4271         if (player->v_stream_caps) {
4272                 gst_caps_unref(player->v_stream_caps);
4273                 player->v_stream_caps = NULL;
4274         }
4275         if (player->a_stream_caps) {
4276                 gst_caps_unref(player->a_stream_caps);
4277                 player->a_stream_caps = NULL;
4278         }
4279
4280         if (player->s_stream_caps) {
4281                 gst_caps_unref(player->s_stream_caps);
4282                 player->s_stream_caps = NULL;
4283         }
4284         __mmplayer_track_destroy(player);
4285
4286         if (player->sink_elements)
4287                 g_list_free(player->sink_elements);
4288         player->sink_elements = NULL;
4289
4290         if (player->bufmgr) {
4291                 tbm_bufmgr_deinit(player->bufmgr);
4292                 player->bufmgr = NULL;
4293         }
4294
4295         LOGW("finished destroy pipeline\n");
4296
4297         MMPLAYER_FLEAVE();
4298
4299         return ret;
4300 }
4301
4302 static int __mmplayer_gst_realize(mm_player_t* player)
4303 {
4304         gint timeout = 0;
4305         int ret = MM_ERROR_NONE;
4306
4307         MMPLAYER_FENTER();
4308
4309         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4310
4311         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
4312
4313         ret = __mmplayer_gst_create_pipeline(player);
4314         if (ret) {
4315                 LOGE("failed to create pipeline\n");
4316                 return ret;
4317         }
4318
4319         /* set pipeline state to READY */
4320         /* NOTE : state change to READY must be performed sync. */
4321         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
4322         ret = __mmplayer_gst_set_state(player,
4323                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
4324
4325         if (ret != MM_ERROR_NONE) {
4326                 /* return error if failed to set state */
4327                 LOGE("failed to set READY state");
4328                 return ret;
4329         }
4330
4331         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
4332
4333         /* create dot before error-return. for debugging */
4334         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-realize");
4335
4336         MMPLAYER_FLEAVE();
4337
4338         return ret;
4339 }
4340
4341 static int __mmplayer_gst_unrealize(mm_player_t* player)
4342 {
4343         int ret = MM_ERROR_NONE;
4344
4345         MMPLAYER_FENTER();
4346
4347         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4348
4349         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
4350         MMPLAYER_PRINT_STATE(player);
4351
4352         /* release miscellaneous information */
4353         __mmplayer_release_misc(player);
4354
4355         /* destroy pipeline */
4356         ret = __mmplayer_gst_destroy_pipeline(player);
4357         if (ret != MM_ERROR_NONE) {
4358                 LOGE("failed to destory pipeline\n");
4359                 return ret;
4360         }
4361
4362         /* release miscellaneous information.
4363            these info needs to be released after pipeline is destroyed. */
4364         __mmplayer_release_misc_post(player);
4365
4366         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
4367
4368         MMPLAYER_FLEAVE();
4369
4370         return ret;
4371 }
4372
4373 static int
4374 __mmplayer_gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param)
4375 {
4376         MMPLAYER_FENTER();
4377
4378         if (!player) {
4379                 LOGW("set_message_callback is called with invalid player handle\n");
4380                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
4381         }
4382
4383         player->msg_cb = callback;
4384         player->msg_cb_param = user_param;
4385
4386         LOGD("msg_cb : %p     msg_cb_param : %p\n", callback, user_param);
4387
4388         MMPLAYER_FLEAVE();
4389
4390         return MM_ERROR_NONE;
4391 }
4392
4393 int __mmplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data)
4394 {
4395         int ret = MM_ERROR_NONE;
4396         char *path = NULL;
4397
4398         MMPLAYER_FENTER();
4399
4400         MMPLAYER_RETURN_VAL_IF_FAIL(uri , FALSE);
4401         MMPLAYER_RETURN_VAL_IF_FAIL(data , FALSE);
4402         MMPLAYER_RETURN_VAL_IF_FAIL((strlen(uri) <= MM_MAX_URL_LEN), FALSE);
4403
4404         memset(data, 0, sizeof(MMPlayerParseProfile));
4405
4406         if (strstr(uri, "es_buff://")) {
4407                 __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_MS_BUFF);
4408         } else if (strstr(uri, "rtsp://") || strstr(uri, "rtsps://") || strstr(uri, "rtspu://")) {
4409                 __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_URL_RTSP);
4410         } else if (strstr(uri, "http://") || strstr(uri, "https://")) {
4411                 gchar *tmp = NULL;
4412                 tmp = g_ascii_strdown(uri, strlen(uri));
4413                 if (tmp && (g_str_has_suffix(tmp, ".ism/manifest") || g_str_has_suffix(tmp, ".isml/manifest")))
4414                         __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_SS);
4415                 else
4416                         __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_URL_HTTP);
4417                 g_free(tmp);
4418         } else if (strstr(uri, "mms://")) {
4419                 __mmplayer_copy_uri_and_set_type(data, uri, MM_PLAYER_URI_TYPE_URL_MMS);
4420         } else if ((path = strstr(uri, "mem://"))) {
4421                 ret = __mmplayer_set_mem_uri(data, path, param);
4422         } else {
4423                 ret = __mmplayer_set_file_uri(data, uri);
4424         }
4425
4426         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE)
4427                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
4428         else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION)
4429                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
4430
4431         /* dump parse result */
4432         SECURE_LOGW("incoming uri : %s\n", uri);
4433         LOGD("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
4434                 data->uri_type, data->input_mem.buf, data->input_mem.len, data->urgent);
4435
4436         MMPLAYER_FLEAVE();
4437
4438         return ret;
4439 }
4440
4441 static gboolean
4442 __mmplayer_can_do_interrupt(mm_player_t *player)
4443 {
4444         if (!player || !player->pipeline || !player->attrs) {
4445                 LOGW("not initialized");
4446                 goto FAILED;
4447         }
4448
4449         if (player->audio_stream_render_cb) {
4450                 LOGW("not support in pcm extraction mode");
4451                 goto FAILED;
4452         }
4453
4454         /* check if seeking */
4455         if (player->seek_state != MMPLAYER_SEEK_NONE) {
4456                 MMMessageParamType msg_param;
4457                 memset(&msg_param, 0, sizeof(MMMessageParamType));
4458                 msg_param.code = MM_ERROR_PLAYER_SEEK;
4459                 player->seek_state = MMPLAYER_SEEK_NONE;
4460                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
4461                 goto FAILED;
4462         }
4463
4464         /* check other thread */
4465         if (!MMPLAYER_CMD_TRYLOCK(player)) {
4466                 LOGW("locked already, cmd state : %d", player->cmd);
4467
4468                 /* check application command */
4469                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) {
4470                         LOGW("playing.. should wait cmd lock then, will be interrupted");
4471
4472                         /* lock will be released at mrp_resource_release_cb() */
4473                         MMPLAYER_CMD_LOCK(player);
4474                         goto INTERRUPT;
4475                 }
4476                 LOGW("nothing to do");
4477                 goto FAILED;
4478         } else {
4479                 LOGW("can interrupt immediately");
4480                 goto INTERRUPT;
4481         }
4482
4483 FAILED:    /* with CMD UNLOCKED */
4484         return FALSE;
4485
4486 INTERRUPT: /* with CMD LOCKED, released at mrp_resource_release_cb() */
4487         return TRUE;
4488 }
4489
4490 static int
4491 __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
4492                 void *user_data)
4493 {
4494         mm_player_t *player = NULL;
4495
4496         MMPLAYER_FENTER();
4497
4498         if (user_data == NULL) {
4499                 LOGE("- user_data is null\n");
4500                 return FALSE;
4501         }
4502         player = (mm_player_t *)user_data;
4503
4504         /* do something to release resource here.
4505          * player stop and interrupt forwarding */
4506         if (!__mmplayer_can_do_interrupt(player)) {
4507                 LOGW("no need to interrupt, so leave");
4508         } else {
4509                 MMMessageParamType msg = {0, };
4510                 gint64 pos = 0;
4511
4512                 player->interrupted_by_resource = TRUE;
4513
4514                 /* get last play position */
4515                 if (_mmplayer_get_position((MMHandleType)player, &pos) != MM_ERROR_NONE) {
4516                         LOGW("failed to get play position.");
4517                 } else {
4518                         msg.union_type = MM_MSG_UNION_TIME;
4519                         msg.time.elapsed = pos;
4520                         MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg);
4521                 }
4522                 LOGD("video resource conflict so, resource will be freed by unrealizing");
4523                 if (_mmplayer_unrealize((MMHandleType)player))
4524                         LOGW("failed to unrealize");
4525
4526                 /* lock is called in __mmplayer_can_do_interrupt() */
4527                 MMPLAYER_CMD_UNLOCK(player);
4528         }
4529
4530         if (res == player->video_overlay_resource)
4531                 player->video_overlay_resource = FALSE;
4532         else
4533                 player->video_decoder_resource = FALSE;
4534
4535         MMPLAYER_FLEAVE();
4536
4537         return FALSE;
4538 }
4539
4540 static void
4541 __mmplayer_initialize_video_roi(mm_player_t *player)
4542 {
4543         player->video_roi.scale_x = 0.0;
4544         player->video_roi.scale_y = 0.0;
4545         player->video_roi.scale_width = 1.0;
4546         player->video_roi.scale_height = 1.0;
4547 }
4548
4549 int
4550 _mmplayer_create_player(MMHandleType handle)
4551 {
4552         int ret = MM_ERROR_PLAYER_INTERNAL;
4553         bool enabled = false;
4554
4555         mm_player_t* player = MM_PLAYER_CAST(handle);
4556
4557         MMPLAYER_FENTER();
4558
4559         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4560
4561         /* initialize player state */
4562         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
4563         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
4564         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
4565         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
4566
4567         /* check current state */
4568         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_CREATE);
4569
4570         /* construct attributes */
4571         player->attrs = _mmplayer_construct_attribute(handle);
4572
4573         if (!player->attrs) {
4574                 LOGE("Failed to construct attributes\n");
4575                 return ret;
4576         }
4577
4578         /* initialize gstreamer with configured parameter */
4579         if (!__mmplayer_init_gstreamer(player)) {
4580                 LOGE("Initializing gstreamer failed\n");
4581                 _mmplayer_deconstruct_attribute(handle);
4582                 return ret;
4583         }
4584
4585         /* create lock. note that g_tread_init() has already called in gst_init() */
4586         g_mutex_init(&player->fsink_lock);
4587
4588         /* create update tag lock */
4589         g_mutex_init(&player->update_tag_lock);
4590
4591         /* create gapless play mutex */
4592         g_mutex_init(&player->gapless_play_thread_mutex);
4593
4594         /* create gapless play cond */
4595         g_cond_init(&player->gapless_play_thread_cond);
4596
4597         /* create gapless play thread */
4598         player->gapless_play_thread =
4599                 g_thread_try_new("gapless_play_thread", __mmplayer_gapless_play_thread, (gpointer)player, NULL);
4600         if (!player->gapless_play_thread) {
4601                 LOGE("failed to create gapless play thread");
4602                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
4603                 g_mutex_clear(&player->gapless_play_thread_mutex);
4604                 g_cond_clear(&player->gapless_play_thread_cond);
4605                 goto ERROR;
4606         }
4607
4608         player->bus_msg_q = g_queue_new();
4609         if (!player->bus_msg_q) {
4610                 LOGE("failed to create queue for bus_msg");
4611                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
4612                 goto ERROR;
4613         }
4614
4615         ret = _mmplayer_initialize_video_capture(player);
4616         if (ret != MM_ERROR_NONE) {
4617                 LOGE("failed to initialize video capture\n");
4618                 goto ERROR;
4619         }
4620
4621         /* initialize resource manager */
4622         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_create(
4623                         MM_RESOURCE_MANAGER_APP_CLASS_MEDIA, __resource_release_cb, player,
4624                         &player->resource_manager)) {
4625                 LOGE("failed to initialize resource manager\n");
4626                 ret = MM_ERROR_PLAYER_INTERNAL;
4627                 goto ERROR;
4628         }
4629
4630         if (MMPLAYER_IS_HTTP_PD(player)) {
4631                 player->pd_downloader = NULL;
4632                 player->pd_file_save_path = NULL;
4633         }
4634
4635         /* create video bo lock and cond */
4636         g_mutex_init(&player->video_bo_mutex);
4637         g_cond_init(&player->video_bo_cond);
4638
4639         /* create media stream callback mutex */
4640         g_mutex_init(&player->media_stream_cb_lock);
4641
4642         /* create subtitle info lock and cond */
4643         g_mutex_init(&player->subtitle_info_mutex);
4644         g_cond_init(&player->subtitle_info_cond);
4645
4646         player->streaming_type = STREAMING_SERVICE_NONE;
4647
4648         /* give default value of audio effect setting */
4649         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
4650         player->sound.rg_enable = false;
4651         player->playback_rate = DEFAULT_PLAYBACK_RATE;
4652
4653         player->play_subtitle = FALSE;
4654         player->has_closed_caption = FALSE;
4655         player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
4656         player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
4657         player->pending_resume = FALSE;
4658         if (player->ini.dump_element_keyword[0][0] == '\0')
4659                 player->ini.set_dump_element_flag = FALSE;
4660         else
4661                 player->ini.set_dump_element_flag = TRUE;
4662
4663         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
4664         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
4665         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
4666
4667         /* Set video360 settings to their defaults for just-created player.
4668          * */
4669
4670         player->is_360_feature_enabled = FALSE;
4671         if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(FEATURE_NAME_SPHERICAL_VIDEO, &enabled)) {
4672                 LOGI("spherical feature info: %d", enabled);
4673                 if (enabled)
4674                         player->is_360_feature_enabled = TRUE;
4675         } else {
4676                 LOGE("failed to get spherical feature info");
4677         }
4678
4679         player->is_content_spherical = FALSE;
4680         player->is_video360_enabled = TRUE;
4681         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
4682         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
4683         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
4684         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
4685         player->video360_zoom = 1.0f;
4686         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
4687         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
4688
4689         __mmplayer_initialize_video_roi(player);
4690
4691         /* set player state to null */
4692         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
4693         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
4694
4695         return MM_ERROR_NONE;
4696
4697 ERROR:
4698         /* free lock */
4699         g_mutex_clear(&player->fsink_lock);
4700
4701         /* free update tag lock */
4702         g_mutex_clear(&player->update_tag_lock);
4703
4704         g_queue_free(player->bus_msg_q);
4705
4706         /* free gapless play thread */
4707         if (player->gapless_play_thread) {
4708                 MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(player);
4709                 player->gapless_play_thread_exit = TRUE;
4710                 MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
4711                 MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
4712
4713                 g_thread_join(player->gapless_play_thread);
4714                 player->gapless_play_thread = NULL;
4715
4716                 g_mutex_clear(&player->gapless_play_thread_mutex);
4717                 g_cond_clear(&player->gapless_play_thread_cond);
4718         }
4719
4720         /* release attributes */
4721         _mmplayer_deconstruct_attribute(handle);
4722
4723         MMPLAYER_FLEAVE();
4724
4725         return ret;
4726 }
4727
4728 static gboolean
4729 __mmplayer_init_gstreamer(mm_player_t* player)
4730 {
4731         static gboolean initialized = FALSE;
4732         static const int max_argc = 50;
4733         gint* argc = NULL;
4734         gchar** argv = NULL;
4735         gchar** argv2 = NULL;
4736         GError *err = NULL;
4737         int i = 0;
4738         int arg_count = 0;
4739
4740         if (initialized) {
4741                 LOGD("gstreamer already initialized.\n");
4742                 return TRUE;
4743         }
4744
4745         /* alloc */
4746         argc = malloc(sizeof(int));
4747         argv = malloc(sizeof(gchar*) * max_argc);
4748         argv2 = malloc(sizeof(gchar*) * max_argc);
4749
4750         if (!argc || !argv || !argv2)
4751                 goto ERROR;
4752
4753         memset(argv, 0, sizeof(gchar*) * max_argc);
4754         memset(argv2, 0, sizeof(gchar*) * max_argc);
4755
4756         /* add initial */
4757         *argc = 1;
4758         argv[0] = g_strdup("mmplayer");
4759
4760         /* add gst_param */
4761         for (i = 0; i < 5; i++) {
4762                 /* FIXIT : num of param is now fixed to 5. make it dynamic */
4763                 if (strlen(player->ini.gst_param[i]) > 0) {
4764                         argv[*argc] = g_strdup(player->ini.gst_param[i]);
4765                         (*argc)++;
4766                 }
4767         }
4768
4769         /* we would not do fork for scanning plugins */
4770         argv[*argc] = g_strdup("--gst-disable-registry-fork");
4771         (*argc)++;
4772
4773         /* check disable registry scan */
4774         if (player->ini.skip_rescan) {
4775                 argv[*argc] = g_strdup("--gst-disable-registry-update");
4776                 (*argc)++;
4777         }
4778
4779         /* check disable segtrap */
4780         if (player->ini.disable_segtrap) {
4781                 argv[*argc] = g_strdup("--gst-disable-segtrap");
4782                 (*argc)++;
4783         }
4784
4785         LOGD("initializing gstreamer with following parameter\n");
4786         LOGD("argc : %d\n", *argc);
4787         arg_count = *argc;
4788
4789         for (i = 0; i < arg_count; i++) {
4790                 argv2[i] = argv[i];
4791                 LOGD("argv[%d] : %s\n", i, argv2[i]);
4792         }
4793
4794         /* initializing gstreamer */
4795         if (!gst_init_check(argc, &argv, &err)) {
4796                 LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
4797                 if (err)
4798                         g_error_free(err);
4799
4800                 goto ERROR;
4801         }
4802         /* release */
4803         for (i = 0; i < arg_count; i++) {
4804                 //LOGD("release - argv[%d] : %s\n", i, argv2[i]);
4805                 MMPLAYER_FREEIF(argv2[i]);
4806         }
4807
4808         MMPLAYER_FREEIF(argv);
4809         MMPLAYER_FREEIF(argv2);
4810         MMPLAYER_FREEIF(argc);
4811
4812         /* done */
4813         initialized = TRUE;
4814
4815         return TRUE;
4816
4817 ERROR:
4818
4819         /* release */
4820         for (i = 0; i < arg_count; i++) {
4821                 LOGD("free[%d] : %s\n", i, argv2[i]);
4822                 MMPLAYER_FREEIF(argv2[i]);
4823         }
4824
4825         MMPLAYER_FREEIF(argv);
4826         MMPLAYER_FREEIF(argv2);
4827         MMPLAYER_FREEIF(argc);
4828
4829         return FALSE;
4830 }
4831
4832 int
4833 __mmplayer_destroy_streaming_ext(mm_player_t* player)
4834 {
4835         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4836
4837         if (player->pd_downloader || MMPLAYER_IS_HTTP_PD(player)) {
4838                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
4839                 MMPLAYER_FREEIF(player->pd_file_save_path);
4840         }
4841
4842         return MM_ERROR_NONE;
4843 }
4844
4845 static void
4846 __mmplayer_check_async_state_transition(mm_player_t* player)
4847 {
4848         GstState element_state = GST_STATE_VOID_PENDING;
4849         GstState element_pending_state = GST_STATE_VOID_PENDING;
4850         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
4851         GstElement * element = NULL;
4852         gboolean async = FALSE;
4853
4854         /* check player handle */
4855         MMPLAYER_RETURN_IF_FAIL(player &&
4856                                                 player->pipeline &&
4857                                                 player->pipeline->mainbin &&
4858                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
4859
4860         if (player->attrs)
4861                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
4862
4863         if (!MMPLAYER_IS_MS_BUFF_SRC(player) && (async == FALSE)) {
4864                 LOGD("don't need to check the pipeline state");
4865                 return;
4866         }
4867
4868         MMPLAYER_PRINT_STATE(player);
4869
4870         /* wait for state transition */
4871         element = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
4872         ret = gst_element_get_state(element, &element_state, &element_pending_state, 1*GST_SECOND);
4873
4874         if (ret == GST_STATE_CHANGE_FAILURE) {
4875                 LOGE(" [%s] state : %s   pending : %s \n",
4876                         GST_ELEMENT_NAME(element),
4877                         gst_element_state_get_name(element_state),
4878                         gst_element_state_get_name(element_pending_state));
4879
4880                 /* dump state of all element */
4881                 __mmplayer_dump_pipeline_state(player);
4882
4883                 return;
4884         }
4885
4886         LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
4887         return;
4888 }
4889
4890 int
4891 _mmplayer_destroy(MMHandleType handle)
4892 {
4893         mm_player_t* player = MM_PLAYER_CAST(handle);
4894
4895         MMPLAYER_FENTER();
4896
4897         /* check player handle */
4898         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4899
4900         /* destroy can called at anytime */
4901         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_DESTROY);
4902
4903         /* check async state transition */
4904         __mmplayer_check_async_state_transition(player);
4905
4906         __mmplayer_destroy_streaming_ext(player);
4907
4908         /* release gapless play thread */
4909         if (player->gapless_play_thread) {
4910                 MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(player);
4911                 player->gapless_play_thread_exit = TRUE;
4912                 MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
4913                 MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(player);
4914
4915                 LOGD("waitting for gapless play thread exit\n");
4916                 g_thread_join(player->gapless_play_thread);
4917                 g_mutex_clear(&player->gapless_play_thread_mutex);
4918                 g_cond_clear(&player->gapless_play_thread_cond);
4919                 LOGD("gapless play thread released\n");
4920         }
4921
4922         _mmplayer_release_video_capture(player);
4923
4924         /* de-initialize resource manager */
4925         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_destroy(
4926                         player->resource_manager))
4927                 LOGE("failed to deinitialize resource manager\n");
4928
4929         /* release pipeline */
4930         if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
4931                 LOGE("failed to destory pipeline\n");
4932                 return MM_ERROR_PLAYER_INTERNAL;
4933         }
4934
4935         g_queue_free(player->bus_msg_q);
4936
4937         /* release subtitle info lock and cond */
4938         g_mutex_clear(&player->subtitle_info_mutex);
4939         g_cond_clear(&player->subtitle_info_cond);
4940
4941         __mmplayer_release_dump_list(player->dump_list);
4942
4943         /* release miscellaneous information */
4944         __mmplayer_release_misc(player);
4945
4946         /* release miscellaneous information.
4947            these info needs to be released after pipeline is destroyed. */
4948         __mmplayer_release_misc_post(player);
4949
4950         /* release attributes */
4951         _mmplayer_deconstruct_attribute(handle);
4952
4953         /* release lock */
4954         g_mutex_clear(&player->fsink_lock);
4955
4956         /* release lock */
4957         g_mutex_clear(&player->update_tag_lock);
4958
4959         /* release video bo lock and cond */
4960         g_mutex_clear(&player->video_bo_mutex);
4961         g_cond_clear(&player->video_bo_cond);
4962
4963         /* release media stream callback lock */
4964         g_mutex_clear(&player->media_stream_cb_lock);
4965
4966         MMPLAYER_FLEAVE();
4967
4968         return MM_ERROR_NONE;
4969 }
4970
4971 int
4972 __mmplayer_realize_streaming_ext(mm_player_t* player)
4973 {
4974         int ret = MM_ERROR_NONE;
4975
4976         MMPLAYER_FENTER();
4977         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4978
4979         if (MMPLAYER_IS_HTTP_PD(player)) {
4980                 gboolean bret = FALSE;
4981
4982                 player->pd_downloader = _mmplayer_create_pd_downloader();
4983                 if (!player->pd_downloader) {
4984                         LOGE("Unable to create PD Downloader...");
4985                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
4986                 }
4987
4988                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
4989
4990                 if (FALSE == bret) {
4991                         LOGE("Unable to create PD Downloader...");
4992                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
4993                 }
4994         }
4995
4996         MMPLAYER_FLEAVE();
4997         return ret;
4998 }
4999
5000 int
5001 _mmplayer_realize(MMHandleType hplayer)
5002 {
5003         mm_player_t* player = (mm_player_t*)hplayer;
5004         char *uri = NULL;
5005         void *param = NULL;
5006         MMHandleType attrs = 0;
5007         int ret = MM_ERROR_NONE;
5008
5009         MMPLAYER_FENTER();
5010
5011         /* check player handle */
5012         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5013
5014         /* check current state */
5015         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_REALIZE);
5016
5017         attrs = MMPLAYER_GET_ATTRS(player);
5018         if (!attrs) {
5019                 LOGE("fail to get attributes.\n");
5020                 return MM_ERROR_PLAYER_INTERNAL;
5021         }
5022         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
5023         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
5024
5025         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_NONE) {
5026                 ret = __mmplayer_parse_profile((const char*)uri, param, &player->profile);
5027
5028                 if (ret != MM_ERROR_NONE) {
5029                         LOGE("failed to parse profile\n");
5030                         return ret;
5031                 }
5032         }
5033
5034         if (uri && (strstr(uri, "es_buff://"))) {
5035                 if (strstr(uri, "es_buff://push_mode"))
5036                         player->es_player_push_mode = TRUE;
5037                 else
5038                         player->es_player_push_mode = FALSE;
5039         }
5040
5041         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS) {
5042                 LOGW("mms protocol is not supported format.\n");
5043                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
5044         }
5045
5046         if (MMPLAYER_IS_HTTP_PD(player))
5047                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_PD_STATE_CHANGE_TIME;
5048         else if (MMPLAYER_IS_STREAMING(player))
5049                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
5050         else
5051                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
5052
5053         player->smooth_streaming = FALSE;
5054         player->videodec_linked  = 0;
5055         player->videosink_linked = 0;
5056         player->audiodec_linked  = 0;
5057         player->audiosink_linked = 0;
5058         player->textsink_linked = 0;
5059         player->is_external_subtitle_present = FALSE;
5060         player->is_external_subtitle_added_now = FALSE;
5061         player->is_subtitle_off = FALSE; /* set the subtitle ON default */
5062         player->video360_metadata.is_spherical = -1;
5063         player->is_openal_plugin_used = FALSE;
5064         player->demux_pad_index = 0;
5065         player->subtitle_language_list = NULL;
5066         player->is_subtitle_force_drop = FALSE;
5067         player->last_multiwin_status = FALSE;
5068
5069         __mmplayer_track_initialize(player);
5070         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
5071
5072         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL)) {
5073                 player->streamer = __mm_player_streaming_create();
5074                 __mm_player_streaming_initialize(player->streamer);
5075         }
5076
5077         /* realize pipeline */
5078         ret = __mmplayer_gst_realize(player);
5079         if (ret != MM_ERROR_NONE)
5080                 LOGE("fail to realize the player.\n");
5081         else
5082                 ret = __mmplayer_realize_streaming_ext(player);
5083
5084         MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
5085
5086         MMPLAYER_FLEAVE();
5087
5088         return ret;
5089 }
5090
5091 int
5092 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
5093 {
5094         MMPLAYER_FENTER();
5095         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5096
5097         /* destroy can called at anytime */
5098         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
5099                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
5100
5101         MMPLAYER_FLEAVE();
5102         return MM_ERROR_NONE;
5103 }
5104
5105 int
5106 _mmplayer_unrealize(MMHandleType hplayer)
5107 {
5108         mm_player_t* player = (mm_player_t*)hplayer;
5109         int ret = MM_ERROR_NONE;
5110
5111         MMPLAYER_FENTER();
5112
5113         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5114
5115         MMPLAYER_CMD_UNLOCK(player);
5116         /* destroy the gst bus msg thread which is created during realize.
5117            this funct have to be called before getting cmd lock. */
5118         __mmplayer_bus_msg_thread_destroy(player);
5119         MMPLAYER_CMD_LOCK(player);
5120
5121         /* check current state */
5122         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_UNREALIZE);
5123
5124         /* check async state transition */
5125         __mmplayer_check_async_state_transition(player);
5126
5127         __mmplayer_unrealize_streaming_ext(player);
5128
5129         /* unrealize pipeline */
5130         ret = __mmplayer_gst_unrealize(player);
5131
5132         /* set asm stop if success */
5133         if (MM_ERROR_NONE == ret) {
5134                 if (!player->interrupted_by_resource) {
5135                         if (player->video_decoder_resource != NULL) {
5136                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
5137                                                 player->video_decoder_resource);
5138                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
5139                                         LOGE("failed to mark decoder resource for release, ret(0x%x)\n", ret);
5140                                 else
5141                                         player->video_decoder_resource = NULL;
5142                         }
5143
5144                         if (player->video_overlay_resource != NULL) {
5145                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
5146                                                 player->video_overlay_resource);
5147                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
5148                                         LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
5149                                 else
5150                                         player->video_overlay_resource = NULL;
5151                         }
5152
5153                         ret = mm_resource_manager_commit(player->resource_manager);
5154                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
5155                                 LOGE("failed to commit resource releases, ret(0x%x)\n", ret);
5156                 }
5157         } else
5158                 LOGE("failed and don't change asm state to stop");
5159
5160         MMPLAYER_FLEAVE();
5161
5162         return ret;
5163 }
5164
5165 int
5166 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param)
5167 {
5168         mm_player_t* player = (mm_player_t*)hplayer;
5169
5170         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5171
5172         return __mmplayer_gst_set_message_callback(player, callback, user_param);
5173 }
5174
5175 int
5176 _mmplayer_get_state(MMHandleType hplayer, int* state)
5177 {
5178         mm_player_t *player = (mm_player_t*)hplayer;
5179
5180         MMPLAYER_RETURN_VAL_IF_FAIL(state, MM_ERROR_INVALID_ARGUMENT);
5181
5182         *state = MMPLAYER_CURRENT_STATE(player);
5183
5184         return MM_ERROR_NONE;
5185 }
5186
5187
5188 int
5189 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume)
5190 {
5191         mm_player_t* player = (mm_player_t*) hplayer;
5192         GstElement* vol_element = NULL;
5193         int i = 0;
5194
5195         MMPLAYER_FENTER();
5196
5197         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5198
5199         LOGD("volume [L]=%f:[R]=%f\n",
5200                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
5201
5202         /* invalid factor range or not */
5203         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++) {
5204                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
5205                         LOGE("Invalid factor!(valid factor:0~1.0)\n");
5206                         return MM_ERROR_INVALID_ARGUMENT;
5207                 }
5208         }
5209
5210         /* not support to set other value into each channel */
5211         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
5212                 return MM_ERROR_INVALID_ARGUMENT;
5213
5214         /* Save volume to handle. Currently the first array element will be saved. */
5215         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
5216
5217         /* check pipeline handle */
5218         if (!player->pipeline || !player->pipeline->audiobin) {
5219                 LOGD("audiobin is not created yet\n");
5220                 LOGD("but, current stored volume will be set when it's created.\n");
5221
5222                 /* NOTE : stored volume will be used in create_audiobin
5223                  * returning MM_ERROR_NONE here makes application to able to
5224                  * set volume at anytime.
5225                  */
5226                 return MM_ERROR_NONE;
5227         }
5228
5229         /* setting volume to volume element */
5230         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
5231
5232         if (vol_element) {
5233                 LOGD("volume is set [%f]\n", player->sound.volume);
5234                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
5235         }
5236
5237         MMPLAYER_FLEAVE();
5238
5239         return MM_ERROR_NONE;
5240 }
5241
5242
5243 int
5244 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
5245 {
5246         mm_player_t* player = (mm_player_t*) hplayer;
5247         int i = 0;
5248
5249         MMPLAYER_FENTER();
5250
5251         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5252         MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
5253
5254         /* returning stored volume */
5255         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
5256                 volume->level[i] = player->sound.volume;
5257
5258         MMPLAYER_FLEAVE();
5259
5260         return MM_ERROR_NONE;
5261 }
5262
5263 int
5264 _mmplayer_set_mute(MMHandleType hplayer, int mute)
5265 {
5266         mm_player_t* player = (mm_player_t*) hplayer;
5267         GstElement* vol_element = NULL;
5268
5269         MMPLAYER_FENTER();
5270
5271         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5272
5273         /* mute value shoud 0 or 1 */
5274         if (mute != 0 && mute != 1) {
5275                 LOGE("bad mute value\n");
5276
5277                 /* FIXIT : definitly, we need _BAD_PARAM error code */
5278                 return MM_ERROR_INVALID_ARGUMENT;
5279         }
5280
5281         player->sound.mute = mute;
5282
5283         /* just hold mute value if pipeline is not ready */
5284         if (!player->pipeline || !player->pipeline->audiobin) {
5285                 LOGD("pipeline is not ready. holding mute value\n");
5286                 return MM_ERROR_NONE;
5287         }
5288
5289         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
5290
5291         /* NOTE : volume will only created when the bt is enabled */
5292         if (vol_element) {
5293                 LOGD("mute : %d\n", mute);
5294                 g_object_set(vol_element, "mute", mute, NULL);
5295         } else
5296                 LOGD("volume elemnet is not created. using volume in audiosink\n");
5297
5298         MMPLAYER_FLEAVE();
5299
5300         return MM_ERROR_NONE;
5301 }
5302
5303 int
5304 _mmplayer_get_mute(MMHandleType hplayer, int* pmute)
5305 {
5306         mm_player_t* player = (mm_player_t*) hplayer;
5307
5308         MMPLAYER_FENTER();
5309
5310         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5311         MMPLAYER_RETURN_VAL_IF_FAIL(pmute, MM_ERROR_INVALID_ARGUMENT);
5312
5313         /* just hold mute value if pipeline is not ready */
5314         if (!player->pipeline || !player->pipeline->audiobin) {
5315                 LOGD("pipeline is not ready. returning stored value\n");
5316                 *pmute = player->sound.mute;
5317                 return MM_ERROR_NONE;
5318         }
5319
5320         *pmute = player->sound.mute;
5321
5322         MMPLAYER_FLEAVE();
5323
5324         return MM_ERROR_NONE;
5325 }
5326
5327 int
5328 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
5329 {
5330         mm_player_t* player = (mm_player_t*) hplayer;
5331
5332         MMPLAYER_FENTER();
5333
5334         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5335
5336         player->video_stream_changed_cb = callback;
5337         player->video_stream_changed_cb_user_param = user_param;
5338         LOGD("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
5339
5340         MMPLAYER_FLEAVE();
5341
5342         return MM_ERROR_NONE;
5343 }
5344
5345 int
5346 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
5347 {
5348         mm_player_t* player = (mm_player_t*) hplayer;
5349
5350         MMPLAYER_FENTER();
5351
5352         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5353
5354         player->audio_stream_changed_cb = callback;
5355         player->audio_stream_changed_cb_user_param = user_param;
5356         LOGD("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
5357
5358         MMPLAYER_FLEAVE();
5359
5360         return MM_ERROR_NONE;
5361 }
5362
5363 int
5364 _mmplayer_set_audiostream_cb(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback callback, void *user_param)
5365 {
5366         mm_player_t *player = (mm_player_t*) hplayer;
5367
5368         MMPLAYER_FENTER();
5369
5370         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5371
5372         player->audio_stream_render_cb = callback;
5373         player->audio_stream_cb_user_param = user_param;
5374         player->audio_stream_sink_sync = sync;
5375         LOGD("handle: %p, cb: %p, sync: %d", player, player->audio_stream_render_cb, player->audio_stream_sink_sync);
5376
5377         MMPLAYER_FLEAVE();
5378
5379         return MM_ERROR_NONE;
5380 }
5381
5382 int
5383 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param)
5384 {
5385         mm_player_t* player = (mm_player_t*) hplayer;
5386
5387         MMPLAYER_FENTER();
5388
5389         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5390
5391         if (callback && !player->bufmgr)
5392                 player->bufmgr = tbm_bufmgr_init(-1);
5393
5394         player->set_mode.media_packet_video_stream = (callback) ? TRUE : FALSE;
5395         player->video_stream_cb = callback;
5396         player->video_stream_cb_user_param = user_param;
5397
5398         LOGD("Stream cb Handle value is %p : %p, enable:%d\n", player, player->video_stream_cb, player->set_mode.media_packet_video_stream);
5399
5400         MMPLAYER_FLEAVE();
5401
5402         return MM_ERROR_NONE;
5403 }
5404
5405 static int
5406 __mmplayer_start_streaming_ext(mm_player_t *player)
5407 {
5408         gint ret = MM_ERROR_NONE;
5409
5410         MMPLAYER_FENTER();
5411         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5412
5413         if (MMPLAYER_IS_HTTP_PD(player)) {
5414                 if (!player->pd_downloader) {
5415                         ret = __mmplayer_realize_streaming_ext(player);
5416
5417                         if (ret != MM_ERROR_NONE) {
5418                                 LOGE("failed to realize streaming ext\n");
5419                                 return ret;
5420                         }
5421                 }
5422
5423                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI) {
5424                         ret = _mmplayer_start_pd_downloader((MMHandleType)player);
5425                         if (!ret) {
5426                                 LOGE("ERROR while starting PD...\n");
5427                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
5428                         }
5429                         ret = MM_ERROR_NONE;
5430                 }
5431         }
5432
5433         MMPLAYER_FLEAVE();
5434         return ret;
5435 }
5436
5437 int
5438 _mmplayer_start(MMHandleType hplayer)
5439 {
5440         mm_player_t* player = (mm_player_t*) hplayer;
5441         gint ret = MM_ERROR_NONE;
5442
5443         MMPLAYER_FENTER();
5444
5445         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5446
5447         /* check current state */
5448         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_START);
5449
5450         /* PD - start streaming */
5451         ret = __mmplayer_start_streaming_ext(player);
5452         if (ret != MM_ERROR_NONE) {
5453                 LOGE("failed to start streaming ext 0x%X", ret);
5454                 return ret;
5455         }
5456
5457         /* start pipeline */
5458         ret = __mmplayer_gst_start(player);
5459         if (ret != MM_ERROR_NONE)
5460                 LOGE("failed to start player.\n");
5461
5462         if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
5463                 LOGD("force playing start even during buffering");
5464                 player->streamer->buffering_state = MM_PLAYER_BUFFERING_ABORT;
5465         }
5466
5467         MMPLAYER_FLEAVE();
5468
5469         return ret;
5470 }
5471
5472 /* NOTE: post "not supported codec message" to application
5473  * when one codec is not found during AUTOPLUGGING in MSL.
5474  * So, it's separated with error of __mmplayer_gst_bus_msg_callback().
5475  * And, if any codec is not found, don't send message here.
5476  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
5477  */
5478 int
5479 __mmplayer_handle_missed_plugin(mm_player_t* player)
5480 {
5481         MMMessageParamType msg_param;
5482         memset(&msg_param, 0, sizeof(MMMessageParamType));
5483         gboolean post_msg_direct = FALSE;
5484
5485         MMPLAYER_FENTER();
5486
5487         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5488
5489         LOGD("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
5490                         player->not_supported_codec, player->can_support_codec);
5491
5492         if (player->not_found_demuxer) {
5493                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
5494                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
5495
5496                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
5497                 MMPLAYER_FREEIF(msg_param.data);
5498
5499                 return MM_ERROR_NONE;
5500         }
5501
5502         if (player->not_supported_codec) {
5503                 if (player->can_support_codec) {
5504                         // There is one codec to play
5505                         post_msg_direct = TRUE;
5506                 } else {
5507                         if (player->pipeline->audiobin) // Some content has only PCM data in container.
5508                                 post_msg_direct = TRUE;
5509                 }
5510
5511                 if (post_msg_direct) {
5512                         MMMessageParamType msg_param;
5513                         memset(&msg_param, 0, sizeof(MMMessageParamType));
5514
5515                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
5516                                 LOGW("not found AUDIO codec, posting error code to application.\n");
5517
5518                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
5519                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
5520                         } else if (player->not_supported_codec ==  MISSING_PLUGIN_VIDEO) {
5521                                 LOGW("not found VIDEO codec, posting error code to application.\n");
5522
5523                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
5524                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
5525                         }
5526
5527                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
5528
5529                         MMPLAYER_FREEIF(msg_param.data);
5530
5531                         return MM_ERROR_NONE;
5532                 } else {
5533                         // no any supported codec case
5534                         LOGW("not found any codec, posting error code to application.\n");
5535
5536                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
5537                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
5538                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
5539                         } else {
5540                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
5541                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
5542                         }
5543
5544                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
5545
5546                         MMPLAYER_FREEIF(msg_param.data);
5547                 }
5548         }
5549
5550         MMPLAYER_FLEAVE();
5551
5552         return MM_ERROR_NONE;
5553 }
5554
5555 static void __mmplayer_check_pipeline(mm_player_t* player)
5556 {
5557         GstState element_state = GST_STATE_VOID_PENDING;
5558         GstState element_pending_state = GST_STATE_VOID_PENDING;
5559         gint timeout = 0;
5560         int ret = MM_ERROR_NONE;
5561
5562         if (player->gapless.reconfigure) {
5563                 LOGW("pipeline is under construction.\n");
5564
5565                 MMPLAYER_PLAYBACK_LOCK(player);
5566                 MMPLAYER_PLAYBACK_UNLOCK(player);
5567
5568                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
5569
5570                 /* wait for state transition */
5571                 ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
5572
5573                 if (ret == GST_STATE_CHANGE_FAILURE)
5574                         LOGE("failed to change pipeline state within %d sec\n", timeout);
5575         }
5576 }
5577
5578 /* NOTE : it should be able to call 'stop' anytime*/
5579 int
5580 _mmplayer_stop(MMHandleType hplayer)
5581 {
5582         mm_player_t* player = (mm_player_t*)hplayer;
5583         int ret = MM_ERROR_NONE;
5584
5585         MMPLAYER_FENTER();
5586
5587         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5588
5589         /* check current state */
5590         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP);
5591
5592         /* check pipline building state */
5593         __mmplayer_check_pipeline(player);
5594         __mmplayer_reset_gapless_state(player);
5595
5596         /* NOTE : application should not wait for EOS after calling STOP */
5597         __mmplayer_cancel_eos_timer(player);
5598
5599         __mmplayer_unrealize_streaming_ext(player);
5600
5601         /* reset */
5602         player->seek_state = MMPLAYER_SEEK_NONE;
5603
5604         /* stop pipeline */
5605         ret = __mmplayer_gst_stop(player);
5606
5607         if (ret != MM_ERROR_NONE)
5608                 LOGE("failed to stop player.\n");
5609
5610         MMPLAYER_FLEAVE();
5611
5612         return ret;
5613 }
5614
5615 int
5616 _mmplayer_pause(MMHandleType hplayer)
5617 {
5618         mm_player_t* player = (mm_player_t*)hplayer;
5619         gint64 pos_nsec = 0;
5620         gboolean async = FALSE;
5621         gint ret = MM_ERROR_NONE;
5622
5623         MMPLAYER_FENTER();
5624
5625         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5626
5627         /* check current state */
5628         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE);
5629
5630         /* check pipline building state */
5631         __mmplayer_check_pipeline(player);
5632
5633         switch (MMPLAYER_CURRENT_STATE(player)) {
5634         case MM_PLAYER_STATE_READY:
5635                 {
5636                         /* check prepare async or not.
5637                          * In the case of streaming playback, it's recommned to avoid blocking wait.
5638                          */
5639                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
5640                         LOGD("prepare working mode : %s", (async ? "async" : "sync"));
5641
5642                         /* Changing back sync of rtspsrc to async */
5643                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
5644                                 LOGD("async prepare working mode for rtsp");
5645                                 async = TRUE;
5646                         }
5647                 }
5648                 break;
5649
5650         case MM_PLAYER_STATE_PLAYING:
5651                 {
5652                         /* NOTE : store current point to overcome some bad operation
5653                         *(returning zero when getting current position in paused state) of some
5654                         * elements
5655                         */
5656                         if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
5657                                 LOGW("getting current position failed in paused\n");
5658
5659                         player->last_position = pos_nsec;
5660
5661                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
5662                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
5663                            This causes problem is position calculation during normal pause resume scenarios also.
5664                            Currently during pause , we are sending the current position to rtspsrc module for position saving. */
5665                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
5666                                 (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
5667                                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
5668                         }
5669                 }
5670                 break;
5671         }
5672
5673         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
5674                 LOGD("doing async pause in case of ms buff src");
5675                 async = TRUE;
5676         }
5677
5678         /* pause pipeline */
5679         ret = __mmplayer_gst_pause(player, async);
5680
5681         if (ret != MM_ERROR_NONE)
5682                 LOGE("failed to pause player. ret : 0x%x\n", ret);
5683
5684         if (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
5685                 if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "display_rotation"))
5686                         LOGE("failed to update display_rotation");
5687         }
5688
5689         MMPLAYER_FLEAVE();
5690
5691         return ret;
5692 }
5693
5694 /* in case of streaming, pause could take long time.*/
5695 int
5696 _mmplayer_abort_pause(MMHandleType hplayer)
5697 {
5698         mm_player_t* player = (mm_player_t*)hplayer;
5699         int ret = MM_ERROR_NONE;
5700
5701         MMPLAYER_FENTER();
5702
5703         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
5704                                                 player->pipeline &&
5705                                                 player->pipeline->mainbin,
5706                                                 MM_ERROR_PLAYER_NOT_INITIALIZED);
5707
5708         LOGD("set the pipeline state to READY");
5709
5710         /* set state to READY */
5711         ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
5712                                                 GST_STATE_READY, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
5713         if (ret != MM_ERROR_NONE) {
5714                 LOGE("fail to change state to READY");
5715                 return MM_ERROR_PLAYER_INTERNAL;
5716         }
5717
5718         LOGD("succeeded in changing state to READY");
5719         return ret;
5720 }
5721
5722
5723 int
5724 _mmplayer_resume(MMHandleType hplayer)
5725 {
5726         mm_player_t* player = (mm_player_t*)hplayer;
5727         int ret = MM_ERROR_NONE;
5728         gboolean async = FALSE;
5729
5730         MMPLAYER_FENTER();
5731
5732         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5733
5734         if ((MMPLAYER_IS_RTSP_STREAMING(player))) {
5735                 if (player->is_external_subtitle_added_now) { /* after setting external subtitle, seeking and buffering is in progress. */
5736                         player->pending_resume = TRUE; /* will be resumed after finishing the buffering. */
5737                         return ret;
5738                 }
5739
5740                 /* Changing back sync mode rtspsrc to async */
5741                 LOGD("async resume for rtsp case");
5742                 async = TRUE;
5743         }
5744
5745         /* check current state */
5746         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
5747
5748         ret = __mmplayer_gst_resume(player, async);
5749         if (ret != MM_ERROR_NONE)
5750                 LOGE("failed to resume player.\n");
5751
5752         if ((player->streamer) && (player->streamer->buffering_state & MM_PLAYER_BUFFERING_IN_PROGRESS)) {
5753                 LOGD("force resume even during buffering");
5754                 player->streamer->buffering_state = MM_PLAYER_BUFFERING_ABORT;
5755         }
5756
5757         MMPLAYER_FLEAVE();
5758
5759         return ret;
5760 }
5761
5762 int
5763 _mmplayer_set_playspeed(MMHandleType hplayer, float rate, bool streaming)
5764 {
5765         mm_player_t* player = (mm_player_t*)hplayer;
5766         gint64 pos_nsec = 0;
5767         int ret = MM_ERROR_NONE;
5768         int mute = FALSE;
5769         signed long long start = 0, stop = 0;
5770         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
5771         MMPLAYER_FENTER();
5772
5773         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5774         MMPLAYER_RETURN_VAL_IF_FAIL(streaming || !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API);
5775
5776         /* The sound of video is not supported under 0.0 and over 2.0. */
5777         if (rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN) {
5778                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
5779                         mute = TRUE;
5780         }
5781         _mmplayer_set_mute(hplayer, mute);
5782
5783         if (player->playback_rate == rate)
5784                 return MM_ERROR_NONE;
5785
5786         /* If the position is reached at start potion during fast backward, EOS is posted.
5787          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
5788          * */
5789         player->playback_rate = rate;
5790
5791         current_state = MMPLAYER_CURRENT_STATE(player);
5792
5793         if (current_state != MM_PLAYER_STATE_PAUSED)
5794                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec);
5795
5796         LOGD("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_nsec), ret, current_state);
5797
5798         if ((current_state == MM_PLAYER_STATE_PAUSED)
5799                 || (!ret) /*|| (player->last_position != 0 && pos_msec == 0)*/) {
5800                 LOGW("returning last point : %"G_GINT64_FORMAT, player->last_position);
5801                 pos_nsec = player->last_position;
5802         }
5803
5804         if (rate >= 0) {
5805                 start = pos_nsec;
5806                 stop = GST_CLOCK_TIME_NONE;
5807         } else {
5808                 start = GST_CLOCK_TIME_NONE;
5809                 stop = pos_nsec;
5810         }
5811
5812         if (!__mmplayer_gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
5813                                 player->playback_rate,
5814                                 GST_FORMAT_TIME,
5815                                 (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
5816                                 GST_SEEK_TYPE_SET, start,
5817                                 GST_SEEK_TYPE_SET, stop)) {
5818                 LOGE("failed to set speed playback\n");
5819                 return MM_ERROR_PLAYER_SEEK;
5820         }
5821
5822         LOGD("succeeded to set speed playback as %0.1f\n", rate);
5823
5824         MMPLAYER_FLEAVE();
5825
5826         return MM_ERROR_NONE;;
5827 }
5828
5829 int
5830 _mmplayer_set_position(MMHandleType hplayer, gint64 position)
5831 {
5832         mm_player_t* player = (mm_player_t*)hplayer;
5833         int ret = MM_ERROR_NONE;
5834
5835         MMPLAYER_FENTER();
5836
5837         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5838
5839         /* check pipline building state */
5840         __mmplayer_check_pipeline(player);
5841
5842         ret = __mmplayer_gst_set_position(player, position, FALSE);
5843
5844         MMPLAYER_FLEAVE();
5845
5846         return ret;
5847 }
5848
5849 int
5850 _mmplayer_get_position(MMHandleType hplayer, gint64 *position)
5851 {
5852         mm_player_t* player = (mm_player_t*)hplayer;
5853         int ret = MM_ERROR_NONE;
5854
5855         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5856
5857         ret = __mmplayer_gst_get_position(player, position);
5858
5859         return ret;
5860 }
5861
5862 int
5863 _mmplayer_get_duration(MMHandleType hplayer, gint64 *duration)
5864 {
5865         mm_player_t* player = (mm_player_t*)hplayer;
5866         int ret = MM_ERROR_NONE;
5867
5868         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5869         MMPLAYER_RETURN_VAL_IF_FAIL(duration, MM_ERROR_COMMON_INVALID_ARGUMENT);
5870
5871         *duration = player->duration;
5872         return ret;
5873 }
5874
5875 int
5876 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos)
5877 {
5878         mm_player_t* player = (mm_player_t*)hplayer;
5879         int ret = MM_ERROR_NONE;
5880
5881         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5882
5883         ret = __mmplayer_gst_get_buffer_position(player, format, start_pos, stop_pos);
5884
5885         return ret;
5886 }
5887
5888 int
5889 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position)
5890 {
5891         mm_player_t* player = (mm_player_t*)hplayer;
5892         int ret = MM_ERROR_NONE;
5893
5894         MMPLAYER_FENTER();
5895
5896         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
5897
5898         ret = __mmplayer_gst_adjust_subtitle_position(player, format, position);
5899
5900         MMPLAYER_FLEAVE();
5901
5902         return ret;
5903 }
5904
5905 static gboolean
5906 __mmplayer_is_midi_type(gchar* str_caps)
5907 {
5908         if ((g_strrstr(str_caps, "audio/midi")) ||
5909                 (g_strrstr(str_caps, "application/x-gst_ff-mmf")) ||
5910                 (g_strrstr(str_caps, "application/x-smaf")) ||
5911                 (g_strrstr(str_caps, "audio/x-imelody")) ||
5912                 (g_strrstr(str_caps, "audio/mobile-xmf")) ||
5913                 (g_strrstr(str_caps, "audio/xmf")) ||
5914                 (g_strrstr(str_caps, "audio/mxmf"))) {
5915                 LOGD("midi\n");
5916                 return TRUE;
5917         }
5918
5919         return FALSE;
5920 }
5921
5922 static gboolean
5923 __mmplayer_is_only_mp3_type(gchar *str_caps)
5924 {
5925         if (g_strrstr(str_caps, "application/x-id3") ||
5926                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion= (int)1")))
5927                 return TRUE;
5928         return FALSE;
5929 }
5930
5931 static void
5932 __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps)
5933 {
5934         GstStructure* caps_structure = NULL;
5935         gint samplerate = 0;
5936         gint channels = 0;
5937
5938         MMPLAYER_FENTER();
5939         MMPLAYER_RETURN_IF_FAIL(player && caps);
5940
5941         caps_structure = gst_caps_get_structure(caps, 0);
5942
5943         /* set stream information */
5944         gst_structure_get_int(caps_structure, "rate", &samplerate);
5945         mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
5946
5947         gst_structure_get_int(caps_structure, "channels", &channels);
5948         mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
5949
5950         LOGD("audio samplerate : %d     channels : %d\n", samplerate, channels);
5951 }
5952
5953 static void
5954 __mmplayer_update_content_type_info(mm_player_t* player)
5955 {
5956         MMPLAYER_FENTER();
5957         MMPLAYER_RETURN_IF_FAIL(player && player->type);
5958
5959         if (__mmplayer_is_midi_type(player->type)) {
5960                 player->bypass_audio_effect = TRUE;
5961         } else if (g_strrstr(player->type, "application/x-hls")) {
5962                 /* If it can't know exact type when it parses uri because of redirection case,
5963                  * it will be fixed by typefinder or when doing autoplugging.
5964                  */
5965                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
5966                 if (player->streamer) {
5967                         player->streamer->is_adaptive_streaming = TRUE;
5968                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
5969                         player->streamer->buffering_req.rebuffer_time = 5 * 1000;
5970                 }
5971         } else if (g_strrstr(player->type, "application/dash+xml")) {
5972                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
5973                 if (player->streamer) {
5974                         player->streamer->is_adaptive_streaming = TRUE;
5975                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
5976                 }
5977         }
5978
5979         LOGD("uri type : %d", player->profile.uri_type);
5980         MMPLAYER_FLEAVE();
5981 }
5982
5983 void
5984 __mmplayer_typefind_have_type(GstElement *tf, guint probability,
5985 GstCaps *caps, gpointer data)
5986 {
5987         mm_player_t* player = (mm_player_t*)data;
5988         GstPad* pad = NULL;
5989
5990         MMPLAYER_FENTER();
5991
5992         MMPLAYER_RETURN_IF_FAIL(player && tf && caps);
5993
5994         /* store type string */
5995         MMPLAYER_FREEIF(player->type);
5996         player->type = gst_caps_to_string(caps);
5997         if (player->type) {
5998                 LOGD("[handle: %p] media type %s found, probability %d%% / %d\n",
5999                                 player, player->type, probability, gst_caps_get_size(caps));
6000         }
6001
6002         if ((!MMPLAYER_IS_RTSP_STREAMING(player)) &&
6003                 (g_strrstr(player->type, "audio/x-raw-int"))) {
6004                 LOGE("not support media format\n");
6005
6006                 if (player->msg_posted == FALSE) {
6007                         MMMessageParamType msg_param;
6008                         memset(&msg_param, 0, sizeof(MMMessageParamType));
6009
6010                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
6011                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
6012
6013                         /* don't post more if one was sent already */
6014                         player->msg_posted = TRUE;
6015                 }
6016                 return;
6017         }
6018
6019         __mmplayer_update_content_type_info(player);
6020
6021         pad = gst_element_get_static_pad(tf, "src");
6022         if (!pad) {
6023                 LOGE("fail to get typefind src pad.\n");
6024                 return;
6025         }
6026
6027         if (!__mmplayer_gst_create_decoder(player, pad, caps)) {
6028                 gboolean async = FALSE;
6029                 LOGE("failed to autoplug %s\n", player->type);
6030
6031                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
6032
6033                 if (async && player->msg_posted == FALSE)
6034                         __mmplayer_handle_missed_plugin(player);
6035
6036                 goto DONE;
6037         }
6038
6039 DONE:
6040         gst_object_unref(GST_OBJECT(pad));
6041
6042         MMPLAYER_FLEAVE();
6043
6044         return;
6045 }
6046
6047 GstElement *
6048 __mmplayer_gst_make_decodebin(mm_player_t* player)
6049 {
6050         GstElement *decodebin = NULL;
6051
6052         MMPLAYER_FENTER();
6053
6054         /* create decodebin */
6055         decodebin = gst_element_factory_make("decodebin", NULL);
6056
6057         if (!decodebin) {
6058                 LOGE("fail to create decodebin\n");
6059                 goto ERROR;
6060         }
6061
6062         /* raw pad handling signal */
6063         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6064                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), (gpointer)player);
6065
6066         /* no-more-pad pad handling signal */
6067         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
6068                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), (gpointer)player);
6069
6070         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
6071                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), (gpointer)player);
6072
6073         /* This signal is emitted when a pad for which there is no further possible
6074            decoding is added to the decodebin.*/
6075         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
6076                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), (gpointer)player);
6077
6078         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6079            before looking for any elements that can handle that stream.*/
6080         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
6081                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), (gpointer)player);
6082
6083         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6084            before looking for any elements that can handle that stream.*/
6085         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
6086                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), (gpointer)player);
6087
6088         /* This signal is emitted once decodebin has finished decoding all the data.*/
6089         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
6090                                                 G_CALLBACK(__mmplayer_gst_decode_drained), (gpointer)player);
6091
6092         /* This signal is emitted when a element is added to the bin.*/
6093         __mmplayer_add_signal_connection(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
6094                                                 G_CALLBACK(__mmplayer_gst_element_added), (gpointer)player);
6095
6096 ERROR:
6097         return decodebin;
6098 }
6099
6100 static GstElement*
6101 __mmplayer_gst_make_queue2(mm_player_t *player)
6102 {
6103         GstElement* queue2 = NULL;
6104         gint64 dur_bytes = 0L;
6105         guint max_buffer_size_bytes = 0;
6106         MMPlayerGstElement *mainbin = NULL;
6107         MuxedBufferType type = MUXED_BUFFER_TYPE_MEM_QUEUE;
6108
6109         MMPLAYER_FENTER();
6110         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, NULL);
6111
6112         mainbin = player->pipeline->mainbin;
6113
6114         queue2 = gst_element_factory_make("queue2", "queue2");
6115         if (!queue2) {
6116                 LOGE("failed to create buffering queue element");
6117                 return NULL;
6118         }
6119
6120         if (!gst_element_query_duration(mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
6121                 LOGE("failed to get duration from source %s", GST_ELEMENT_NAME(mainbin[MMPLAYER_M_SRC].gst));
6122
6123         LOGD("dur_bytes = %"G_GINT64_FORMAT, dur_bytes);
6124
6125         if (dur_bytes > 0) {
6126                 if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
6127                         type = MUXED_BUFFER_TYPE_FILE;
6128                 } else {
6129                         type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
6130                         player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
6131                 }
6132         } else {
6133                 dur_bytes = 0;
6134         }
6135
6136         /* NOTE : in case of ts streaming, player cannot get the correct duration info *
6137          *                skip the pull mode(file or ring buffering) setting. */
6138         if (!g_strrstr(player->type, "video/mpegts")) {
6139                 max_buffer_size_bytes = (type == MUXED_BUFFER_TYPE_FILE) ? (player->ini.http_max_size_bytes) : (5*1024*1024);
6140                 LOGD("max_buffer_size_bytes = %d", max_buffer_size_bytes);
6141
6142                 __mm_player_streaming_set_queue2(player->streamer,
6143                                                                                 queue2,
6144                                                                                 FALSE,
6145                                                                                 max_buffer_size_bytes,
6146                                                                                 player->ini.http_buffering_time,
6147                                                                                 1.0,                                                            /* no meaning */
6148                                                                                 player->ini.http_buffering_limit,       /* no meaning */
6149                                                                                 type,
6150                                                                                 player->http_file_buffering_path,
6151                                                                                 (guint64)dur_bytes);
6152         }
6153
6154         return queue2;
6155 }
6156
6157 gboolean
6158 __mmplayer_gst_create_decoder(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
6159 {
6160         MMPlayerGstElement* mainbin = NULL;
6161         GstElement* decodebin = NULL;
6162         GstElement* queue2 = NULL;
6163         GstPad* sinkpad = NULL;
6164         GstPad* qsrcpad = NULL;
6165         gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
6166
6167         MMPLAYER_FENTER();
6168         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
6169
6170         mainbin = player->pipeline->mainbin;
6171
6172         if ((!MMPLAYER_IS_HTTP_PD(player)) && (MMPLAYER_IS_HTTP_STREAMING(player))) {
6173
6174                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
6175                         LOGW("need to check: muxed buffer is not null");
6176                 }
6177
6178                 queue2 = __mmplayer_gst_make_queue2(player);
6179                 if (!queue2) {
6180                         LOGE("failed to make queue2");
6181                         goto ERROR;
6182                 }
6183
6184                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
6185                         LOGE("failed to add buffering queue");
6186                         goto ERROR;
6187                 }
6188
6189                 sinkpad = gst_element_get_static_pad(queue2, "sink");
6190                 qsrcpad = gst_element_get_static_pad(queue2, "src");
6191
6192                 if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
6193                         LOGE("failed to link [%s:%s]-[%s:%s]",
6194                                                 GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
6195                         goto ERROR;
6196                 }
6197
6198                 if (gst_element_sync_state_with_parent(queue2) == GST_STATE_CHANGE_FAILURE) {
6199                         LOGE("failed to sync queue2 state with parent");
6200                         goto ERROR;
6201                 }
6202
6203                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
6204                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
6205
6206                 srcpad = qsrcpad;
6207
6208                 gst_object_unref(GST_OBJECT(sinkpad));
6209                 sinkpad = NULL;
6210         }
6211
6212         /* create decodebin */
6213         decodebin = __mmplayer_gst_make_decodebin(player);
6214         if (!decodebin) {
6215                 LOGE("failed to make decodebin");
6216                 goto ERROR;
6217         }
6218
6219         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
6220                 LOGE("failed to add decodebin\n");
6221                 goto ERROR;
6222         }
6223
6224         /* to force caps on the decodebin element and avoid reparsing stuff by
6225         * typefind. It also avoids a deadlock in the way typefind activates pads in
6226         * the state change */
6227         g_object_set(decodebin, "sink-caps", caps, NULL);
6228
6229         sinkpad = gst_element_get_static_pad(decodebin, "sink");
6230
6231         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
6232                 LOGE("failed to link [%s:%s]-[%s:%s]",
6233                                 GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
6234                 goto ERROR;
6235         }
6236
6237         gst_object_unref(GST_OBJECT(sinkpad));
6238         sinkpad = NULL;
6239
6240         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
6241         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
6242
6243         /* set decodebin property about buffer in streaming playback. *
6244          * in case of HLS/DASH, it does not need to have big buffer   *
6245          * because it is kind of adaptive streaming.                  */
6246         if (!MMPLAYER_IS_HTTP_PD(player) &&
6247             (MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING(player) || MMPLAYER_IS_DASH_STREAMING(player))) {
6248             gdouble high_percent = 0.0;
6249
6250                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
6251                 high_percent = (gdouble)(init_buffering_time * 100) / GET_MAX_BUFFER_TIME(player->streamer);
6252
6253                 LOGD("decodebin setting - bytes: %d, time: %d ms, per: 1~%d",
6254                         GET_MAX_BUFFER_BYTES(player->streamer), GET_MAX_BUFFER_TIME(player->streamer), (gint)high_percent);
6255
6256                 g_object_set(G_OBJECT(decodebin), "use-buffering", TRUE,
6257                                                                                         "high-percent", (gint)high_percent,
6258                                                                                         "low-percent", (gint)DEFAULT_BUFFER_LOW_PERCENT,
6259                                                                                         "max-size-bytes", GET_MAX_BUFFER_BYTES(player->streamer),
6260                                                                                         "max-size-time", (guint64)(GET_MAX_BUFFER_TIME(player->streamer) * GST_MSECOND),
6261                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
6262         }
6263
6264         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin)) {
6265                 LOGE("failed to sync decodebin state with parent\n");
6266                 goto ERROR;
6267         }
6268
6269         MMPLAYER_FLEAVE();
6270
6271         return TRUE;
6272
6273 ERROR:
6274
6275         if (sinkpad)
6276                 gst_object_unref(GST_OBJECT(sinkpad));
6277
6278         if (queue2) {
6279                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
6280                  * You need to explicitly set elements to the NULL state before
6281                  * dropping the final reference, to allow them to clean up.
6282                  */
6283                 gst_element_set_state(queue2, GST_STATE_NULL);
6284
6285                 /* And, it still has a parent "player".
6286                  * You need to let the parent manage the object instead of unreffing the object directly.
6287                  */
6288                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
6289                 gst_object_unref(queue2);
6290                 queue2 = NULL;
6291         }
6292
6293         if (decodebin) {
6294                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
6295                  * You need to explicitly set elements to the NULL state before
6296                  * dropping the final reference, to allow them to clean up.
6297                  */
6298                 gst_element_set_state(decodebin, GST_STATE_NULL);
6299
6300                 /* And, it still has a parent "player".
6301                  * You need to let the parent manage the object instead of unreffing the object directly.
6302                  */
6303
6304                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
6305                 gst_object_unref(decodebin);
6306                 decodebin = NULL;
6307         }
6308
6309         return FALSE;
6310 }
6311
6312 static int
6313 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
6314 {
6315         MMPLAYER_FENTER();
6316
6317         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6318         MMPLAYER_RETURN_VAL_IF_FAIL(mime, MM_ERROR_INVALID_ARGUMENT);
6319
6320         LOGD("class : %s, mime : %s \n", factory_class, mime);
6321
6322         /* add missing plugin */
6323         /* NOTE : msl should check missing plugin for image mime type.
6324          * Some motion jpeg clips can have playable audio track.
6325          * So, msl have to play audio after displaying popup written video format not supported.
6326          */
6327         if (!(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)) {
6328                 if (!(player->can_support_codec | player->videodec_linked | player->audiodec_linked)) {
6329                         LOGD("not found demuxer\n");
6330                         player->not_found_demuxer = TRUE;
6331                         player->unlinked_demuxer_mime = g_strdup_printf("%s", mime);
6332
6333                         goto DONE;
6334                 }
6335         }
6336
6337         if (!g_strrstr(factory_class, "Demuxer")) {
6338                 if ((g_str_has_prefix(mime, "video")) || (g_str_has_prefix(mime, "image"))) {
6339                         LOGD("can support codec=0x%X, vdec_linked=%d, adec_linked=%d\n",
6340                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
6341
6342                         /* check that clip have multi tracks or not */
6343                         if ((player->can_support_codec & FOUND_PLUGIN_VIDEO) && (player->videodec_linked)) {
6344                                 LOGD("video plugin is already linked\n");
6345                         } else {
6346                                 LOGW("add VIDEO to missing plugin\n");
6347                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
6348                                 player->unlinked_video_mime = g_strdup_printf("%s", mime);
6349                         }
6350                 } else if (g_str_has_prefix(mime, "audio")) {
6351                         if ((player->can_support_codec & FOUND_PLUGIN_AUDIO) && (player->audiodec_linked)) {
6352                                 LOGD("audio plugin is already linked\n");
6353                         } else {
6354                                 LOGW("add AUDIO to missing plugin\n");
6355                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
6356                                 player->unlinked_audio_mime = g_strdup_printf("%s", mime);
6357                         }
6358                 }
6359         }
6360
6361 DONE:
6362         MMPLAYER_FLEAVE();
6363
6364         return MM_ERROR_NONE;
6365 }
6366
6367
6368 static void
6369 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
6370 {
6371         mm_player_t* player = (mm_player_t*)data;
6372
6373         MMPLAYER_FENTER();
6374
6375         MMPLAYER_RETURN_IF_FAIL(player);
6376
6377         /* remove fakesink. */
6378         if (!__mmplayer_gst_remove_fakesink(player,
6379                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) {
6380                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
6381                  * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
6382                  * source element are not same. To overcome this situation, this function will called
6383                  * several places and several times. Therefore, this is not an error case.
6384                  */
6385                 return;
6386         }
6387
6388         LOGD("[handle: %p] pipeline has completely constructed", player);
6389
6390         if ((player->ini.async_start) &&
6391                 (player->msg_posted == FALSE) &&
6392                 (player->cmd >= MMPLAYER_COMMAND_START))
6393                 __mmplayer_handle_missed_plugin(player);
6394
6395         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-complete");
6396 }
6397
6398 static int
6399 __mmplayer_check_profile(void)
6400 {
6401         char *profileName;
6402         static int profile_tv = -1;
6403
6404         if (__builtin_expect(profile_tv != -1, 1))
6405                 return profile_tv;
6406
6407         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
6408         switch (*profileName) {
6409         case 't':
6410         case 'T':
6411                 profile_tv = 1;
6412                 break;
6413         default:
6414                 profile_tv = 0;
6415                 break;
6416         }
6417         free(profileName);
6418
6419         return profile_tv;
6420 }
6421
6422 static gboolean
6423 __mmplayer_get_next_uri(mm_player_t *player)
6424 {
6425         MMPlayerParseProfile profile;
6426         gint uri_idx = 0;
6427         guint num_of_list = 0;
6428         char *uri = NULL;
6429
6430         num_of_list = g_list_length(player->uri_info.uri_list);
6431         uri_idx = player->uri_info.uri_idx;
6432
6433         LOGD("num of uri list = %d, current uri idx %d", num_of_list, uri_idx);
6434         for (uri_idx++; uri_idx < num_of_list; uri_idx++) {
6435                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
6436                 if (uri == NULL) {
6437                         LOGW("next uri does not exist");
6438                         continue;
6439                 }
6440
6441                 if (__mmplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) {
6442                         LOGE("failed to parse profile");
6443                         continue;
6444                 }
6445
6446                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
6447                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) {
6448                         LOGW("uri type is not supported(%d)", profile.uri_type);
6449                         continue;
6450                 }
6451
6452                 LOGD("success to find next uri %d", uri_idx);
6453                 break;
6454         }
6455
6456         if (uri_idx == num_of_list) {
6457                 LOGE("failed to find next uri");
6458                 return FALSE;
6459         }
6460
6461         player->uri_info.uri_idx = uri_idx;
6462         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
6463
6464         if (mmf_attrs_commit(player->attrs)) {
6465                 LOGE("failed to commit");
6466                 return FALSE;
6467         }
6468
6469         SECURE_LOGD("next playback uri: %s", uri);
6470         return TRUE;
6471 }
6472
6473 static gboolean
6474 __mmplayer_verify_gapless_play_path(mm_player_t *player)
6475 {
6476 #define REPEAT_COUNT_INFINITELY -1
6477 #define REPEAT_COUNT_MIN 2
6478
6479         MMHandleType attrs = 0;
6480         gint mode = MM_PLAYER_PD_MODE_NONE;
6481         gint video = 0;
6482         gint count = 0;
6483         gint gapless = 0;
6484         guint num_of_list = 0;
6485         int profile_tv = -1;
6486
6487         MMPLAYER_FENTER();
6488
6489         LOGD("checking for gapless play option");
6490
6491         if (player->pipeline->textbin) {
6492                 LOGE("subtitle path is enabled. gapless play is not supported.\n");
6493                 goto ERROR;
6494         }
6495
6496         attrs = MMPLAYER_GET_ATTRS(player);
6497         if (!attrs) {
6498                 LOGE("fail to get attributes.\n");
6499                 goto ERROR;
6500         }
6501
6502         mm_attrs_get_int_by_name(attrs, "content_video_found", &video);
6503
6504         /* gapless playback is not supported in case of video at TV profile. */
6505         profile_tv = __mmplayer_check_profile();
6506         if (profile_tv && video) {
6507                 LOGW("not support video gapless playback");
6508                 goto ERROR;
6509         }
6510
6511         if (mm_attrs_get_int_by_name(attrs, "pd_mode", &mode) == MM_ERROR_NONE) {
6512                 if (mode == TRUE) {
6513                         LOGW("pd mode\n");
6514                         goto ERROR;
6515                 }
6516         }
6517
6518         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
6519                 LOGE("failed to get play count");
6520
6521         if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE)
6522                 LOGE("failed to get gapless mode");
6523
6524         /* check repeat count in case of audio */
6525         if (!gapless &&
6526                 (video || (count != REPEAT_COUNT_INFINITELY && count < REPEAT_COUNT_MIN))) {
6527                 LOGW("gapless is disabled");
6528                 goto ERROR;
6529         }
6530
6531         num_of_list = g_list_length(player->uri_info.uri_list);
6532
6533         LOGD("repeat count = %d, num_of_list = %d", count, num_of_list);
6534
6535         if (num_of_list == 0) {
6536                 /* audio looping path */
6537                 if (count >= REPEAT_COUNT_MIN) {
6538                         /* decrease play count */
6539                         /* we succeeded to rewind. update play count and then wait for next EOS */
6540                         count--;
6541
6542                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
6543
6544                         /* commit attribute */
6545                         if (mmf_attrs_commit(attrs))
6546                                 LOGE("failed to commit attribute");
6547                 } else if (count != REPEAT_COUNT_INFINITELY) {
6548                         LOGD("there is no next uri and no repeat");
6549                         goto ERROR;
6550                 }
6551
6552                 LOGD("looping cnt %d", count);
6553         } else {
6554                 /* gapless playback path */
6555                 if (!__mmplayer_get_next_uri(player)) {
6556                         LOGE("failed to get next uri");
6557                         goto ERROR;
6558                 }
6559         }
6560
6561         return TRUE;
6562
6563 ERROR:
6564         LOGE("unable to play gapless path. EOS will be posted soon");
6565         return FALSE;
6566 }
6567
6568 static void
6569 __mmplayer_initialize_gapless_play(mm_player_t *player)
6570 {
6571         int i;
6572
6573         MMPLAYER_FENTER();
6574
6575         player->smooth_streaming = FALSE;
6576         player->videodec_linked = 0;
6577         player->audiodec_linked = 0;
6578         player->videosink_linked = 0;
6579         player->audiosink_linked = 0;
6580         player->textsink_linked = 0;
6581         player->is_external_subtitle_present = FALSE;
6582         player->is_external_subtitle_added_now = FALSE;
6583         player->not_supported_codec = MISSING_PLUGIN_NONE;
6584         player->can_support_codec = FOUND_PLUGIN_NONE;
6585         player->pending_seek.is_pending = FALSE;
6586         player->pending_seek.pos = 0;
6587         player->msg_posted = FALSE;
6588         player->has_many_types = FALSE;
6589         player->no_more_pad = FALSE;
6590         player->not_found_demuxer = 0;
6591         player->seek_state = MMPLAYER_SEEK_NONE;
6592         player->is_subtitle_force_drop = FALSE;
6593         player->play_subtitle = FALSE;
6594         player->adjust_subtitle_pos = 0;
6595
6596         player->total_bitrate = 0;
6597         player->total_maximum_bitrate = 0;
6598
6599         __mmplayer_track_initialize(player);
6600         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
6601
6602         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
6603                 player->bitrate[i] = 0;
6604                 player->maximum_bitrate[i] = 0;
6605         }
6606
6607         if (player->v_stream_caps) {
6608                 gst_caps_unref(player->v_stream_caps);
6609                 player->v_stream_caps = NULL;
6610         }
6611
6612         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
6613
6614         /* clean found parsers */
6615         if (player->parsers) {
6616                 GList *parsers = player->parsers;
6617                 for (; parsers; parsers = g_list_next(parsers)) {
6618                         gchar *name = parsers->data;
6619                         MMPLAYER_FREEIF(name);
6620                 }
6621                 g_list_free(player->parsers);
6622                 player->parsers = NULL;
6623         }
6624
6625         /* clean found audio decoders */
6626         if (player->audio_decoders) {
6627                 GList *a_dec = player->audio_decoders;
6628                 for (; a_dec; a_dec = g_list_next(a_dec)) {
6629                         gchar *name = a_dec->data;
6630                         MMPLAYER_FREEIF(name);
6631                 }
6632                 g_list_free(player->audio_decoders);
6633                 player->audio_decoders = NULL;
6634         }
6635
6636         MMPLAYER_FLEAVE();
6637 }
6638
6639 static void
6640 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
6641 {
6642         MMPlayerGstElement *mainbin = NULL;
6643         MMMessageParamType msg_param = {0,};
6644         GstElement *element = NULL;
6645         MMHandleType attrs = 0;
6646         char *uri = NULL;
6647         enum MainElementID elem_idx = MMPLAYER_M_NUM;
6648
6649         MMPLAYER_FENTER();
6650
6651         if (!player || !player->pipeline || !player->pipeline->mainbin) {
6652                 LOGE("player is not initialized");
6653                 goto ERROR;
6654         }
6655
6656         mainbin = player->pipeline->mainbin;
6657         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
6658
6659         attrs = MMPLAYER_GET_ATTRS(player);
6660         if (!attrs) {
6661                 LOGE("fail to get attributes");
6662                 goto ERROR;
6663         }
6664
6665         /* Initialize Player values */
6666         __mmplayer_initialize_gapless_play(player);
6667
6668         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
6669
6670         if (__mmplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE) {
6671                 LOGE("failed to parse profile");
6672                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
6673                 goto ERROR;
6674         }
6675
6676         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
6677                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
6678                 LOGE("dash or hls is not supportable");
6679                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
6680                 goto ERROR;
6681         }
6682
6683         element = __mmplayer_gst_create_source(player);
6684         if (!element) {
6685                 LOGE("no source element was created");
6686                 goto ERROR;
6687         }
6688
6689         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
6690                 LOGE("failed to add source element to pipeline");
6691                 gst_object_unref(GST_OBJECT(element));
6692                 element = NULL;
6693                 goto ERROR;
6694         }
6695
6696         /* take source element */
6697         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
6698         mainbin[MMPLAYER_M_SRC].gst = element;
6699
6700         element = NULL;
6701
6702         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
6703                 if (player->streamer == NULL) {
6704                         player->streamer = __mm_player_streaming_create();
6705                         __mm_player_streaming_initialize(player->streamer);
6706                 }
6707
6708                 elem_idx = MMPLAYER_M_TYPEFIND;
6709                 element = gst_element_factory_make("typefind", "typefinder");
6710                 __mmplayer_add_signal_connection(player, G_OBJECT(element),
6711                         MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type", G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
6712         } else {
6713                 elem_idx = MMPLAYER_M_AUTOPLUG;
6714                 element = __mmplayer_gst_make_decodebin(player);
6715         }
6716
6717         /* check autoplug element is OK */
6718         if (!element) {
6719                 LOGE("can not create element(%d)", elem_idx);
6720                 goto ERROR;
6721         }
6722
6723         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
6724                 LOGE("failed to add sinkbin to pipeline");
6725                 gst_object_unref(GST_OBJECT(element));
6726                 element = NULL;
6727                 goto ERROR;
6728         }
6729
6730         mainbin[elem_idx].id = elem_idx;
6731         mainbin[elem_idx].gst = element;
6732
6733         if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elem_idx].gst) == FALSE) {
6734                 LOGE("Failed to link src - autoplug(or typefind)");
6735                 goto ERROR;
6736         }
6737
6738         if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
6739                 LOGE("Failed to change state of src element");
6740                 goto ERROR;
6741         }
6742
6743         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
6744                 if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
6745                         LOGE("Failed to change state of decodebin");
6746                         goto ERROR;
6747                 }
6748         } else {
6749                 if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
6750                         LOGE("Failed to change state of src element");
6751                         goto ERROR;
6752                 }
6753         }
6754
6755         player->gapless.stream_changed = TRUE;
6756         player->gapless.running = TRUE;
6757         MMPLAYER_FLEAVE();
6758         return;
6759
6760 ERROR:
6761         if (player) {
6762                 MMPLAYER_PLAYBACK_UNLOCK(player);
6763
6764                 if (!player->msg_posted) {
6765                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
6766                         player->msg_posted = TRUE;
6767                 }
6768         }
6769         return;
6770 }
6771
6772 static gboolean
6773 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
6774 {
6775         mm_player_selector_t *selector = &player->selector[type];
6776         MMPlayerGstElement *sinkbin = NULL;
6777         enum MainElementID selectorId = MMPLAYER_M_NUM;
6778         enum MainElementID sinkId = MMPLAYER_M_NUM;
6779         GstPad *srcpad = NULL;
6780         GstPad *sinkpad = NULL;
6781         gboolean send_notice = FALSE;
6782
6783         MMPLAYER_FENTER();
6784         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
6785
6786         LOGD("type %d", type);
6787
6788         switch (type) {
6789         case MM_PLAYER_TRACK_TYPE_AUDIO:
6790                 selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
6791                 sinkId = MMPLAYER_A_BIN;
6792                 sinkbin = player->pipeline->audiobin;
6793                 break;
6794         case MM_PLAYER_TRACK_TYPE_VIDEO:
6795                 selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
6796                 sinkId = MMPLAYER_V_BIN;
6797                 sinkbin = player->pipeline->videobin;
6798                 send_notice = TRUE;
6799                 break;
6800         case MM_PLAYER_TRACK_TYPE_TEXT:
6801                 selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
6802                 sinkId = MMPLAYER_T_BIN;
6803                 sinkbin = player->pipeline->textbin;
6804                 break;
6805         default:
6806                 LOGE("requested type is not supportable");
6807                 return FALSE;
6808                 break;
6809         }
6810
6811         if (player->pipeline->mainbin[selectorId].gst) {
6812                 gint n;
6813
6814                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
6815
6816                 if (selector->event_probe_id != 0)
6817                         gst_pad_remove_probe(srcpad, selector->event_probe_id);
6818                 selector->event_probe_id = 0;
6819
6820                 if ((sinkbin) && (sinkbin[sinkId].gst)) {
6821                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
6822
6823                         if (srcpad && sinkpad) {
6824                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
6825                                 LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
6826                                 gst_pad_unlink(srcpad, sinkpad);
6827
6828                                 /* send custom event to sink pad to handle it at video sink */
6829                                 if (send_notice) {
6830                                         LOGD("send custom event to sinkpad");
6831                                         GstStructure *s = gst_structure_new_empty("tizen/flush-buffer");
6832                                         GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s);
6833                                         gst_pad_send_event(sinkpad, event);
6834                                 }
6835                         }
6836
6837                         gst_object_unref(sinkpad);
6838                         sinkpad = NULL;
6839                 }
6840                 gst_object_unref(srcpad);
6841                 srcpad = NULL;
6842
6843                 LOGD("selector release");
6844
6845                 /* release and unref requests pad from the selector */
6846                 for (n = 0; n < selector->channels->len; n++) {
6847                         GstPad *sinkpad = g_ptr_array_index(selector->channels, n);
6848                         gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad);
6849                 }
6850                 g_ptr_array_set_size(selector->channels, 0);
6851
6852                 gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
6853                 gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
6854
6855                 player->pipeline->mainbin[selectorId].gst = NULL;
6856                 selector = NULL;
6857         }
6858
6859         return TRUE;
6860 }
6861
6862 static void
6863 __mmplayer_deactivate_old_path(mm_player_t *player)
6864 {
6865         MMPLAYER_FENTER();
6866         MMPLAYER_RETURN_IF_FAIL(player);
6867
6868         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
6869                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
6870                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
6871                 LOGE("deactivate selector error");
6872                 goto ERROR;
6873         }
6874
6875         __mmplayer_track_destroy(player);
6876         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
6877
6878         if (player->streamer) {
6879                 __mm_player_streaming_deinitialize(player->streamer);
6880                 __mm_player_streaming_destroy(player->streamer);
6881                 player->streamer = NULL;
6882         }
6883
6884         MMPLAYER_PLAYBACK_LOCK(player);
6885         MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(player);
6886
6887         MMPLAYER_FLEAVE();
6888         return;
6889
6890 ERROR:
6891
6892         if (!player->msg_posted) {
6893                 MMMessageParamType msg = {0,};
6894
6895                 /*post error*/
6896                 msg.code = MM_ERROR_PLAYER_INTERNAL;
6897                 LOGE("gapless_uri_play> deactivate error");
6898
6899                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
6900                 player->msg_posted = TRUE;
6901         }
6902         return;
6903 }
6904
6905 int _mmplayer_set_file_buffering_path(MMHandleType hplayer, const char* file_path)
6906 {
6907         int result = MM_ERROR_NONE;
6908         mm_player_t* player = (mm_player_t*) hplayer;
6909         MMPLAYER_FENTER();
6910
6911         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6912
6913         if (file_path) {
6914                 player->http_file_buffering_path = (gchar*)file_path;
6915                 LOGD("temp file path: %s\n", player->http_file_buffering_path);
6916         }
6917         MMPLAYER_FLEAVE();
6918         return result;
6919 }
6920
6921 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
6922 {
6923         int result = MM_ERROR_NONE;
6924         mm_player_t* player = (mm_player_t*) hplayer;
6925         MMPLAYER_FENTER();
6926
6927         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6928
6929         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
6930         if (mmf_attrs_commit(player->attrs)) {
6931                 LOGE("failed to commit the original uri.\n");
6932                 result = MM_ERROR_PLAYER_INTERNAL;
6933         } else {
6934                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
6935                         LOGE("failed to add the original uri in the uri list.\n");
6936         }
6937
6938         MMPLAYER_FLEAVE();
6939         return result;
6940 }
6941
6942 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
6943 {
6944         mm_player_t* player = (mm_player_t*) hplayer;
6945         guint num_of_list = 0;
6946
6947         MMPLAYER_FENTER();
6948
6949         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6950         MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT);
6951
6952         if (player->pipeline && player->pipeline->textbin) {
6953                 LOGE("subtitle path is enabled.\n");
6954                 return MM_ERROR_PLAYER_INVALID_STATE;
6955         }
6956
6957         num_of_list = g_list_length(player->uri_info.uri_list);
6958
6959         if (is_first_path == TRUE) {
6960                 if (num_of_list == 0) {
6961                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
6962                         LOGD("add original path : %s", uri);
6963                 } else {
6964                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
6965                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
6966
6967                         LOGD("change original path : %s", uri);
6968                 }
6969         } else {
6970                 MMHandleType attrs = 0;
6971                 attrs = MMPLAYER_GET_ATTRS(player);
6972
6973                 if (num_of_list == 0) {
6974                         char *original_uri = NULL;
6975
6976                         if (attrs) {
6977                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
6978
6979                                 if (!original_uri) {
6980                                         LOGE("there is no original uri.");
6981                                         return MM_ERROR_PLAYER_INVALID_STATE;
6982                                 }
6983
6984                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
6985                                 player->uri_info.uri_idx = 0;
6986
6987                                 LOGD("add original path at first : %s(%d)", original_uri);
6988                         }
6989                 }
6990
6991                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
6992                 LOGD("add new path : %s(total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
6993         }
6994
6995         MMPLAYER_FLEAVE();
6996         return MM_ERROR_NONE;
6997 }
6998
6999 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
7000 {
7001         mm_player_t* player = (mm_player_t*) hplayer;
7002         char *next_uri = NULL;
7003         guint num_of_list = 0;
7004
7005         MMPLAYER_FENTER();
7006         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7007
7008         num_of_list = g_list_length(player->uri_info.uri_list);
7009
7010         if (num_of_list > 0) {
7011                 gint uri_idx = player->uri_info.uri_idx;
7012
7013                 if (uri_idx < num_of_list-1)
7014                         uri_idx++;
7015                 else
7016                         uri_idx = 0;
7017
7018                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
7019                 LOGE("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
7020
7021                 *uri = g_strdup(next_uri);
7022         }
7023
7024         MMPLAYER_FLEAVE();
7025         return MM_ERROR_NONE;
7026 }
7027
7028 static void
7029 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
7030 GstCaps *caps, gpointer data)
7031 {
7032         mm_player_t* player = (mm_player_t*)data;
7033         const gchar* klass = NULL;
7034         const gchar* mime = NULL;
7035         gchar* caps_str = NULL;
7036
7037         klass = gst_element_factory_get_metadata(gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
7038         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
7039         caps_str = gst_caps_to_string(caps);
7040
7041         LOGW("unknown type of caps : %s from %s",
7042                                         caps_str, GST_ELEMENT_NAME(elem));
7043
7044         MMPLAYER_FREEIF(caps_str);
7045
7046         /* There is no available codec. */
7047         __mmplayer_check_not_supported_codec(player, klass, mime);
7048 }
7049
7050 static gboolean
7051 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
7052 GstCaps * caps,  gpointer data)
7053 {
7054         mm_player_t* player = (mm_player_t*)data;
7055         const char* mime = NULL;
7056         gboolean ret = TRUE;
7057
7058         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
7059         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
7060
7061         if (g_str_has_prefix(mime, "audio")) {
7062                 GstStructure* caps_structure = NULL;
7063                 gint samplerate = 0;
7064                 gint channels = 0;
7065                 gchar *caps_str = NULL;
7066
7067                 caps_structure = gst_caps_get_structure(caps, 0);
7068                 gst_structure_get_int(caps_structure, "rate", &samplerate);
7069                 gst_structure_get_int(caps_structure, "channels", &channels);
7070
7071                 if ((channels > 0 && samplerate == 0)) {
7072                         LOGD("exclude audio...");
7073                         ret = FALSE;
7074                 }
7075
7076                 caps_str = gst_caps_to_string(caps);
7077                 /* set it directly because not sent by TAG */
7078                 if (g_strrstr(caps_str, "mobile-xmf"))
7079                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
7080                 MMPLAYER_FREEIF(caps_str);
7081         } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) {
7082                 MMMessageParamType msg_param;
7083                 memset(&msg_param, 0, sizeof(MMMessageParamType));
7084                 msg_param.code = MM_ERROR_NOT_SUPPORT_API;
7085                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
7086                 LOGD("video file is not supported on this device");
7087                 ret = FALSE;
7088         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
7089                 LOGD("already video linked");
7090                 ret = FALSE;
7091         } else {
7092                 LOGD("found new stream");
7093         }
7094
7095         return ret;
7096 }
7097
7098 static int
7099 __mmplayer_check_codec_info(mm_player_t* player, const char* klass, GstCaps* caps, char* factory_name)
7100 {
7101         int ret = MM_ERROR_NONE;
7102         int idx = 0;
7103         int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
7104
7105         if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
7106                 mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
7107
7108                 LOGD("audio codec type: %d", codec_type);
7109                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
7110                         /* sw codec will be skipped */
7111                         for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) {
7112                                 if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) {
7113                                         LOGW("skipping sw acodec:[%s] by codec type", factory_name);
7114                                         ret = MM_ERROR_PLAYER_INTERNAL;
7115                                         goto DONE;
7116                                 }
7117                         }
7118                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
7119                         /* hw codec will be skipped */
7120                         if (strcmp(player->ini.audiocodec_element_hw, "") &&
7121                             g_strrstr(factory_name, player->ini.audiocodec_element_hw)) {
7122                                 LOGW("skipping hw acodec:[%s] by codec type", factory_name);
7123                                 ret = MM_ERROR_PLAYER_INTERNAL;
7124                                 goto DONE;
7125                         }
7126                 }
7127
7128                 /* set stream information */
7129                 if (!player->audiodec_linked)
7130                         __mmplayer_set_audio_attrs(player, caps);
7131
7132                 /* update codec info */
7133                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
7134                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
7135                 player->audiodec_linked = 1;
7136
7137         } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
7138
7139                 mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type);
7140
7141                 LOGD("video codec type: %d", codec_type);
7142                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
7143                         /* sw codec is skipped */
7144                         for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) {
7145                                 if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) {
7146                                         LOGW("skipping sw vcodec:[%s] by codec type", factory_name);
7147                                         ret = MM_ERROR_PLAYER_INTERNAL;
7148                                         goto DONE;
7149                                 }
7150                         }
7151                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
7152                         /* hw codec is skipped */
7153                         if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
7154                                 LOGW("skipping hw vcodec:[%s] by codec type", factory_name);
7155                                 ret = MM_ERROR_PLAYER_INTERNAL;
7156                                 goto DONE;
7157                         }
7158                 }
7159
7160                 if ((strlen(player->ini.videocodec_element_hw) > 0) &&
7161                         (g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
7162
7163                         /* mark video decoder for acquire */
7164                         if (player->video_decoder_resource == NULL) {
7165                                 if (mm_resource_manager_mark_for_acquire(player->resource_manager,
7166                                                 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
7167                                                 MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
7168                                                 &player->video_decoder_resource)
7169                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
7170                                         LOGE("could not mark video_decoder resource for acquire");
7171                                         ret = MM_ERROR_PLAYER_INTERNAL;
7172                                         goto DONE;
7173                                 }
7174                         } else {
7175                                 LOGW("video decoder resource is already acquired, skip it.");
7176                                 ret = MM_ERROR_PLAYER_INTERNAL;
7177                                 goto DONE;
7178                         }
7179
7180                         player->interrupted_by_resource = FALSE;
7181                         /* acquire resources for video playing */
7182                         if (mm_resource_manager_commit(player->resource_manager)
7183                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
7184                                 LOGE("could not acquire resources for video decoding\n");
7185                                 ret = MM_ERROR_PLAYER_INTERNAL;
7186                                 goto DONE;
7187                         }
7188                 }
7189
7190                 /* update codec info */
7191                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
7192                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
7193                 player->videodec_linked = 1;
7194         }
7195
7196 DONE:
7197         return ret;
7198 }
7199
7200 gint
7201 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
7202 GstCaps* caps, GstElementFactory* factory, gpointer data)
7203 {
7204         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
7205          We are defining our own and will be removed when it actually exposed */
7206         typedef enum {
7207                 GST_AUTOPLUG_SELECT_TRY,
7208                 GST_AUTOPLUG_SELECT_EXPOSE,
7209                 GST_AUTOPLUG_SELECT_SKIP
7210         } GstAutoplugSelectResult;
7211
7212         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
7213         mm_player_t* player = (mm_player_t*)data;
7214
7215         gchar* factory_name = NULL;
7216         gchar* caps_str = NULL;
7217         const gchar* klass = NULL;
7218         gint idx = 0;
7219
7220         factory_name = GST_OBJECT_NAME(factory);
7221         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
7222         caps_str = gst_caps_to_string(caps);
7223
7224         LOGD("[handle: %p] found new element [%s] to link", player, factory_name);
7225
7226         /* store type string */
7227         if (player->type == NULL) {
7228                 player->type = gst_caps_to_string(caps);
7229                 __mmplayer_update_content_type_info(player);
7230         }
7231
7232         /* filtering exclude keyword */
7233         for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) {
7234                 if (strstr(factory_name, player->ini.exclude_element_keyword[idx])) {
7235                         LOGW("skipping [%s] by exculde keyword [%s]",
7236                                         factory_name, player->ini.exclude_element_keyword[idx]);
7237
7238                         result = GST_AUTOPLUG_SELECT_SKIP;
7239                         goto DONE;
7240                 }
7241         }
7242
7243         for (idx = 0; player->ini.unsupported_codec_keyword[idx][0] != '\0'; idx++) {
7244                 if (caps_str && strstr(caps_str, player->ini.unsupported_codec_keyword[idx])) {
7245                         LOGW("skipping [%s] by unsupported codec keyword [%s]",
7246                                 factory_name, player->ini.unsupported_codec_keyword[idx]);
7247                         result = GST_AUTOPLUG_SELECT_SKIP;
7248                         goto DONE;
7249                 }
7250         }
7251
7252         /* exclude webm format */
7253         /* NOTE : MSL have to post MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT
7254          * because webm format is not supportable.
7255          * If webm is disabled in "autoplug-continue", there is no state change
7256          * failure or error because the decodebin will expose the pad directly.
7257          * It make MSL invoke _prepare_async_callback.
7258          * So, we need to disable webm format in "autoplug-select" */
7259         if (caps_str && strstr(caps_str, "webm")) {
7260                 LOGW("webm is not supported");
7261                 result = GST_AUTOPLUG_SELECT_SKIP;
7262                 goto DONE;
7263         }
7264
7265         /* check factory class for filtering */
7266         /* NOTE : msl don't need to use image plugins.
7267          * So, those plugins should be skipped for error handling.
7268          */
7269         if (g_strrstr(klass, "Codec/Decoder/Image")) {
7270                 LOGD("skipping [%s] by not required\n", factory_name);
7271                 result = GST_AUTOPLUG_SELECT_SKIP;
7272                 goto DONE;
7273         }
7274
7275         if ((MMPLAYER_IS_MS_BUFF_SRC(player)) &&
7276                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser")))) {
7277                 // TO CHECK : subtitle if needed, add subparse exception.
7278                 LOGD("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
7279                 result = GST_AUTOPLUG_SELECT_SKIP;
7280                 goto DONE;
7281         }
7282
7283         if (g_strrstr(factory_name, "mpegpsdemux")) {
7284                 LOGD("skipping PS container - not support\n");
7285                 result = GST_AUTOPLUG_SELECT_SKIP;
7286                 goto DONE;
7287         }
7288
7289         if (g_strrstr(factory_name, "mssdemux"))
7290                 player->smooth_streaming = TRUE;
7291
7292         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
7293                 (g_strrstr(klass, "Codec/Decoder/Video"))) {
7294                 gint stype = 0;
7295                 gint width = 0;
7296                 GstStructure *str = NULL;
7297                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
7298
7299                 /* don't make video because of not required */
7300                 if ((stype == MM_DISPLAY_SURFACE_NULL) &&
7301                         (player->set_mode.media_packet_video_stream == FALSE)) {
7302                         LOGD("no video because it's not required. -> return expose");
7303                         result = GST_AUTOPLUG_SELECT_EXPOSE;
7304                         goto DONE;
7305                 }
7306
7307                 /* get w/h for omx state-tune */
7308                 /* FIXME: deprecated? */
7309                 str = gst_caps_get_structure(caps, 0);
7310                 gst_structure_get_int(str, "width", &width);
7311
7312                 if (width != 0) {
7313                         if (player->v_stream_caps) {
7314                                 gst_caps_unref(player->v_stream_caps);
7315                                 player->v_stream_caps = NULL;
7316                         }
7317
7318                         player->v_stream_caps = gst_caps_copy(caps);
7319                         LOGD("take caps for video state tune");
7320                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
7321                 }
7322         }
7323
7324         if (g_strrstr(klass, "Codec/Decoder")) {
7325                 if (__mmplayer_check_codec_info(player, klass, caps, factory_name) != MM_ERROR_NONE) {
7326                         LOGD("skipping %s codec", factory_name);
7327                         result = GST_AUTOPLUG_SELECT_SKIP;
7328                         goto DONE;
7329                 }
7330         }
7331
7332 DONE:
7333         MMPLAYER_FREEIF(caps_str);
7334
7335         return result;
7336 }
7337
7338 static void
7339 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
7340 gpointer data)
7341 {
7342         //mm_player_t* player = (mm_player_t*)data;
7343         GstCaps* caps = NULL;
7344
7345         LOGD("[Decodebin2] pad-removed signal\n");
7346
7347         caps = gst_pad_query_caps(new_pad, NULL);
7348         if (caps) {
7349                 gchar* caps_str = NULL;
7350                 caps_str = gst_caps_to_string(caps);
7351
7352                 LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
7353
7354                 MMPLAYER_FREEIF(caps_str);
7355                 gst_caps_unref(caps);
7356         }
7357 }
7358
7359 static void
7360 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
7361 {
7362         mm_player_t* player = (mm_player_t*)data;
7363         GstIterator *iter = NULL;
7364         GValue item = { 0, };
7365         GstPad *pad = NULL;
7366         gboolean done = FALSE;
7367         gboolean is_all_drained = TRUE;
7368
7369         MMPLAYER_FENTER();
7370         MMPLAYER_RETURN_IF_FAIL(player);
7371
7372         LOGD("__mmplayer_gst_decode_drained");
7373
7374         if (!MMPLAYER_CMD_TRYLOCK(player)) {
7375                 LOGW("Fail to get cmd lock");
7376                 return;
7377         }
7378
7379         if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */
7380                 !__mmplayer_verify_gapless_play_path(player)) {
7381                 LOGD("decoding is finished.");
7382                 __mmplayer_reset_gapless_state(player);
7383                 MMPLAYER_CMD_UNLOCK(player);
7384                 return;
7385         }
7386
7387         player->gapless.reconfigure = TRUE;
7388
7389         /* check decodebin src pads whether they received EOS or not */
7390         iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
7391
7392         while (!done) {
7393                 switch (gst_iterator_next(iter, &item)) {
7394                 case GST_ITERATOR_OK:
7395                         pad = g_value_get_object(&item);
7396                         if (pad && !GST_PAD_IS_EOS(pad)) {
7397                                 LOGW("[%s:%s] not received EOS yet.", GST_DEBUG_PAD_NAME(pad));
7398                                 is_all_drained = FALSE;
7399                                 break;
7400                         }
7401                         g_value_reset(&item);
7402                         break;
7403                 case GST_ITERATOR_RESYNC:
7404                         gst_iterator_resync(iter);
7405                         break;
7406                 case GST_ITERATOR_ERROR:
7407                 case GST_ITERATOR_DONE:
7408                         done = TRUE;
7409                         break;
7410                 }
7411         }
7412         g_value_unset(&item);
7413         gst_iterator_free(iter);
7414
7415         if (!is_all_drained) {
7416                 LOGD("Wait util the all pads get EOS.");
7417                 MMPLAYER_CMD_UNLOCK(player);
7418                 MMPLAYER_FLEAVE();
7419                 return;
7420         }
7421
7422         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_AUDIO] = FALSE;
7423         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
7424
7425         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
7426         MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */
7427         __mmplayer_deactivate_old_path(player);
7428         MMPLAYER_CMD_UNLOCK(player);
7429
7430         MMPLAYER_FLEAVE();
7431 }
7432
7433 void
7434 __mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
7435 {
7436         mm_player_t* player = (mm_player_t*)data;
7437         const gchar* klass = NULL;
7438         gchar* factory_name = NULL;
7439
7440         klass = gst_element_factory_get_metadata(gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
7441         factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
7442
7443         LOGD("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
7444
7445         if (__mmplayer_add_dump_buffer_probe(player, element))
7446                 LOGD("add buffer probe");
7447
7448         //<-
7449         if (g_strrstr(klass, "Codec/Decoder/Audio")) {
7450                 gchar* selected = NULL;
7451                 selected = g_strdup(GST_ELEMENT_NAME(element));
7452                 player->audio_decoders = g_list_append(player->audio_decoders, selected);
7453         }
7454         //-> temp code
7455
7456         if (g_strrstr(klass, "Parser")) {
7457                 gchar* selected = NULL;
7458
7459                 selected = g_strdup(factory_name);
7460                 player->parsers = g_list_append(player->parsers, selected);
7461         }
7462
7463         if (g_strrstr(klass, "Demuxer/Adaptive")) {
7464                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
7465                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
7466
7467                 LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth,
7468                                                 player->adaptive_info.limit.width, player->adaptive_info.limit.height);
7469
7470                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
7471                                                 "max-bandwidth", player->adaptive_info.limit.bandwidth,
7472                                                 "max-video-width", player->adaptive_info.limit.width,
7473                                                 "max-video-height", player->adaptive_info.limit.height, NULL);
7474
7475         } else if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) {
7476                 /* FIXIT : first value will be overwritten if there's more
7477                  * than 1 demuxer/parser
7478                  */
7479
7480                 //LOGD("plugged element is demuxer. take it\n");
7481                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
7482                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
7483
7484                 /*Added for multi audio support */ // Q. del?
7485                 if (g_strrstr(klass, "Demux")) {
7486                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
7487                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
7488                 }
7489         }
7490
7491         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
7492                 int surface_type = 0;
7493
7494                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
7495         }
7496
7497         // to support trust-zone only
7498         if (g_strrstr(factory_name, "asfdemux")) {
7499                 LOGD("set file-location %s\n", player->profile.uri);
7500                 g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
7501
7502                 if (player->video_hub_download_mode == TRUE)
7503                         g_object_set(G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
7504         } else if (g_strrstr(factory_name, "legacyh264parse")) {
7505                 LOGD("[%s] output-format to legacyh264parse\n", "mssdemux");
7506                 g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
7507         } else if (g_strrstr(factory_name, "mpegaudioparse")) {
7508                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
7509                         (__mmplayer_is_only_mp3_type(player->type))) {
7510                         LOGD("[mpegaudioparse] set streaming pull mode.");
7511                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
7512                 }
7513         } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
7514                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
7515         }
7516
7517         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
7518                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
7519                 LOGD("plugged element is multiqueue. take it %s", GST_ELEMENT_NAME(element));
7520
7521                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
7522                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
7523
7524                 if (!MMPLAYER_IS_HTTP_PD(player) &&
7525                         ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
7526                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) ||
7527                         (MMPLAYER_IS_DASH_STREAMING(player)))) {
7528                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
7529                         __mm_player_streaming_set_multiqueue(player->streamer, element, player->ini.http_buffering_time, 1.0, player->ini.http_buffering_limit);
7530                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
7531                 }
7532
7533         }
7534
7535         return;
7536 }
7537
7538 static void
7539 __mmplayer_release_misc(mm_player_t* player)
7540 {
7541         int i;
7542         bool cur_mode = player->set_mode.rich_audio;
7543         MMPLAYER_FENTER();
7544
7545         MMPLAYER_RETURN_IF_FAIL(player);
7546
7547         player->video_stream_cb = NULL;
7548         player->video_stream_cb_user_param = NULL;
7549         player->video_stream_prerolled = FALSE;
7550
7551         player->audio_stream_render_cb = NULL;
7552         player->audio_stream_cb_user_param = NULL;
7553         player->audio_stream_sink_sync = false;
7554
7555         player->video_stream_changed_cb = NULL;
7556         player->video_stream_changed_cb_user_param = NULL;
7557
7558         player->audio_stream_changed_cb = NULL;
7559         player->audio_stream_changed_cb_user_param = NULL;
7560
7561         player->sent_bos = FALSE;
7562         player->playback_rate = DEFAULT_PLAYBACK_RATE;
7563
7564         player->seek_state = MMPLAYER_SEEK_NONE;
7565
7566         player->total_bitrate = 0;
7567         player->total_maximum_bitrate = 0;
7568
7569         player->not_found_demuxer = 0;
7570
7571         player->last_position = 0;
7572         player->duration = 0;
7573         player->http_content_size = 0;
7574         player->not_supported_codec = MISSING_PLUGIN_NONE;
7575         player->can_support_codec = FOUND_PLUGIN_NONE;
7576         player->pending_seek.is_pending = FALSE;
7577         player->pending_seek.pos = 0;
7578         player->msg_posted = FALSE;
7579         player->has_many_types = FALSE;
7580         player->is_subtitle_force_drop = FALSE;
7581         player->play_subtitle = FALSE;
7582         player->adjust_subtitle_pos = 0;
7583         player->last_multiwin_status = FALSE;
7584         player->has_closed_caption = FALSE;
7585         player->set_mode.media_packet_video_stream = FALSE;
7586         player->profile.uri_type = MM_PLAYER_URI_TYPE_NONE;
7587         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
7588         /* recover mode */
7589         player->set_mode.rich_audio = cur_mode;
7590
7591         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
7592                 player->bitrate[i] = 0;
7593                 player->maximum_bitrate[i] = 0;
7594         }
7595
7596         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
7597
7598         /* remove media stream cb(appsrc cb) */
7599         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) {
7600                 player->media_stream_buffer_status_cb[i] = NULL;
7601                 player->media_stream_seek_data_cb[i] = NULL;
7602                 player->buffer_cb_user_param[i] = NULL;
7603                 player->seek_cb_user_param[i] = NULL;
7604         }
7605         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
7606
7607         /* free memory related to audio effect */
7608         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
7609
7610         if (player->adaptive_info.var_list) {
7611                 g_list_free_full(player->adaptive_info.var_list, g_free);
7612                 player->adaptive_info.var_list = NULL;
7613         }
7614
7615         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
7616         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
7617         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
7618
7619         /* Reset video360 settings to their defaults in case if the pipeline is to be
7620          * re-created.
7621          * */
7622         player->video360_metadata.is_spherical = -1;
7623         player->is_openal_plugin_used = FALSE;
7624
7625         player->is_content_spherical = FALSE;
7626         player->is_video360_enabled = TRUE;
7627         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
7628         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
7629         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
7630         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
7631         player->video360_zoom = 1.0f;
7632         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
7633         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
7634
7635         player->sound.rg_enable = false;
7636
7637         __mmplayer_initialize_video_roi(player);
7638         MMPLAYER_FLEAVE();
7639 }
7640
7641 static void
7642 __mmplayer_release_misc_post(mm_player_t* player)
7643 {
7644         char *original_uri = NULL;
7645         MMPLAYER_FENTER();
7646
7647         /* player->pipeline is already released before. */
7648
7649         MMPLAYER_RETURN_IF_FAIL(player);
7650
7651         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
7652
7653         /* clean found parsers */
7654         if (player->parsers) {
7655                 GList *parsers = player->parsers;
7656                 for (; parsers; parsers = g_list_next(parsers)) {
7657                         gchar *name = parsers->data;
7658                         MMPLAYER_FREEIF(name);
7659                 }
7660                 g_list_free(player->parsers);
7661                 player->parsers = NULL;
7662         }
7663
7664         /* clean found audio decoders */
7665         if (player->audio_decoders) {
7666                 GList *a_dec = player->audio_decoders;
7667                 for (; a_dec; a_dec = g_list_next(a_dec)) {
7668                         gchar *name = a_dec->data;
7669                         MMPLAYER_FREEIF(name);
7670                 }
7671                 g_list_free(player->audio_decoders);
7672                 player->audio_decoders = NULL;
7673         }
7674
7675         /* clean the uri list except original uri */
7676         if (player->uri_info.uri_list) {
7677                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
7678
7679                 if (player->attrs) {
7680                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
7681                         LOGD("restore original uri = %s\n", original_uri);
7682
7683                         if (mmf_attrs_commit(player->attrs))
7684                                 LOGE("failed to commit the original uri.\n");
7685                 }
7686
7687                 GList *uri_list = player->uri_info.uri_list;
7688                 for (; uri_list; uri_list = g_list_next(uri_list)) {
7689                         gchar *uri = uri_list->data;
7690                         MMPLAYER_FREEIF(uri);
7691                 }
7692                 g_list_free(player->uri_info.uri_list);
7693                 player->uri_info.uri_list = NULL;
7694         }
7695
7696         /* clear the audio stream buffer list */
7697         __mmplayer_audio_stream_clear_buffer(player, FALSE);
7698
7699         /* clear the video stream bo list */
7700         __mmplayer_video_stream_destroy_bo_list(player);
7701         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
7702
7703         if (player->profile.input_mem.buf) {
7704                 free(player->profile.input_mem.buf);
7705                 player->profile.input_mem.buf = NULL;
7706         }
7707         player->profile.input_mem.len = 0;
7708         player->profile.input_mem.offset = 0;
7709
7710         player->uri_info.uri_idx = 0;
7711         MMPLAYER_FLEAVE();
7712 }
7713
7714 gboolean
7715 __mmplayer_check_subtitle(mm_player_t* player)
7716 {
7717         MMHandleType attrs = 0;
7718         char *subtitle_uri = NULL;
7719
7720         MMPLAYER_FENTER();
7721
7722         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
7723
7724         /* get subtitle attribute */
7725         attrs = MMPLAYER_GET_ATTRS(player);
7726         if (!attrs)
7727                 return FALSE;
7728
7729         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
7730         if (!subtitle_uri || !strlen(subtitle_uri))
7731                 return FALSE;
7732
7733         SECURE_LOGD("subtitle uri is %s[%d]", subtitle_uri, strlen(subtitle_uri));
7734         player->is_external_subtitle_present = TRUE;
7735
7736         MMPLAYER_FLEAVE();
7737
7738         return TRUE;
7739 }
7740
7741 void
7742 __mmplayer_cancel_eos_timer(mm_player_t* player)
7743 {
7744         MMPLAYER_RETURN_IF_FAIL(player);
7745
7746         if (player->eos_timer) {
7747                 LOGD("cancel eos timer");
7748                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
7749                 player->eos_timer = 0;
7750         }
7751
7752         return;
7753 }
7754
7755 static void
7756 __mmplayer_add_sink(mm_player_t* player, GstElement* sink)
7757 {
7758         MMPLAYER_FENTER();
7759
7760         MMPLAYER_RETURN_IF_FAIL(player);
7761         MMPLAYER_RETURN_IF_FAIL(sink);
7762
7763         player->sink_elements =
7764                 g_list_append(player->sink_elements, sink);
7765
7766         MMPLAYER_FLEAVE();
7767 }
7768
7769 static void
7770 __mmplayer_del_sink(mm_player_t* player, GstElement* sink)
7771 {
7772         MMPLAYER_FENTER();
7773
7774         MMPLAYER_RETURN_IF_FAIL(player);
7775         MMPLAYER_RETURN_IF_FAIL(sink);
7776
7777         player->sink_elements =
7778                         g_list_remove(player->sink_elements, sink);
7779
7780         MMPLAYER_FLEAVE();
7781 }
7782
7783 void
7784 __mmplayer_add_signal_connection(mm_player_t* player, GObject* object,
7785                         MMPlayerSignalType type, const gchar* signal, GCallback cb_funct, gpointer u_data)
7786 {
7787         MMPlayerSignalItem* item = NULL;
7788
7789         MMPLAYER_FENTER();
7790         MMPLAYER_RETURN_IF_FAIL(player);
7791
7792         if (type >= MM_PLAYER_SIGNAL_TYPE_MAX) {
7793                 LOGE("invalid signal type [%d]", type);
7794                 return;
7795         }
7796
7797         item = (MMPlayerSignalItem*)g_malloc(sizeof(MMPlayerSignalItem));
7798         if (!item) {
7799                 LOGE("cannot connect signal [%s]", signal);
7800                 return;
7801         }
7802
7803         item->obj = object;
7804         item->sig = g_signal_connect(object, signal, cb_funct, u_data);
7805         player->signals[type] = g_list_append(player->signals[type], item);
7806
7807         MMPLAYER_FLEAVE();
7808         return;
7809 }
7810
7811 /* NOTE : be careful with calling this api. please refer to below glib comment
7812  * glib comment : Note that there is a bug in GObject that makes this function much
7813  * less useful than it might seem otherwise. Once gobject is disposed, the callback
7814  * will no longer be called, but, the signal handler is not currently disconnected.
7815  * If the instance is itself being freed at the same time than this doesn't matter,
7816  * since the signal will automatically be removed, but if instance persists,
7817  * then the signal handler will leak. You should not remove the signal yourself
7818  * because in a future versions of GObject, the handler will automatically be
7819  * disconnected.
7820  *
7821  * It's possible to work around this problem in a way that will continue to work
7822  * with future versions of GObject by checking that the signal handler is still
7823  * connected before disconnected it:
7824  *
7825  *  if (g_signal_handler_is_connected(instance, id))
7826  *    g_signal_handler_disconnect(instance, id);
7827  */
7828 static void
7829 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
7830 {
7831         GList* sig_list = NULL;
7832         MMPlayerSignalItem* item = NULL;
7833
7834         MMPLAYER_FENTER();
7835
7836         MMPLAYER_RETURN_IF_FAIL(player);
7837
7838         LOGD("release signals type : %d", type);
7839
7840         if (type >= MM_PLAYER_SIGNAL_TYPE_ALL) {
7841                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
7842                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
7843                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
7844                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
7845                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
7846                 return;
7847         }
7848
7849         sig_list = player->signals[type];
7850
7851         for (; sig_list; sig_list = sig_list->next) {
7852                 item = sig_list->data;
7853
7854                 if (item && item->obj && GST_IS_ELEMENT(item->obj)) {
7855                         if (g_signal_handler_is_connected(item->obj, item->sig))
7856                                 g_signal_handler_disconnect(item->obj, item->sig);
7857                 }
7858
7859                 MMPLAYER_FREEIF(item);
7860         }
7861
7862         g_list_free(player->signals[type]);
7863         player->signals[type] = NULL;
7864
7865         MMPLAYER_FLEAVE();
7866
7867         return;
7868 }
7869
7870 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
7871 {
7872         mm_player_t* player = 0;
7873         int prev_display_surface_type = 0;
7874         void *prev_display_overlay = NULL;
7875
7876         MMPLAYER_FENTER();
7877
7878         MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
7879         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
7880
7881         player = MM_PLAYER_CAST(handle);
7882
7883         /* check video sinkbin is created */
7884         if (__mmplayer_video_param_check_video_sink_bin(player) == MM_ERROR_NONE) {
7885                 LOGE("Videosink is already created");
7886                 return MM_ERROR_NONE;
7887         }
7888
7889         LOGD("videosink element is not yet ready");
7890
7891         if (surface_type >= MM_DISPLAY_SURFACE_NUM) {
7892                 LOGE("Not support this surface type(%d) for changing vidoesink", surface_type);
7893                 MMPLAYER_FLEAVE();
7894                 return MM_ERROR_INVALID_ARGUMENT;
7895         }
7896
7897         /* load previous attributes */
7898         if (player->attrs) {
7899                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &prev_display_surface_type);
7900                 mm_attrs_get_data_by_name(player->attrs, "display_overlay", &prev_display_overlay);
7901                 LOGD("[0: Video surface, 4: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
7902                 if (prev_display_surface_type == surface_type) {
7903                         LOGD("incoming display surface type is same as previous one, do nothing..");
7904                         MMPLAYER_FLEAVE();
7905                         return MM_ERROR_NONE;
7906                 }
7907         } else {
7908                 LOGE("failed to load attributes");
7909                 MMPLAYER_FLEAVE();
7910                 return MM_ERROR_PLAYER_INTERNAL;
7911         }
7912
7913         /* videobin is not created yet, so we just set attributes related to display surface */
7914         LOGD("store display attribute for given surface type(%d)", surface_type);
7915         mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
7916         mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
7917         if (mmf_attrs_commit(player->attrs)) {
7918                 LOGE("failed to commit attribute");
7919                 MMPLAYER_FLEAVE();
7920                 return MM_ERROR_PLAYER_INTERNAL;
7921         }
7922
7923         MMPLAYER_FLEAVE();
7924         return MM_ERROR_NONE;
7925 }
7926
7927 /* Note : if silent is true, then subtitle would not be displayed. :*/
7928 int _mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
7929 {
7930         mm_player_t* player = (mm_player_t*) hplayer;
7931
7932         MMPLAYER_FENTER();
7933
7934         /* check player handle */
7935         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7936
7937         player->set_mode.subtitle_off = silent;
7938
7939         LOGD("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
7940
7941         MMPLAYER_FLEAVE();
7942
7943         return MM_ERROR_NONE;
7944 }
7945
7946 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
7947 {
7948         MMPlayerGstElement* mainbin = NULL;
7949         MMPlayerGstElement* textbin = NULL;
7950         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
7951         GstState current_state = GST_STATE_VOID_PENDING;
7952         GstState element_state = GST_STATE_VOID_PENDING;
7953         GstState element_pending_state = GST_STATE_VOID_PENDING;
7954         gint64 time = 0;
7955         GstEvent *event = NULL;
7956         int result = MM_ERROR_NONE;
7957
7958         GstClock *curr_clock = NULL;
7959         GstClockTime base_time, start_time, curr_time;
7960
7961
7962         MMPLAYER_FENTER();
7963
7964         /* check player handle */
7965         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
7966                                                                 player->pipeline &&
7967                                                                 player->pipeline->mainbin &&
7968                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7969
7970         mainbin = player->pipeline->mainbin;
7971         textbin = player->pipeline->textbin;
7972
7973         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
7974
7975         // sync clock with current pipeline
7976         curr_clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
7977         curr_time = gst_clock_get_time(curr_clock);
7978
7979         base_time = gst_element_get_base_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7980         start_time = gst_element_get_start_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7981
7982         LOGD("state: %d, base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
7983                 current_state, GST_TIME_ARGS(base_time), GST_TIME_ARGS(start_time), GST_TIME_ARGS(curr_time));
7984
7985         if (current_state > GST_STATE_READY) {
7986                 // sync state with current pipeline
7987                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
7988                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
7989                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
7990
7991                 ret = gst_element_get_state(mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
7992                 if (GST_STATE_CHANGE_FAILURE == ret) {
7993                         LOGE("fail to state change.\n");
7994                         result = MM_ERROR_PLAYER_INTERNAL;
7995                         goto ERROR;
7996                 }
7997         }
7998
7999         gst_element_set_base_time(textbin[MMPLAYER_T_BIN].gst, base_time);
8000         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
8001
8002         if (curr_clock) {
8003                 gst_element_set_clock(textbin[MMPLAYER_T_BIN].gst, curr_clock);
8004                 gst_object_unref(curr_clock);
8005         }
8006
8007         // seek to current position
8008         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
8009                 result = MM_ERROR_PLAYER_INVALID_STATE;
8010                 LOGE("gst_element_query_position failed, invalid state\n");
8011                 goto ERROR;
8012         }
8013
8014         LOGD("seek time = %"G_GINT64_FORMAT", rate = %f", time, player->playback_rate);
8015         event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
8016         if (event) {
8017                 __mmplayer_gst_send_event_to_sink(player, event);
8018         } else {
8019                 result = MM_ERROR_PLAYER_INTERNAL;
8020                 LOGE("gst_event_new_seek failed"); /* pipeline will got error and can not be recovered */
8021                 goto ERROR;
8022         }
8023
8024         /* sync state with current pipeline */
8025         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
8026         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
8027         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
8028
8029         return MM_ERROR_NONE;
8030
8031 ERROR:
8032         /* release text pipeline resource */
8033         player->textsink_linked = 0;
8034
8035         /* release signal */
8036         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
8037
8038         /* release textbin with it's childs */
8039         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
8040         MMPLAYER_FREEIF(player->pipeline->textbin);
8041         player->pipeline->textbin = NULL;
8042
8043         /* release subtitle elem */
8044         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
8045         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
8046
8047         return result;
8048 }
8049
8050 static int
8051 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
8052 {
8053         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
8054         GstState current_state = GST_STATE_VOID_PENDING;
8055
8056         MMHandleType attrs = 0;
8057         MMPlayerGstElement* mainbin = NULL;
8058         MMPlayerGstElement* textbin = NULL;
8059
8060         gchar* subtitle_uri = NULL;
8061         int result = MM_ERROR_NONE;
8062         const gchar *charset = NULL;
8063
8064         MMPLAYER_FENTER();
8065
8066         /* check player handle */
8067         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
8068                                                                 player->pipeline &&
8069                                                                 player->pipeline->mainbin &&
8070                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
8071         MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
8072
8073         mainbin = player->pipeline->mainbin;
8074         textbin = player->pipeline->textbin;
8075
8076         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
8077         if (current_state < GST_STATE_READY) {
8078                 result = MM_ERROR_PLAYER_INVALID_STATE;
8079                 LOGE("Pipeline is not in proper state\n");
8080                 goto EXIT;
8081         }
8082
8083         attrs = MMPLAYER_GET_ATTRS(player);
8084         if (!attrs) {
8085                 LOGE("cannot get content attribute\n");
8086                 result = MM_ERROR_PLAYER_INTERNAL;
8087                 goto EXIT;
8088         }
8089
8090         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
8091         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
8092                 LOGE("subtitle uri is not proper filepath\n");
8093                 result = MM_ERROR_PLAYER_INVALID_URI;
8094                 goto EXIT;
8095         }
8096
8097         if (!util_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) {
8098                 LOGE("failed to get storage info of subtitle path");
8099                 result = MM_ERROR_PLAYER_INVALID_URI;
8100                 goto EXIT;
8101         }
8102
8103         LOGD("old subtitle file path is [%s]\n", subtitle_uri);
8104         LOGD("new subtitle file path is [%s]\n", filepath);
8105
8106         if (!strcmp(filepath, subtitle_uri)) {
8107                 LOGD("No need to swtich subtitle, as input filepath is same as current filepath\n");
8108                 goto EXIT;
8109         } else {
8110                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
8111                 if (mmf_attrs_commit(player->attrs)) {
8112                         LOGE("failed to commit.\n");
8113                         goto EXIT;
8114                 }
8115         }
8116
8117         //gst_pad_set_blocked_async(src-srcpad, TRUE)
8118         MMPLAYER_SUBTITLE_INFO_LOCK(player);
8119         player->subtitle_language_list = NULL;
8120         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
8121
8122         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
8123         if (ret != GST_STATE_CHANGE_SUCCESS) {
8124                 LOGE("failed to change state of textbin to READY");
8125                 result = MM_ERROR_PLAYER_INTERNAL;
8126                 goto EXIT;
8127         }
8128
8129         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
8130         if (ret != GST_STATE_CHANGE_SUCCESS) {
8131                 LOGE("failed to change state of subparse to READY");
8132                 result = MM_ERROR_PLAYER_INTERNAL;
8133                 goto EXIT;
8134         }
8135
8136         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
8137         if (ret != GST_STATE_CHANGE_SUCCESS) {
8138                 LOGE("failed to change state of filesrc to READY");
8139                 result = MM_ERROR_PLAYER_INTERNAL;
8140                 goto EXIT;
8141         }
8142
8143         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_TEXT);
8144
8145         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
8146
8147         charset = util_get_charset(filepath);
8148         if (charset) {
8149                 LOGD("detected charset is %s\n", charset);
8150                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
8151         }
8152
8153         result = _mmplayer_sync_subtitle_pipeline(player);
8154
8155 EXIT:
8156         MMPLAYER_FLEAVE();
8157         return result;
8158 }
8159
8160 /* API to switch between external subtitles */
8161 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
8162 {
8163         int result = MM_ERROR_NONE;
8164         mm_player_t* player = (mm_player_t*)hplayer;
8165         char *path = NULL;
8166
8167         MMPLAYER_FENTER();
8168
8169         /* check player handle */
8170         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8171
8172         /* filepath can be null in idle state */
8173         if (filepath) {
8174                 /* check file path */
8175                 if ((path = strstr(filepath, "file://")))
8176                         result = util_exist_file_path(path + 7);
8177                 else
8178                         result = util_exist_file_path(filepath);
8179
8180                 if (result != MM_ERROR_NONE) {
8181                         LOGE("invalid subtitle path 0x%X", result);
8182                         return result; /* file not found or permission denied */
8183                 }
8184         }
8185
8186         if (!player->pipeline) {
8187                 /* IDLE state */
8188                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
8189                 if (mmf_attrs_commit(player->attrs)) {
8190                         LOGE("failed to commit");       /* subtitle path will not be created */
8191                         return MM_ERROR_PLAYER_INTERNAL;
8192                 }
8193         } else {
8194                 /* cur state <> IDLE(READY, PAUSE, PLAYING..) */
8195                 /* check filepath */
8196                 MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
8197
8198                 if (!__mmplayer_check_subtitle(player)) {
8199                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
8200                         if (mmf_attrs_commit(player->attrs)) {
8201                                 LOGE("failed to commit");
8202                                 return MM_ERROR_PLAYER_INTERNAL;
8203                         }
8204
8205                         if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) {
8206                                 LOGE("fail to create text pipeline");
8207                                 return MM_ERROR_PLAYER_INTERNAL;
8208                         }
8209
8210                         result = _mmplayer_sync_subtitle_pipeline(player);
8211                 } else {
8212                         result = __mmplayer_change_external_subtitle_language(player, filepath);
8213                 }
8214
8215                 MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
8216                 player->is_external_subtitle_added_now = TRUE;
8217
8218                 MMPLAYER_SUBTITLE_INFO_LOCK(player);
8219                 if (!player->subtitle_language_list) {
8220                         gint64 timeout = g_get_monotonic_time() + G_TIME_SPAN_SECOND; /* wait 1 sec */
8221                         if (!MMPLAYER_SUBTITLE_INFO_WAIT_UNTIL(player, timeout))
8222                                 LOGW("subtitle language list is not updated yet");
8223                 }
8224                 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
8225         }
8226
8227         MMPLAYER_FLEAVE();
8228         return result;
8229 }
8230
8231 static int
8232 __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index)
8233 {
8234         int result = MM_ERROR_NONE;
8235         gchar* change_pad_name = NULL;
8236         GstPad* sinkpad = NULL;
8237         MMPlayerGstElement* mainbin = NULL;
8238         enum MainElementID elem_idx = MMPLAYER_M_NUM;
8239         GstCaps* caps = NULL;
8240         gint total_track_num = 0;
8241
8242         MMPLAYER_FENTER();
8243
8244         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin,
8245                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
8246
8247         LOGD("Change Track(%d) to %d\n", type, index);
8248
8249         mainbin = player->pipeline->mainbin;
8250
8251         if (type == MM_PLAYER_TRACK_TYPE_AUDIO) {
8252                 elem_idx = MMPLAYER_M_A_INPUT_SELECTOR;
8253         } else if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
8254                 elem_idx = MMPLAYER_M_T_INPUT_SELECTOR;
8255         } else {
8256                 /* Changing Video Track is not supported. */
8257                 LOGE("Track Type Error\n");
8258                 goto EXIT;
8259         }
8260
8261         if (mainbin[elem_idx].gst == NULL) {
8262                 result = MM_ERROR_PLAYER_NO_OP;
8263                 LOGD("Req track doesn't exist\n");
8264                 goto EXIT;
8265         }
8266
8267         total_track_num = player->selector[type].total_track_num;
8268         if (total_track_num <= 0) {
8269                 result = MM_ERROR_PLAYER_NO_OP;
8270                 LOGD("Language list is not available \n");
8271                 goto EXIT;
8272         }
8273
8274         if ((index < 0) || (index >= total_track_num)) {
8275                 result = MM_ERROR_INVALID_ARGUMENT;
8276                 LOGD("Not a proper index : %d \n", index);
8277                 goto EXIT;
8278         }
8279
8280         /*To get the new pad from the selector*/
8281         change_pad_name = g_strdup_printf("sink_%u", index);
8282         if (change_pad_name == NULL) {
8283                 result = MM_ERROR_PLAYER_INTERNAL;
8284                 LOGD("Pad does not exists\n");
8285                 goto EXIT;
8286         }
8287
8288         LOGD("new active pad name: %s\n", change_pad_name);
8289
8290         sinkpad = gst_element_get_static_pad(mainbin[elem_idx].gst, change_pad_name);
8291         if (sinkpad == NULL) {
8292                 LOGD("sinkpad is NULL");
8293                 result = MM_ERROR_PLAYER_INTERNAL;
8294                 goto EXIT;
8295         }
8296
8297         LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
8298         g_object_set(mainbin[elem_idx].gst, "active-pad", sinkpad, NULL);
8299
8300         caps = gst_pad_get_current_caps(sinkpad);
8301         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
8302
8303         if (sinkpad)
8304                 gst_object_unref(sinkpad);
8305
8306         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
8307                 __mmplayer_set_audio_attrs(player, caps);
8308
8309 EXIT:
8310
8311         MMPLAYER_FREEIF(change_pad_name);
8312         return result;
8313 }
8314
8315 int _mmplayer_change_track_language(MMHandleType hplayer, MMPlayerTrackType type, int index)
8316 {
8317         int result = MM_ERROR_NONE;
8318         mm_player_t* player = NULL;
8319         MMPlayerGstElement* mainbin = NULL;
8320
8321         gint current_active_index = 0;
8322
8323         GstState current_state = GST_STATE_VOID_PENDING;
8324         GstEvent* event = NULL;
8325         gint64 time = 0;
8326
8327         MMPLAYER_FENTER();
8328
8329         player = (mm_player_t*)hplayer;
8330         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8331
8332         if (!player->pipeline) {
8333                 LOGE("Track %d pre setting -> %d\n", type, index);
8334
8335                 player->selector[type].active_pad_index = index;
8336                 goto EXIT;
8337         }
8338
8339         mainbin = player->pipeline->mainbin;
8340
8341         current_active_index = player->selector[type].active_pad_index;
8342
8343         /*If index is same as running index no need to change the pad*/
8344         if (current_active_index == index)
8345                 goto EXIT;
8346
8347         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
8348                 result = MM_ERROR_PLAYER_INVALID_STATE;
8349                 goto EXIT;
8350         }
8351
8352         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
8353         if (current_state < GST_STATE_PAUSED) {
8354                 result = MM_ERROR_PLAYER_INVALID_STATE;
8355                 LOGW("Pipeline not in porper state\n");
8356                 goto EXIT;
8357         }
8358
8359         result = __mmplayer_change_selector_pad(player, type, index);
8360         if (result != MM_ERROR_NONE) {
8361                 LOGE("change selector pad error\n");
8362                 goto EXIT;
8363         }
8364
8365         player->selector[type].active_pad_index = index;
8366
8367         if (current_state == GST_STATE_PLAYING) {
8368                 event = gst_event_new_seek(player->playback_rate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SKIP), GST_SEEK_TYPE_SET, time, GST_SEEK_TYPE_NONE, -1);
8369                 if (event) {
8370                         __mmplayer_gst_send_event_to_sink(player, event);
8371                 } else {
8372                         result = MM_ERROR_PLAYER_INTERNAL;
8373                         goto EXIT;
8374                 }
8375         }
8376
8377 EXIT:
8378         return result;
8379 }
8380
8381 int _mmplayer_get_subtitle_silent(MMHandleType hplayer, int* silent)
8382 {
8383         mm_player_t* player = (mm_player_t*) hplayer;
8384
8385         MMPLAYER_FENTER();
8386
8387         /* check player handle */
8388         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8389
8390         *silent = player->set_mode.subtitle_off;
8391
8392         LOGD("subtitle is %s.\n", silent ? "ON" : "OFF");
8393
8394         MMPLAYER_FLEAVE();
8395
8396         return MM_ERROR_NONE;
8397 }
8398
8399 int
8400 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
8401 {
8402         mm_player_t* player = (mm_player_t*) hplayer;
8403
8404         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8405
8406         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL) {
8407                 MMPLAYER_PRINT_STATE(player);
8408                 LOGE("wrong-state : can't set the download mode to parse");
8409                 return MM_ERROR_PLAYER_INVALID_STATE;
8410         }
8411
8412         LOGD("set video hub download mode to %s", (mode) ? "ON" : "OFF");
8413         player->video_hub_download_mode = mode;
8414
8415         return MM_ERROR_NONE;
8416 }
8417
8418 int
8419 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
8420 {
8421         mm_player_t* player = (mm_player_t*) hplayer;
8422
8423         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8424
8425         LOGD("enable sync handler : %s", (enable) ? "ON" : "OFF");
8426         player->sync_handler = enable;
8427
8428         return MM_ERROR_NONE;
8429 }
8430
8431 static gboolean
8432 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
8433 {
8434         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
8435         MMPLAYER_RETURN_VAL_IF_FAIL(element, FALSE);
8436
8437         gchar *factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
8438         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
8439
8440         int idx = 0;
8441
8442         for (idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++) {
8443                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx])) {
8444                         LOGD("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
8445                         mm_player_dump_t *dump_s;
8446                         dump_s = g_malloc(sizeof(mm_player_dump_t));
8447
8448                         if (dump_s == NULL) {
8449                                 LOGE("malloc fail");
8450                                 return FALSE;
8451                         }
8452
8453                         dump_s->dump_element_file = NULL;
8454                         dump_s->dump_pad = NULL;
8455                         dump_s->dump_pad = gst_element_get_static_pad(element, "sink");
8456
8457                         if (dump_s->dump_pad) {
8458                                 memset(dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
8459                                 snprintf(dump_file_name, PLAYER_INI_MAX_STRLEN*2, "%s/%s_sink_pad.dump", player->ini.dump_element_path, player->ini.dump_element_keyword[idx]);
8460                                 dump_s->dump_element_file = fopen(dump_file_name, "w+");
8461                                 dump_s->probe_handle_id = gst_pad_add_probe(dump_s->dump_pad, GST_PAD_PROBE_TYPE_BUFFER, __mmplayer_dump_buffer_probe_cb, dump_s->dump_element_file, NULL);
8462                                 /* add list for removed buffer probe and close FILE */
8463                                 player->dump_list = g_list_append(player->dump_list, dump_s);
8464                                 LOGD("%s sink pad added buffer probe for dump", factory_name);
8465                                 return TRUE;
8466                         } else {
8467                                 g_free(dump_s);
8468                                 dump_s = NULL;
8469                                 LOGE("failed to get %s sink pad added", factory_name);
8470                         }
8471
8472
8473                 }
8474         }
8475         return FALSE;
8476 }
8477
8478 static GstPadProbeReturn
8479 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
8480 {
8481         FILE *dump_data = (FILE *) u_data;
8482 //      int written = 0;
8483         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
8484         GstMapInfo probe_info = GST_MAP_INFO_INIT;
8485
8486         MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, FALSE);
8487
8488         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
8489
8490 //      LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
8491
8492         fwrite(probe_info.data, 1, probe_info.size , dump_data);
8493
8494         return GST_PAD_PROBE_OK;
8495 }
8496
8497 static void
8498 __mmplayer_release_dump_list(GList *dump_list)
8499 {
8500         if (dump_list) {
8501                 GList *d_list = dump_list;
8502                 for (; d_list; d_list = g_list_next(d_list)) {
8503                         mm_player_dump_t *dump_s = d_list->data;
8504                         if (dump_s->dump_pad) {
8505                                 if (dump_s->probe_handle_id)
8506                                         gst_pad_remove_probe(dump_s->dump_pad, dump_s->probe_handle_id);
8507                         }
8508                         if (dump_s->dump_element_file) {
8509                                 fclose(dump_s->dump_element_file);
8510                                 dump_s->dump_element_file = NULL;
8511                         }
8512                         MMPLAYER_FREEIF(dump_s);
8513                 }
8514                 g_list_free(dump_list);
8515                 dump_list = NULL;
8516         }
8517 }
8518
8519 int
8520 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
8521 {
8522         mm_player_t* player = (mm_player_t*) hplayer;
8523
8524         MMPLAYER_FENTER();
8525
8526         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8527         MMPLAYER_RETURN_VAL_IF_FAIL(exist, MM_ERROR_INVALID_ARGUMENT);
8528
8529         *exist = player->has_closed_caption;
8530
8531         MMPLAYER_FLEAVE();
8532
8533         return MM_ERROR_NONE;
8534 }
8535
8536 void _mm_player_video_stream_internal_buffer_unref(void *buffer)
8537 {
8538         MMPLAYER_FENTER();
8539         if (buffer) {
8540                 // LOGD("unref internal gst buffer %p", buffer);
8541                 gst_buffer_unref((GstBuffer *)buffer);
8542                 buffer = NULL;
8543         }
8544         MMPLAYER_FLEAVE();
8545 }
8546
8547 int _mmplayer_get_timeout(MMHandleType hplayer, int *timeout)
8548 {
8549         mm_player_t* player = (mm_player_t*) hplayer;
8550
8551         MMPLAYER_FENTER();
8552
8553         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8554         MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
8555
8556         if (MMPLAYER_IS_HTTP_PD(player))
8557                 /* consider the timeout both download pipeline and playback pipeline */
8558                 *timeout = player->ini.live_state_change_timeout + PLAYER_PD_STATE_CHANGE_TIME;
8559         else if (MMPLAYER_IS_STREAMING(player))
8560                 *timeout = player->ini.live_state_change_timeout;
8561         else
8562                 *timeout = player->ini.localplayback_state_change_timeout;
8563
8564         LOGD("timeout = %d\n", *timeout);
8565
8566         MMPLAYER_FLEAVE();
8567         return MM_ERROR_NONE;
8568 }
8569
8570 int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
8571 {
8572         mm_player_t* player = (mm_player_t*) hplayer;
8573
8574         MMPLAYER_FENTER();
8575
8576         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8577         MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT);
8578
8579         *num = player->video_num_buffers;
8580         *extra_num = player->video_extra_num_buffers;
8581
8582         LOGD("state %d, num %d(%d)\n", MMPLAYER_CURRENT_STATE(player), *num, *extra_num);
8583
8584         MMPLAYER_FLEAVE();
8585         return MM_ERROR_NONE;
8586 }
8587
8588 static void
8589 __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type)
8590 {
8591         int i = 0;
8592         MMPLAYER_FENTER();
8593         MMPLAYER_RETURN_IF_FAIL(player);
8594
8595         for (i = 0; i < MMPLAYER_PATH_MAX; i++) {
8596
8597                 if (path_type == MMPLAYER_PATH_MAX || path_type == i) {
8598                         player->storage_info[i].type = STORAGE_TYPE_INTERNAL;
8599                         player->storage_info[i].state = STORAGE_STATE_UNMOUNTABLE;
8600                         player->storage_info[i].id = -1;
8601                         memset(player->storage_info[i].path, 0x00, MM_MAX_URL_LEN);
8602
8603                         if (path_type != MMPLAYER_PATH_MAX)
8604                                 break;
8605                 }
8606         }
8607
8608         MMPLAYER_FLEAVE();
8609 }
8610
8611 int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int id, int state)
8612 {
8613         int ret = MM_ERROR_NONE;
8614         mm_player_t* player = (mm_player_t*)hplayer;
8615         MMMessageParamType msg_param = {0, };
8616
8617         MMPLAYER_FENTER();
8618         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8619
8620         LOGW("state changed storage %d:%d", id, state);
8621
8622         if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED)
8623                 return MM_ERROR_NONE;
8624
8625         /* FIXME: text path should be handled seperately. */
8626         if (((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_VOD].id == id)) ||
8627                 ((player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_TEXT].id == id))) {
8628                 LOGW("external storage is removed");
8629
8630                 if (player->msg_posted == FALSE) {
8631                         memset(&msg_param, 0, sizeof(MMMessageParamType));
8632                         msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
8633                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
8634                         player->msg_posted = TRUE;
8635                 }
8636
8637                 /* unrealize the player */
8638                 ret = _mmplayer_unrealize(hplayer);
8639                 if (ret != MM_ERROR_NONE)
8640                         LOGE("failed to unrealize");
8641         }
8642
8643         MMPLAYER_FLEAVE();
8644         return ret;
8645 }
8646
8647 int _mmplayer_get_adaptive_variant_info(MMHandleType hplayer, int *num, char **var_info)
8648 {
8649         int ret = MM_ERROR_NONE;
8650         mm_player_t* player = (mm_player_t*) hplayer;
8651         int idx = 0, total = 0;
8652         gchar *result = NULL, *tmp = NULL;
8653
8654         MMPLAYER_FENTER();
8655         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8656         MMPLAYER_RETURN_VAL_IF_FAIL(num && var_info, MM_ERROR_COMMON_INVALID_ARGUMENT);
8657
8658         total = *num = g_list_length(player->adaptive_info.var_list);
8659         if (total <= 0) {
8660                 LOGW("There is no stream variant info.");
8661                 return ret;
8662         }
8663
8664         result = g_strdup("");
8665         for (idx = 0 ; idx < total ; idx++) {
8666                 VariantData *v_data = NULL;
8667                 v_data = g_list_nth_data(player->adaptive_info.var_list, idx);
8668
8669                 if (v_data) {
8670                         gchar data[64] = {0};
8671                         snprintf(data, sizeof(data), "%d,%d,%d,", v_data->bandwidth, v_data->width, v_data->height);
8672
8673                         tmp = g_strconcat(result, data, NULL);
8674                         g_free(result);
8675                         result = tmp;
8676                 } else {
8677                         LOGW("There is no variant data in %d", idx);
8678                         (*num)--;
8679                 }
8680         }
8681
8682         *var_info = (char *)result;
8683
8684         LOGD("variant info %d:%s", *num, *var_info);
8685         MMPLAYER_FLEAVE();
8686         return ret;
8687 }
8688
8689 int _mmplayer_set_max_adaptive_variant_limit(MMHandleType hplayer, int bandwidth, int width, int height)
8690 {
8691         int ret = MM_ERROR_NONE;
8692         mm_player_t* player = (mm_player_t*) hplayer;
8693
8694         MMPLAYER_FENTER();
8695         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8696
8697         LOGD("set limit to [b]%d, [w]%d, [h]%d", bandwidth, width, height);
8698
8699         player->adaptive_info.limit.bandwidth = (bandwidth >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (bandwidth) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
8700         player->adaptive_info.limit.width = (width >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (width) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
8701         player->adaptive_info.limit.height = (height >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (height) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
8702
8703         if (player->pipeline && player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst) {
8704                 LOGD("update max limit of %s", GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst));
8705                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
8706                                                 "max-bandwidth", bandwidth, "max-video-width", width, "max-video-height", height, NULL);
8707
8708                 /* FIXME: seek to current position for applying new variant limitation */
8709         }
8710
8711         MMPLAYER_FLEAVE();
8712         return ret;
8713
8714 }
8715
8716 int _mmplayer_get_max_adaptive_variant_limit(MMHandleType hplayer, int *bandwidth, int *width, int *height)
8717 {
8718         int ret = MM_ERROR_NONE;
8719         mm_player_t* player = (mm_player_t*) hplayer;
8720
8721         MMPLAYER_FENTER();
8722         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8723         MMPLAYER_RETURN_VAL_IF_FAIL(bandwidth && width && height, MM_ERROR_COMMON_INVALID_ARGUMENT);
8724
8725         *bandwidth = player->adaptive_info.limit.bandwidth;
8726         *width = player->adaptive_info.limit.width;
8727         *height = player->adaptive_info.limit.height;
8728
8729         LOGD("get limit to [b]%d, [w]%d, [h]%d", *bandwidth, *width, *height);
8730
8731         MMPLAYER_FLEAVE();
8732         return ret;
8733 }
8734
8735 int _mmplayer_set_streaming_buffering_time(MMHandleType hplayer, int buffer_ms, int rebuffer_ms)
8736 {
8737         int ret = MM_ERROR_NONE;
8738         mm_player_t* player = (mm_player_t*) hplayer;
8739
8740         MMPLAYER_FENTER();
8741         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8742
8743         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
8744                 LOGW("buffer_ms will not be applied.");
8745
8746
8747         LOGD("set buffering time %d ms / %d ms", buffer_ms, rebuffer_ms);
8748
8749         if (player->streamer == NULL) {
8750                 player->streamer = __mm_player_streaming_create();
8751                 __mm_player_streaming_initialize(player->streamer);
8752         }
8753
8754         if (buffer_ms >= 0)
8755                 player->streamer->buffering_req.prebuffer_time = buffer_ms;
8756
8757         if (rebuffer_ms >= 0)
8758                 player->streamer->buffering_req.rebuffer_time = rebuffer_ms;
8759
8760         MMPLAYER_FLEAVE();
8761         return ret;
8762
8763 }
8764
8765 int _mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *buffer_ms, int *rebuffer_ms)
8766 {
8767         int ret = MM_ERROR_NONE;
8768         mm_player_t* player = (mm_player_t*) hplayer;
8769
8770         MMPLAYER_FENTER();
8771         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8772         MMPLAYER_RETURN_VAL_IF_FAIL(buffer_ms && rebuffer_ms, MM_ERROR_COMMON_INVALID_ARGUMENT);
8773
8774         if (player->streamer == NULL) {
8775                 player->streamer = __mm_player_streaming_create();
8776                 __mm_player_streaming_initialize(player->streamer);
8777         }
8778
8779         *buffer_ms = player->streamer->buffering_req.prebuffer_time;
8780         *rebuffer_ms = player->streamer->buffering_req.rebuffer_time;
8781
8782         LOGD("buffering time %d ms / %d ms", *buffer_ms, *rebuffer_ms);
8783
8784         MMPLAYER_FLEAVE();
8785         return ret;
8786 }
8787
8788 int _mmplayer_set_codec_type(MMHandleType hplayer, MMPlayerStreamType stream_type, MMPlayerVideoCodecType codec_type)
8789 {
8790 #define IDX_FIRST_SW_CODEC 0
8791         mm_player_t* player = (mm_player_t*) hplayer;
8792         const char* attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE);
8793         MMHandleType attrs = 0;
8794
8795         MMPLAYER_FENTER();
8796         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8797
8798         LOGD("ini setting : [a][h:%s][s:%s] / [v][h:%s][s:%s]",
8799                 player->ini.audiocodec_element_hw, player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC],
8800                 player->ini.videocodec_element_hw, player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]);
8801
8802         switch (stream_type) {
8803         case MM_PLAYER_STREAM_TYPE_AUDIO:
8804         /* to support audio codec selection, codec info have to be added in ini file as below.
8805            audio codec element hw = xxxx
8806            audio codec element sw = avdec */
8807                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
8808                          (!strcmp(player->ini.audiocodec_element_hw, ""))) ||
8809                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
8810                          (!strcmp(player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
8811                         LOGE("There is no audio codec info for codec_type %d", codec_type);
8812                         return MM_ERROR_PLAYER_NO_OP;
8813                 }
8814         break;
8815         case MM_PLAYER_STREAM_TYPE_VIDEO:
8816         /* to support video codec selection, codec info have to be added in ini file as below.
8817            video codec element hw = omx
8818            video codec element sw = avdec */
8819                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
8820                          (!strcmp(player->ini.videocodec_element_hw, ""))) ||
8821                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
8822                          (!strcmp(player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
8823                         LOGE("There is no video codec info for codec_type %d", codec_type);
8824                         return MM_ERROR_PLAYER_NO_OP;
8825                 }
8826         break;
8827         default:
8828                 LOGE("Invalid stream type %s", MMPLAYER_STREAM_TYPE_GET_NAME(stream_type));
8829                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
8830         break;
8831         }
8832
8833         LOGD("update %s codec_type to %d", attr_name, codec_type);
8834
8835         attrs = MMPLAYER_GET_ATTRS(player);
8836         mm_attrs_set_int_by_name(attrs, attr_name, codec_type);
8837
8838         if (mmf_attrs_commit(player->attrs)) {
8839                 LOGE("failed to commit codec_type attributes");
8840                 return MM_ERROR_PLAYER_INTERNAL;
8841         }
8842
8843         MMPLAYER_FLEAVE();
8844         return MM_ERROR_NONE;
8845 }
8846
8847 int
8848 _mmplayer_set_replaygain_enabled(MMHandleType hplayer, bool enabled)
8849 {
8850         mm_player_t* player = (mm_player_t*) hplayer;
8851         GstElement* rg_vol_element = NULL;
8852
8853         MMPLAYER_FENTER();
8854
8855         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8856
8857         player->sound.rg_enable = enabled;
8858
8859         /* just hold rgvolume enable value if pipeline is not ready */
8860         if (!player->pipeline || !player->pipeline->audiobin) {
8861                 LOGD("pipeline is not ready. holding rgvolume enable value\n");
8862                 return MM_ERROR_NONE;
8863         }
8864
8865         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
8866
8867         if (!rg_vol_element) {
8868                 LOGD("rgvolume element is not created");
8869                 return MM_ERROR_PLAYER_INTERNAL;
8870         }
8871
8872         if (enabled)
8873                 g_object_set(rg_vol_element, "enable-rgvolume", TRUE, NULL);
8874         else
8875                 g_object_set(rg_vol_element, "enable-rgvolume", FALSE, NULL);
8876
8877         MMPLAYER_FLEAVE();
8878
8879         return MM_ERROR_NONE;
8880 }
8881
8882 int
8883 _mmplayer_is_replaygain_enabled(MMHandleType hplayer, bool *enabled)
8884 {
8885         mm_player_t* player = (mm_player_t*) hplayer;
8886         GstElement* rg_vol_element = NULL;
8887         gboolean enable = FALSE;
8888
8889         MMPLAYER_FENTER();
8890
8891         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8892         MMPLAYER_RETURN_VAL_IF_FAIL(enabled, MM_ERROR_INVALID_ARGUMENT);
8893
8894         /* just hold enable_rg value if pipeline is not ready */
8895         if (!player->pipeline || !player->pipeline->audiobin) {
8896                 LOGD("pipeline is not ready. holding rgvolume value (%d)\n", player->sound.rg_enable);
8897                 *enabled = player->sound.rg_enable;
8898                 return MM_ERROR_NONE;
8899         }
8900
8901         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
8902
8903         if (!rg_vol_element) {
8904                 LOGD("rgvolume element is not created");
8905                 return MM_ERROR_PLAYER_INTERNAL;
8906         }
8907
8908         g_object_get(rg_vol_element, "enable-rgvolume", &enable, NULL);
8909         *enabled = enable;
8910
8911         MMPLAYER_FLEAVE();
8912
8913         return MM_ERROR_NONE;
8914 }
8915
8916 int
8917 _mmplayer_set_video_roi_area(MMHandleType hplayer, double scale_x, double scale_y, double scale_width, double scale_height)
8918 {
8919         mm_player_t* player = (mm_player_t*) hplayer;
8920         MMHandleType attrs = 0;
8921         void *handle = NULL;
8922         int ret = MM_ERROR_NONE;
8923
8924         MMPLAYER_FENTER();
8925
8926         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8927
8928         attrs = MMPLAYER_GET_ATTRS(player);
8929         MMPLAYER_RETURN_VAL_IF_FAIL(attrs, MM_ERROR_PLAYER_INTERNAL);
8930
8931         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
8932         if (!handle) {
8933                 LOGE("Display handle is NULL, after setting window handle, set video roi area");
8934                 return MM_ERROR_PLAYER_INTERNAL;
8935         }
8936
8937         player->video_roi.scale_x = scale_x;
8938         player->video_roi.scale_y = scale_y;
8939         player->video_roi.scale_width = scale_width;
8940         player->video_roi.scale_height = scale_height;
8941
8942         /* check video sinkbin is created */
8943         if (__mmplayer_video_param_check_video_sink_bin(player) != MM_ERROR_NONE)
8944                 return MM_ERROR_NONE;
8945
8946         if (!gst_video_overlay_set_video_roi_area(
8947                 GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
8948                 scale_x, scale_y, scale_width, scale_height))
8949                 ret = MM_ERROR_PLAYER_INTERNAL;
8950         else
8951                 LOGD("set video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)",
8952                         scale_x, scale_y, scale_width, scale_height);
8953
8954         MMPLAYER_FLEAVE();
8955
8956         return ret;
8957 }
8958
8959 int
8960 _mmplayer_get_video_roi_area(MMHandleType hplayer, double *scale_x, double *scale_y, double *scale_width, double *scale_height)
8961 {
8962         mm_player_t* player = (mm_player_t*) hplayer;
8963         int ret = MM_ERROR_NONE;
8964
8965         MMPLAYER_FENTER();
8966
8967         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8968         MMPLAYER_RETURN_VAL_IF_FAIL(scale_x && scale_y && scale_width && scale_height, MM_ERROR_INVALID_ARGUMENT);
8969
8970         *scale_x = player->video_roi.scale_x;
8971         *scale_y = player->video_roi.scale_y;
8972         *scale_width = player->video_roi.scale_width;
8973         *scale_height = player->video_roi.scale_height;
8974
8975         LOGD("get video param : video roi area scale value: x(%f) y(%f) width(%f) height(%f)",
8976                 *scale_x, *scale_y, *scale_width, *scale_height);
8977
8978         return ret;
8979 }
8980
8981 static gboolean
8982 __mmplayer_update_duration_attrs(mm_player_t *player, MMHandleType attrs)
8983 {
8984         gboolean ret = FALSE;
8985         gint64 dur_nsec = 0;
8986         LOGD("try to update duration");
8987
8988         if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec) && (dur_nsec > 0)) {
8989                 player->duration = dur_nsec;
8990                 LOGW("duration : %"G_GINT64_FORMAT" msec", GST_TIME_AS_MSECONDS(dur_nsec));
8991                 ret = TRUE;
8992         }
8993
8994         if (player->duration < 0) {
8995                 LOGW("duration is Non-Initialized !!!");
8996                 player->duration = 0;
8997         }
8998
8999         /* update streaming service type */
9000         player->streaming_type =  __mmplayer_get_stream_service_type(player);
9001
9002         /* check duration is OK */
9003         if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player)) {
9004                 /* FIXIT : find another way to get duration here. */
9005                 LOGW("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
9006         }
9007
9008         return ret;
9009 }
9010
9011 static gboolean
9012 __mmplayer_update_audio_attrs(mm_player_t *player, MMHandleType attrs)
9013 {
9014         /* update audio params
9015         NOTE : We need original audio params and it can be only obtained from src pad of audio
9016         decoder. Below code only valid when we are not using 'resampler' just before
9017         'audioconverter'. */
9018         GstCaps *caps_a = NULL;
9019         GstPad* pad = NULL;
9020         gint samplerate = 0, channels = 0;
9021         GstStructure* p = NULL;
9022
9023         LOGD("try to update audio attrs");
9024
9025         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->audiobin, FALSE);
9026         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, FALSE);
9027
9028         pad = gst_element_get_static_pad(
9029                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink");
9030
9031         if (!pad) {
9032                 LOGW("failed to get pad from audiosink");
9033                 return FALSE;
9034         }
9035
9036         caps_a = gst_pad_get_current_caps(pad);
9037
9038         if (!caps_a) {
9039                 LOGW("not ready to get audio caps");
9040                 gst_object_unref(pad);
9041                 return FALSE;
9042         }
9043
9044         p = gst_caps_get_structure(caps_a, 0);
9045
9046         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
9047
9048         gst_structure_get_int(p, "rate", &samplerate);
9049         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
9050
9051         gst_structure_get_int(p, "channels", &channels);
9052         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
9053
9054         SECURE_LOGD("samplerate : %d    channels : %d", samplerate, channels);
9055
9056         gst_caps_unref(caps_a);
9057         gst_object_unref(pad);
9058
9059         return TRUE;
9060 }
9061
9062 static gboolean
9063 __mmplayer_update_video_attrs(mm_player_t *player, MMHandleType attrs)
9064 {
9065         LOGD("try to update video attrs");
9066
9067         GstCaps *caps_v = NULL;
9068         GstPad* pad = NULL;
9069         gint tmpNu, tmpDe;
9070         gint width, height;
9071         GstStructure* p = NULL;
9072
9073         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin, FALSE);
9074         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin[MMPLAYER_V_SINK].gst, FALSE);
9075
9076         pad = gst_element_get_static_pad(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink");
9077         if (!pad) {
9078                 LOGD("no videosink sink pad");
9079                 return FALSE;
9080         }
9081
9082         caps_v = gst_pad_get_current_caps(pad);
9083         /* Use v_stream_caps, if fail to get video_sink sink pad*/
9084         if (!caps_v && player->v_stream_caps) {
9085                 caps_v = player->v_stream_caps;
9086                 gst_caps_ref(caps_v);
9087         }
9088
9089         if (!caps_v) {
9090                 LOGD("no negitiated caps from videosink");
9091                 gst_object_unref(pad);
9092                 return FALSE;
9093         }
9094
9095         p = gst_caps_get_structure(caps_v, 0);
9096         gst_structure_get_int(p, "width", &width);
9097         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
9098
9099         gst_structure_get_int(p, "height", &height);
9100         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
9101
9102         gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
9103
9104         SECURE_LOGD("width : %d     height : %d", width, height);
9105
9106         gst_caps_unref(caps_v);
9107         gst_object_unref(pad);
9108
9109         if (tmpDe > 0) {
9110                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
9111                 SECURE_LOGD("fps : %d", tmpNu / tmpDe);
9112         }
9113
9114         return TRUE;
9115 }
9116
9117 static gboolean
9118 __mmplayer_update_bitrate_attrs(mm_player_t *player, MMHandleType attrs)
9119 {
9120         gboolean ret = FALSE;
9121         guint64 data_size = 0;
9122         gchar *path = NULL;
9123         struct stat sb;
9124
9125         /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
9126         if (!player->duration)
9127                 return FALSE;
9128
9129         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
9130                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
9131                 if (stat(path, &sb) == 0)
9132                         data_size = (guint64)sb.st_size;
9133
9134         } else if (MMPLAYER_IS_HTTP_STREAMING(player)) {
9135                 data_size = player->http_content_size;
9136         }
9137
9138         LOGD("try to update bitrate : data_size = %"G_GUINT64_FORMAT, data_size);
9139
9140         if (data_size) {
9141                 guint64 bitrate = 0;
9142                 guint64 msec_dur = 0;
9143
9144                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
9145                 if (msec_dur > 0) {
9146                         bitrate = data_size * 8 * 1000 / msec_dur;
9147                         SECURE_LOGD("file size : %u, video bitrate = %llu", data_size, bitrate);
9148                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
9149
9150                         ret = TRUE;
9151                 } else {
9152                         LOGD("player duration is less than 0");
9153                 }
9154         }
9155
9156         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
9157                 if (player->total_bitrate) {
9158                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
9159                         ret = TRUE;
9160                 }
9161         }
9162
9163         return ret;
9164 }
9165 static void
9166 __mmplayer_copy_uri_and_set_type(MMPlayerParseProfile* data, const char *uri, int uri_type)
9167 {
9168         strncpy(data->uri, uri, MM_MAX_URL_LEN - 1);
9169         data->uri_type = uri_type;
9170 }
9171 static int
9172 __mmplayer_set_mem_uri(MMPlayerParseProfile* data, char *path, void *param)
9173 {
9174         int ret = MM_ERROR_PLAYER_INVALID_URI;
9175         int mem_size = 0;
9176         char *buffer = NULL;
9177         char *seperator = strchr(path, ',');
9178         char ext[100] = {0,}, size[100] = {0,};
9179
9180         if (seperator) {
9181                 if ((buffer = strstr(path, "ext="))) {
9182                         buffer += strlen("ext=");
9183
9184                         if (strlen(buffer)) {
9185                                 strncpy(ext, buffer, 99);
9186
9187                                 if ((seperator = strchr(ext, ','))
9188                                         || (seperator = strchr(ext, ' '))
9189                                         || (seperator = strchr(ext, '\0'))) {
9190                                         seperator[0] = '\0';
9191                                 }
9192                         }
9193                 }
9194
9195                 if ((buffer = strstr(path, "size="))) {
9196                         buffer += strlen("size=");
9197
9198                         if (strlen(buffer) > 0) {
9199                                 strncpy(size, buffer, 99);
9200
9201                                 if ((seperator = strchr(size, ','))
9202                                         || (seperator = strchr(size, ' '))
9203                                         || (seperator = strchr(size, '\0'))) {
9204                                         seperator[0] = '\0';
9205                                 }
9206
9207                                 mem_size = atoi(size);
9208                         }
9209                 }
9210         }
9211
9212         LOGD("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
9213
9214         if (mem_size && param) {
9215                 if (data->input_mem.buf)
9216                         free(data->input_mem.buf);
9217                 data->input_mem.buf = malloc(mem_size);
9218
9219                 if (data->input_mem.buf) {
9220                         memcpy(data->input_mem.buf, param, mem_size);
9221                         data->input_mem.len = mem_size;
9222                         ret = MM_ERROR_NONE;
9223                 } else {
9224                         LOGE("failed to alloc mem %d", mem_size);
9225                         ret = MM_ERROR_PLAYER_INTERNAL;
9226                 }
9227
9228                 data->input_mem.offset = 0;
9229                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
9230         }
9231
9232         return ret;
9233 }
9234
9235 static int
9236 __mmplayer_set_file_uri(MMPlayerParseProfile* data, const char *uri)
9237 {
9238         gchar *location = NULL;
9239         GError *err = NULL;
9240         char *path = NULL;
9241         int ret = MM_ERROR_NONE;
9242
9243         if ((path = strstr(uri, "file://"))) {
9244                 location = g_filename_from_uri(uri, NULL, &err);
9245                 if (!location || (err != NULL)) {
9246                         LOGE("Invalid URI '%s' for filesrc: %s", path,
9247                                 (err != NULL) ? err->message : "unknown error");
9248                         if (err)
9249                                 g_error_free(err);
9250                         if (location)
9251                                 g_free(location);
9252
9253                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
9254                         return MM_ERROR_PLAYER_INVALID_URI;
9255                 }
9256                 LOGD("path from uri: %s", location);
9257         }
9258
9259         path = (location != NULL) ? (location) : ((char *)uri);
9260
9261
9262         ret = util_exist_file_path(path);
9263
9264         /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
9265         if (ret == MM_ERROR_NONE) {
9266                 g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", path);
9267                 if (util_is_sdp_file(path)) {
9268                         LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
9269                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
9270                 } else {
9271                         data->uri_type = MM_PLAYER_URI_TYPE_FILE;
9272                 }
9273         } else if (ret == MM_ERROR_PLAYER_PERMISSION_DENIED) {
9274                 data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
9275         } else {
9276                 LOGE("invalid uri, could not play..\n");
9277                 data->uri_type = MM_PLAYER_URI_TYPE_NONE;
9278         }
9279
9280         if (location)
9281                 g_free(location);
9282
9283         return ret;
9284 }
9285
9286 static MMPlayerVideoStreamDataType*
9287 __mmplayer_create_stream_from_pad(GstPad *pad)
9288 {
9289         GstCaps *caps = NULL;
9290         GstStructure *structure = NULL;
9291         unsigned int fourcc = 0;
9292         const gchar *string_format = NULL;
9293         MMPlayerVideoStreamDataType *stream = NULL;
9294         gint width, height;
9295         MMPixelFormatType format;
9296
9297         caps = gst_pad_get_current_caps(pad);
9298         if (!caps) {
9299                 LOGE("Caps is NULL.");
9300                 return NULL;
9301         }
9302
9303         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
9304         structure = gst_caps_get_structure(caps, 0);
9305         gst_structure_get_int(structure, "width", &width);
9306         gst_structure_get_int(structure, "height", &height);
9307         string_format = gst_structure_get_string(structure, "format");
9308         if (string_format)
9309                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
9310         format = util_get_pixtype(fourcc);
9311         gst_caps_unref(caps);
9312
9313         /* moved here */
9314         if (width == 0 || height == 0 || format == MM_PIXEL_FORMAT_INVALID) {
9315                 LOGE("Wrong condition!!");
9316                 return NULL;
9317         }
9318
9319         stream = (MMPlayerVideoStreamDataType *)g_malloc0(sizeof(MMPlayerVideoStreamDataType));
9320         if (!stream) {
9321                 LOGE("failed to alloc mem for video data");
9322                 return NULL;
9323         }
9324
9325         stream->width = width;
9326         stream->height = height;
9327         stream->format = format;
9328
9329         return stream;
9330 }
9331
9332 static void
9333 __mmplayer_zerocopy_set_stride_elevation_bo(MMPlayerVideoStreamDataType *stream, GstMemory *mem)
9334 {
9335         unsigned int pitch = 0;
9336         int index = 0;
9337         tbm_surface_h surface = gst_tizen_memory_get_surface(mem);
9338
9339         for (index = 0; index < gst_tizen_memory_get_num_bos(mem); index++) {
9340                 tbm_surface_internal_get_plane_data(surface, index, NULL, NULL, &pitch);
9341                 stream->bo[index] = tbm_bo_ref(gst_tizen_memory_get_bos(mem, index));
9342                 stream->stride[index] = pitch;
9343                 stream->elevation[index] = stream->height;
9344         }
9345 }
9346
9347 static gboolean
9348 __mmplayer_swcodec_set_stride_elevation(MMPlayerVideoStreamDataType *stream)
9349 {
9350         if (stream->format == MM_PIXEL_FORMAT_I420) {
9351                 int ret = TBM_SURFACE_ERROR_NONE;
9352                 tbm_surface_h surface;
9353                 tbm_surface_info_s info;
9354
9355                 surface = tbm_surface_create(stream->width, stream->height, TBM_FORMAT_YUV420);
9356
9357                 ret = tbm_surface_get_info(surface, &info);
9358                 if (ret != TBM_SURFACE_ERROR_NONE) {
9359                         tbm_surface_destroy(surface);
9360                         return FALSE;
9361                 }
9362
9363                 tbm_surface_destroy(surface);
9364                 stream->stride[0] = info.planes[0].stride;
9365                 stream->elevation[0] = info.planes[0].size / info.planes[0].stride;
9366                 stream->stride[1] = info.planes[1].stride;
9367                 stream->elevation[1] = info.planes[1].size / info.planes[1].stride;
9368                 stream->stride[2] = info.planes[2].stride;
9369                 stream->elevation[2] = info.planes[2].size / info.planes[2].stride;
9370                 stream->bo_size = info.planes[0].size + info.planes[1].size + info.planes[2].size;
9371         } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
9372                 stream->stride[0] = stream->width * 4;
9373                 stream->elevation[0] = stream->height;
9374                 stream->bo_size = stream->stride[0] * stream->height;
9375         } else {
9376                 LOGE("Not support format %d", stream->format);
9377                 return FALSE;
9378         }
9379
9380         return TRUE;
9381 }
9382
9383 static gboolean
9384 __mmplayer_swcodec_set_bo(mm_player_t *player, MMPlayerVideoStreamDataType *stream, GstMemory *mem)
9385 {
9386         tbm_bo_handle thandle;
9387         gboolean is_mapped;
9388         int src_stride[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
9389         int src_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
9390         int dest_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
9391         int i = 0;
9392         int j = 0;
9393         int k = 0;
9394         unsigned char *src = NULL;
9395         unsigned char *dest = NULL;
9396         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
9397
9398         is_mapped = gst_memory_map(mem, &mapinfo, GST_MAP_READWRITE);
9399         if (!is_mapped) {
9400                 LOGE("fail to gst_memory_map");
9401                 return FALSE;
9402         }
9403
9404         if (!mapinfo.data) {
9405                 LOGE("data pointer is wrong");
9406                 goto ERROR;
9407         }
9408
9409         stream->bo[0] = __mmplayer_video_stream_get_bo(player, stream->bo_size);
9410         if (!stream->bo[0]) {
9411                 LOGE("Fail to tbm_bo_alloc!!");
9412                 goto ERROR;
9413         }
9414
9415         thandle = tbm_bo_map(stream->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
9416         if (!thandle.ptr) {
9417                 LOGE("thandle pointer is wrong");
9418                 goto ERROR;
9419         }
9420
9421         if (stream->format == MM_PIXEL_FORMAT_I420) {
9422                 src_stride[0] = GST_ROUND_UP_4(stream->width);
9423                 src_stride[1] = src_stride[2] = GST_ROUND_UP_4(stream->width >> 1);
9424                 src_offset[1] = src_stride[0] * GST_ROUND_UP_2(stream->height);
9425                 src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(stream->height) >> 1));
9426
9427                 dest_offset[0] = 0;
9428                 dest_offset[1] = stream->stride[0] * stream->elevation[0];
9429                 dest_offset[2] = dest_offset[1] + stream->stride[1] * stream->elevation[1];
9430
9431                 for (i = 0; i < 3; i++) {
9432                         src = mapinfo.data + src_offset[i];
9433                         dest = thandle.ptr + dest_offset[i];
9434
9435                         if (i > 0)
9436                                 k = 1;
9437
9438                         for (j = 0; j < stream->height >> k; j++) {
9439                                 memcpy(dest, src, stream->width>>k);
9440                                 src += src_stride[i];
9441                                 dest += stream->stride[i];
9442                         }
9443                 }
9444         } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
9445                 memcpy(thandle.ptr, mapinfo.data, stream->bo_size);
9446         } else {
9447                 LOGE("Not support format %d", stream->format);
9448                 goto ERROR;
9449         }
9450
9451         tbm_bo_unmap(stream->bo[0]);
9452         gst_memory_unmap(mem, &mapinfo);
9453
9454         return TRUE;
9455
9456 ERROR:
9457         if (stream->bo[0])
9458                 tbm_bo_unmap(stream->bo[0]);
9459
9460         if (is_mapped)
9461                 gst_memory_unmap(mem, &mapinfo);
9462
9463         return FALSE;
9464 }