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