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