[0.6.115] add orient info into video data
[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/app/gstappsrc.h>
31 #include <gst/video/videooverlay.h>
32 #include <gst/audio/gstaudiobasesink.h>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <string.h>
36 #include <sys/time.h>
37 #include <stdlib.h>
38 #include <dlog.h>
39
40 #include <mm_error.h>
41 #include <mm_attrs.h>
42 #include <mm_attrs_private.h>
43
44 #include "mm_player_priv.h"
45 #include "mm_player_ini.h"
46 #include "mm_player_attrs.h"
47 #include "mm_player_capture.h"
48 #include "mm_player_utils.h"
49 #include "mm_player_tracks.h"
50 #include "mm_player_360.h"
51
52 #include <system_info.h>
53 #include <sound_manager.h>
54
55 /*===========================================================================================
56 |                                                                                                                                                                                       |
57 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
58 |                                                                                                                                                                                       |
59 ========================================================================================== */
60
61 /*---------------------------------------------------------------------------
62 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
63 ---------------------------------------------------------------------------*/
64
65 /*---------------------------------------------------------------------------
66 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
67 ---------------------------------------------------------------------------*/
68
69 /*---------------------------------------------------------------------------
70 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
71 ---------------------------------------------------------------------------*/
72
73 /*---------------------------------------------------------------------------
74 |    LOCAL #defines:                                                                                                            |
75 ---------------------------------------------------------------------------*/
76 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
77 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
78
79 #define MM_VOLUME_FACTOR_DEFAULT                1.0
80 #define MM_VOLUME_FACTOR_MIN                    0
81 #define MM_VOLUME_FACTOR_MAX                    1.0
82
83 /* Don't need to sleep for sound fadeout
84  * fadeout related fucntion will be deleted(Deprecated)
85  */
86 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  0
87
88 #define DEFAULT_PLAYBACK_RATE                   1.0
89 #define DEFAULT_NUM_OF_V_OUT_BUFFER             3
90
91 #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) \
92         (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && \
93         (player->ini.http_use_file_buffer) && \
94         (player->http_file_buffering_path) && \
95         (strlen(player->http_file_buffering_path) > 0))
96
97 #define PLAYER_DISPLAY_MODE_DST_ROI             5
98
99 #define ADAPTIVE_VARIANT_DEFAULT_VALUE -1 /* auto */
100
101 /* For PD mode */
102 #define PLAYER_PD_EXT_MAX_SIZE_BYTE             1024 * 1024 * 3
103
104 #define PLAYER_BUS_MSG_DEFAULT_TIMEOUT 500 /* bus msg wait timeout */
105 #define PLAYER_BUS_MSG_PREPARE_TIMEOUT 10
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 /*---------------------------------------------------------------------------
116 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
117 ---------------------------------------------------------------------------*/
118
119 /*---------------------------------------------------------------------------
120 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
121 ---------------------------------------------------------------------------*/
122
123 /*---------------------------------------------------------------------------
124 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
125 ---------------------------------------------------------------------------*/
126
127 /*---------------------------------------------------------------------------
128 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
129 ---------------------------------------------------------------------------*/
130 static sound_stream_info_h stream_info;
131
132 /*---------------------------------------------------------------------------
133 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
134 ---------------------------------------------------------------------------*/
135 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
136 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
137 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
138 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
139 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
140 static int              __mmplayer_gst_create_text_sink_bin(mm_player_t* player);
141 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
142
143 static GstPadProbeReturn        __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data);
144 static void             __mmplayer_gst_decode_pad_added(GstElement* elem, GstPad* pad, 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 gint             __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad, GstCaps * caps, GstElementFactory* factory, gpointer data);
150 static void __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad, gpointer data);
151 static void __mmplayer_gst_decode_drained(GstElement *bin, gpointer data);
152 static void     __mmplayer_gst_element_added(GstElement* bin, GstElement* element, gpointer data);
153 static GstElement * __mmplayer_create_decodebin(mm_player_t* player);
154 static gboolean __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps);
155 static void     __mmplayer_typefind_have_type(GstElement *tf, guint probability, GstCaps *caps, gpointer data);
156 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
157 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
158 static gboolean __mmplayer_is_only_mp3_type(gchar *str_caps);
159 static void     __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps);
160
161 static void             __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data);
162 static void             __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data);
163 static MMStreamingType  __mmplayer_get_stream_service_type(mm_player_t* player);
164 static gboolean __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
165 static void             __mmplayer_release_misc(mm_player_t* player);
166 static void             __mmplayer_release_misc_post(mm_player_t* player);
167 static gboolean __mmplayer_init_gstreamer(mm_player_t* player);
168 static GstBusSyncReply __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data);
169 static void __mmplayer_gst_callback(GstMessage *msg, gpointer data);
170 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
171 static gboolean      __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg);
172 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
173 static GstPadProbeReturn __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
174 static void __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
175 static void __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
176 static GstPadProbeReturn __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data);
177 static int __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index);
178
179 static gboolean __mmplayer_check_subtitle(mm_player_t* player);
180 static gboolean __mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message);
181 static void             __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms);
182 static void             __mmplayer_cancel_eos_timer(mm_player_t* player);
183 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
184 static int              __mmplayer_handle_missed_plugin(mm_player_t* player);
185 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime);
186 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
187 static void             __mmplayer_add_sink(mm_player_t* player, GstElement* sink);
188 static void             __mmplayer_del_sink(mm_player_t* player, GstElement* sink);
189 static void             __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type);
190 static gpointer __mmplayer_next_play_thread(gpointer data);
191 static gboolean _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag);
192
193 static gboolean __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element);
194 static GstPadProbeReturn __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data);
195 static void __mmplayer_release_dump_list(GList *dump_list);
196
197 static int              __gst_realize(mm_player_t* player);
198 static int              __gst_unrealize(mm_player_t* player);
199 static int              __gst_start(mm_player_t* player);
200 static int              __gst_stop(mm_player_t* player);
201 static int              __gst_pause(mm_player_t* player, gboolean async);
202 static int              __gst_resume(mm_player_t* player, gboolean async);
203 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
204                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
205                                         gint64 cur, GstSeekType stop_type, gint64 stop);
206 static int __gst_pending_seek(mm_player_t* player);
207
208 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
209 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
210 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
211 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
212 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
213
214 static gboolean __gst_send_event_to_sink(mm_player_t* player, GstEvent* event);
215
216 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
217 static gboolean __mmplayer_can_extract_pcm(mm_player_t* player);
218
219 /* util */
220 static gboolean __is_ms_buff_src(mm_player_t* player);
221 static gboolean __has_suffix(mm_player_t * player, const gchar * suffix);
222
223 static int __mmplayer_realize_streaming_ext(mm_player_t* player);
224 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
225 static int __mmplayer_start_streaming_ext(mm_player_t *player);
226 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
227 static int __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay);
228
229 static gboolean __mmplayer_verify_next_play_path(mm_player_t *player);
230 static void __mmplayer_activate_next_source(mm_player_t *player, GstState target);
231 static void __mmplayer_check_pipeline(mm_player_t* player);
232 static gboolean __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type);
233 static void __mmplayer_deactivate_old_path(mm_player_t *player);
234
235 static void __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg);
236 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name);
237
238 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player);
239 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name);
240 static void             __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data);
241 static void             __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data);
242 static void     __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data);
243 static void             __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data);
244 static void             __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data);
245 static gboolean __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data);
246 static gboolean __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data);
247 static gboolean __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data);
248 static void             __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data);
249 static void             __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all);
250 static void             __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer);
251 static void             __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type);
252 static void             __mmplayer_get_metadata_360_from_tags(GstTagList *tags, mm_player_spherical_metadata_t *metadata);
253 static int              __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res, void *user_data);
254
255 /*===========================================================================================
256 |                                                                                                                                                                                       |
257 |  FUNCTION DEFINITIONS                                                                                                                                         |
258 |                                                                                                                                                                                       |
259 ========================================================================================== */
260
261 #if 0 //debug
262 static void
263 print_tag(const GstTagList * list, const gchar * tag, gpointer unused)
264 {
265         gint i, count;
266
267         count = gst_tag_list_get_tag_size(list, tag);
268
269         LOGD("count = %d", count);
270
271         for (i = 0; i < count; i++) {
272                 gchar *str;
273
274                 if (gst_tag_get_type(tag) == G_TYPE_STRING) {
275                         if (!gst_tag_list_get_string_index(list, tag, i, &str))
276                                 g_assert_not_reached();
277                 } else
278                         str = g_strdup_value_contents(gst_tag_list_get_value_index(list, tag, i));
279
280                 if (i == 0)
281                         g_print("  %15s: %s\n", gst_tag_get_nick(tag), str);
282                 else
283                         g_print("                 : %s\n", str);
284
285                 g_free(str);
286         }
287 }
288 #endif
289
290 /* This function should be called after the pipeline goes PAUSED or higher
291 state. */
292 gboolean
293 _mmplayer_update_content_attrs(mm_player_t* player, enum content_attr_flag flag)
294 {
295         static gboolean has_duration = FALSE;
296         static gboolean has_video_attrs = FALSE;
297         static gboolean has_audio_attrs = FALSE;
298         static gboolean has_bitrate = FALSE;
299         gboolean missing_only = FALSE;
300         gboolean all = FALSE;
301         gint64 dur_nsec = 0;
302         GstStructure* p = NULL;
303         MMHandleType attrs = 0;
304         gchar *path = NULL;
305         struct stat sb;
306
307         MMPLAYER_FENTER();
308
309         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
310
311         /* check player state here */
312         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED &&
313                 MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) {
314                 /* give warning now only */
315                 LOGW("be careful. content attributes may not available in this state ");
316         }
317
318         /* get content attribute first */
319         attrs = MMPLAYER_GET_ATTRS(player);
320         if (!attrs) {
321                 LOGE("cannot get content attribute");
322                 return FALSE;
323         }
324
325         /* get update flag */
326
327         if (flag & ATTR_MISSING_ONLY) {
328                 missing_only = TRUE;
329                 LOGD("updating missed attr only");
330         }
331
332         if (flag & ATTR_ALL) {
333                 all = TRUE;
334                 has_duration = FALSE;
335                 has_video_attrs = FALSE;
336                 has_audio_attrs = FALSE;
337                 has_bitrate = FALSE;
338
339                 LOGD("updating all attrs");
340         }
341
342         if (missing_only && all) {
343                 LOGW("cannot use ATTR_MISSING_ONLY and ATTR_ALL. ignoring ATTR_MISSING_ONLY flag!");
344                 missing_only = FALSE;
345         }
346
347         if ((flag & ATTR_DURATION) ||   (!has_duration && missing_only) || all) {
348                 LOGD("try to update duration");
349                 has_duration = FALSE;
350
351                 if (gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
352                         player->duration = dur_nsec;
353                         LOGW("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
354                 }
355
356                 if (player->duration < 0) {
357                         LOGW("duration : %lld is Non-Initialized !!! \n", player->duration);
358                         player->duration = 0;
359                 }
360
361                 /* update streaming service type */
362                 player->streaming_type =  __mmplayer_get_stream_service_type(player);
363
364                 /* check duration is OK */
365                 if (dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING(player)) {
366                         /* FIXIT : find another way to get duration here. */
367                         LOGE("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
368                 } else {
369                         /*update duration */
370                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
371                         has_duration = TRUE;
372                 }
373         }
374
375         if ((flag & ATTR_AUDIO) || (!has_audio_attrs && missing_only) || all) {
376                 /* update audio params
377                 NOTE : We need original audio params and it can be only obtained from src pad of audio
378                 decoder. Below code only valid when we are not using 'resampler' just before
379                 'audioconverter'. */
380
381                 LOGD("try to update audio attrs");
382                 has_audio_attrs = FALSE;
383
384                 if (player->pipeline->audiobin &&
385                          player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
386                         GstCaps *caps_a = NULL;
387                         GstPad* pad = NULL;
388                         gint samplerate = 0, channels = 0;
389
390                         pad = gst_element_get_static_pad(
391                                         player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink");
392
393                         if (pad) {
394                                 caps_a = gst_pad_get_current_caps(pad);
395
396                                 if (caps_a) {
397                                         p = gst_caps_get_structure(caps_a, 0);
398
399                                         mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
400
401                                         gst_structure_get_int(p, "rate", &samplerate);
402                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
403
404                                         gst_structure_get_int(p, "channels", &channels);
405                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
406
407                                         SECURE_LOGD("samplerate : %d    channels : %d", samplerate, channels);
408
409                                         gst_caps_unref(caps_a);
410                                         caps_a = NULL;
411
412                                         has_audio_attrs = TRUE;
413                                 } else
414                                         LOGW("not ready to get audio caps");
415
416                                 gst_object_unref(pad);
417                         } else
418                                 LOGW("failed to get pad from audiosink");
419                 }
420         }
421
422         if ((flag & ATTR_VIDEO) || (!has_video_attrs && missing_only) || all) {
423                 LOGD("try to update video attrs");
424                 has_video_attrs = FALSE;
425
426                 if (player->pipeline->videobin &&
427                          player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
428                         GstCaps *caps_v = NULL;
429                         GstPad* pad = NULL;
430                         gint tmpNu, tmpDe;
431                         gint width, height;
432
433                         pad = gst_element_get_static_pad(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink");
434                         if (pad) {
435                                 caps_v = gst_pad_get_current_caps(pad);
436
437                                 /* Use v_stream_caps, if fail to get video_sink sink pad*/
438                                 if (!caps_v && player->v_stream_caps) {
439                                         caps_v = player->v_stream_caps;
440                                         gst_caps_ref(caps_v);
441                                 }
442
443                                 if (caps_v) {
444                                         p = gst_caps_get_structure(caps_v, 0);
445                                         gst_structure_get_int(p, "width", &width);
446                                         mm_attrs_set_int_by_name(attrs, "content_video_width", width);
447
448                                         gst_structure_get_int(p, "height", &height);
449                                         mm_attrs_set_int_by_name(attrs, "content_video_height", height);
450
451                                         gst_structure_get_fraction(p, "framerate", &tmpNu, &tmpDe);
452
453                                         SECURE_LOGD("width : %d     height : %d", width, height);
454
455                                         gst_caps_unref(caps_v);
456                                         caps_v = NULL;
457
458                                         if (tmpDe > 0) {
459                                                 mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
460                                                 SECURE_LOGD("fps : %d", tmpNu / tmpDe);
461                                         }
462
463                                         has_video_attrs = TRUE;
464                                 } else
465                                         LOGD("no negitiated caps from videosink");
466                                 gst_object_unref(pad);
467                                 pad = NULL;
468                         } else
469                                 LOGD("no videosink sink pad");
470                 }
471         }
472
473
474         if ((flag & ATTR_BITRATE) || (!has_bitrate && missing_only) || all) {
475                 has_bitrate = FALSE;
476
477                 /* FIXIT : please make it clear the dependancy with duration/codec/uritype */
478                 if (player->duration) {
479                         guint64 data_size = 0;
480
481                         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
482                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
483
484                                 if (stat(path, &sb) == 0)
485                                         data_size = (guint64)sb.st_size;
486                         } else if (MMPLAYER_IS_HTTP_STREAMING(player)) {
487                                 data_size = player->http_content_size;
488                         }
489                         LOGD("try to update bitrate : data_size = %lld", data_size);
490
491                         if (data_size) {
492                                 guint64 bitrate = 0;
493                                 guint64 msec_dur = 0;
494
495                                 msec_dur = GST_TIME_AS_MSECONDS(player->duration);
496                                 if (msec_dur > 0) {
497                                         bitrate = data_size * 8 * 1000 / msec_dur;
498                                         SECURE_LOGD("file size : %u, video bitrate = %llu", data_size, bitrate);
499                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
500
501                                         has_bitrate = TRUE;
502                                 } else {
503                                         LOGD("player duration is less than 0");
504                                 }
505                         }
506
507                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
508                                 if (player->total_bitrate) {
509                                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", player->total_bitrate);
510                                         has_bitrate = TRUE;
511                                 }
512                         }
513                 }
514         }
515
516         /* validate all */
517         if (mmf_attrs_commit(attrs)) {
518                 LOGE("failed to update attributes\n");
519                 return FALSE;
520         }
521
522         MMPLAYER_FLEAVE();
523
524         return TRUE;
525 }
526
527 static MMStreamingType __mmplayer_get_stream_service_type(mm_player_t* player)
528 {
529         MMStreamingType streaming_type = STREAMING_SERVICE_NONE;
530
531         MMPLAYER_FENTER();
532
533         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
534                         player->pipeline &&
535                         player->pipeline->mainbin &&
536                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
537                         STREAMING_SERVICE_NONE);
538
539         /* streaming service type if streaming */
540         if (!MMPLAYER_IS_STREAMING(player))
541                 return STREAMING_SERVICE_NONE;
542
543         if (MMPLAYER_IS_HTTP_STREAMING(player))
544                 streaming_type = (player->duration == 0) ?
545                         STREAMING_SERVICE_LIVE : STREAMING_SERVICE_VOD;
546
547         switch (streaming_type) {
548         case STREAMING_SERVICE_LIVE:
549                 LOGD("it's live streaming");
550                 break;
551         case STREAMING_SERVICE_VOD:
552                 LOGD("it's vod streaming");
553                 break;
554         default:
555                 LOGE("should not get here");
556                 break;
557         }
558
559         MMPLAYER_FLEAVE();
560
561         return streaming_type;
562 }
563
564
565 /* this function sets the player state and also report
566  * it to applicaton by calling callback function
567  */
568 int
569 __mmplayer_set_state(mm_player_t* player, int state)
570 {
571         MMMessageParamType msg = {0, };
572         gboolean post_bos = FALSE;
573
574         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
575
576         if (MMPLAYER_CURRENT_STATE(player) == state) {
577                 LOGW("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
578                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
579                 return MM_ERROR_NONE;
580         }
581
582         /* update player states */
583         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
584         MMPLAYER_CURRENT_STATE(player) = state;
585
586         if (MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player))
587                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
588
589         /* print state */
590         MMPLAYER_PRINT_STATE(player);
591
592         switch (MMPLAYER_CURRENT_STATE(player)) {
593         case MM_PLAYER_STATE_NULL:
594         case MM_PLAYER_STATE_READY:
595                 break;
596
597         case MM_PLAYER_STATE_PAUSED:
598                 {
599                         if (!player->sent_bos) {
600                                 /* rtsp case, get content attrs by GstMessage */
601                                 if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
602                                         /* it's first time to update all content attrs. */
603                                         _mmplayer_update_content_attrs(player, ATTR_ALL);
604                                 }
605                         }
606
607                         /* add audio callback probe if condition is satisfied */
608                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
609                                 __mmplayer_configure_audio_callback(player);
610
611                         /* FIXIT : handle return value */
612                 }
613                 break;
614
615         case MM_PLAYER_STATE_PLAYING:
616                 {
617                         /* try to get content metadata */
618                         if (!player->sent_bos) {
619                                 /* NOTE : giving ATTR_MISSING_ONLY may have dependency with
620                                  * c-api since c-api doesn't use _start() anymore. It may not work propery with
621                                  * legacy mmfw-player api */
622                                 _mmplayer_update_content_attrs(player, ATTR_MISSING_ONLY);
623                         }
624
625                         if ((player->cmd == MMPLAYER_COMMAND_START) || (player->cmd == MMPLAYER_COMMAND_RESUME)) {
626                                 if (!player->sent_bos)
627                                         __mmplayer_handle_missed_plugin(player);
628                         }
629
630                         if (player->resumed_by_rewind && player->playback_rate < 0.0) {
631                                 /* initialize because auto resume is done well. */
632                                 player->resumed_by_rewind = FALSE;
633                                 player->playback_rate = 1.0;
634                         }
635
636                         if (!player->sent_bos) {
637                                 /* check audio codec field is set or not
638                                  * we can get it from typefinder or codec's caps.
639                                  */
640                                 gchar *audio_codec = NULL;
641                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
642
643                                 /* The codec format can't be sent for audio only case like amr, mid etc.
644                                  * Because, parser don't make related TAG.
645                                  * So, if it's not set yet, fill it with found data.
646                                  */
647                                 if (!audio_codec) {
648                                         if (g_strrstr(player->type, "audio/midi"))
649                                                 audio_codec = g_strdup("MIDI");
650                                         else if (g_strrstr(player->type, "audio/x-amr"))
651                                                 audio_codec = g_strdup("AMR");
652                                         else if (g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion= (int)1"))
653                                                 audio_codec = g_strdup("AAC");
654                                         else
655                                                 audio_codec = g_strdup("unknown");
656                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
657
658                                         MMPLAYER_FREEIF(audio_codec);
659                                         if (mmf_attrs_commit(player->attrs))
660                                                 LOGE("failed to update attributes\n");
661
662                                         LOGD("set audio codec type with caps\n");
663                                 }
664
665                                 post_bos = TRUE;
666                         }
667                 }
668                 break;
669
670         case MM_PLAYER_STATE_NONE:
671         default:
672                 LOGW("invalid target state, there is nothing to do.\n");
673                 break;
674         }
675
676
677         /* post message to application */
678         if (MMPLAYER_TARGET_STATE(player) == state) {
679                 /* fill the message with state of player */
680                 msg.union_type = MM_MSG_UNION_STATE;
681                 msg.state.previous = MMPLAYER_PREV_STATE(player);
682                 msg.state.current = MMPLAYER_CURRENT_STATE(player);
683
684                 LOGD("player reach the target state (%s)", MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
685
686                 /* state changed by resource callback */
687                 if (player->interrupted_by_resource) {
688                         msg.state.code = MM_PLAYER_FOCUS_CHANGED_BY_RESOURCE_CONFLICT;
689                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
690                 } else { /* state changed by usecase */
691                         MMPLAYER_POST_MSG(player, MM_MESSAGE_STATE_CHANGED, &msg);
692                 }
693         } else {
694                 LOGD("intermediate state, do nothing.\n");
695                 MMPLAYER_PRINT_STATE(player);
696                 return MM_ERROR_NONE;
697         }
698
699         if (post_bos) {
700                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BEGIN_OF_STREAM, NULL);
701                 player->sent_bos = TRUE;
702         }
703
704         return MM_ERROR_NONE;
705 }
706
707 static gpointer __mmplayer_next_play_thread(gpointer data)
708 {
709         mm_player_t* player = (mm_player_t*) data;
710         MMPlayerGstElement *mainbin = NULL;
711
712         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
713
714         MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
715         while (!player->next_play_thread_exit) {
716                 LOGD("next play thread started. waiting for signal.\n");
717                 MMPLAYER_NEXT_PLAY_THREAD_WAIT(player);
718
719                 LOGD("reconfigure pipeline for gapless play.\n");
720
721                 if (player->next_play_thread_exit) {
722                         if (player->gapless.reconfigure) {
723                                 player->gapless.reconfigure = false;
724                                 MMPLAYER_PLAYBACK_UNLOCK(player);
725                         }
726                         LOGD("exiting gapless play thread\n");
727                         break;
728                 }
729
730                 mainbin = player->pipeline->mainbin;
731
732                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_MUXED_S_BUFFER);
733                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_ID3DEMUX);
734                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_AUTOPLUG);
735                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_TYPEFIND);
736                 MMPLAYER_RELEASE_ELEMENT(player, mainbin, MMPLAYER_M_SRC);
737
738                 __mmplayer_activate_next_source(player, GST_STATE_PLAYING);
739         }
740         MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
741
742         return NULL;
743 }
744
745 static void
746 __mmplayer_update_buffer_setting(mm_player_t *player, GstMessage *buffering_msg)
747 {
748         MMHandleType attrs = 0;
749         guint64 data_size = 0;
750         gchar* path = NULL;
751         unsigned long pos_msec = 0;
752         struct stat sb;
753
754         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
755
756         __gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &pos_msec);       // update last_position
757
758         attrs = MMPLAYER_GET_ATTRS(player);
759         if (!attrs) {
760                 LOGE("fail to get attributes.\n");
761                 return;
762         }
763
764         if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO)) {
765                 mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
766
767                 if (stat(path, &sb) == 0)
768                         data_size = (guint64)sb.st_size;
769         } else if (MMPLAYER_IS_HTTP_STREAMING(player))
770                 data_size = player->http_content_size;
771
772         __mm_player_streaming_buffering(player->streamer,
773                                                                                 buffering_msg,
774                                                                                 data_size,
775                                                                                 player->last_position,
776                                                                                 player->duration);
777
778         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
779
780         return;
781 }
782
783 static int
784 __mmplayer_handle_buffering_message(mm_player_t* player)
785 {
786         int ret = MM_ERROR_NONE;
787         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
788         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
789         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
790         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
791
792         if (!player || !player->streamer || (MMPLAYER_IS_LIVE_STREAMING(player) && MMPLAYER_IS_RTSP_STREAMING(player))) {
793                 LOGW("do nothing for buffering msg\n");
794                 ret = MM_ERROR_PLAYER_INVALID_STATE;
795                 goto exit;
796         }
797
798         prev_state = MMPLAYER_PREV_STATE(player);
799         current_state = MMPLAYER_CURRENT_STATE(player);
800         target_state = MMPLAYER_TARGET_STATE(player);
801         pending_state = MMPLAYER_PENDING_STATE(player);
802
803         LOGD("player state : prev %s, current %s, pending %s, target %s, buffering %d",
804                 MMPLAYER_STATE_GET_NAME(prev_state),
805                 MMPLAYER_STATE_GET_NAME(current_state),
806                 MMPLAYER_STATE_GET_NAME(pending_state),
807                 MMPLAYER_STATE_GET_NAME(target_state),
808                 player->streamer->is_buffering);
809
810         if (!player->streamer->is_buffering) {
811                 /* NOTE : if buffering has done, player has to go to target state. */
812                 switch (target_state) {
813                 case MM_PLAYER_STATE_PAUSED:
814                         {
815                                 switch (pending_state) {
816                                 case MM_PLAYER_STATE_PLAYING:
817                                         __gst_pause(player, TRUE);
818                                         break;
819
820                                 case MM_PLAYER_STATE_PAUSED:
821                                         LOGD("player is already going to paused state, there is nothing to do.\n");
822                                         break;
823
824                                 case MM_PLAYER_STATE_NONE:
825                                 case MM_PLAYER_STATE_NULL:
826                                 case MM_PLAYER_STATE_READY:
827                                 default:
828                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
829                                         break;
830                                 }
831                         }
832                         break;
833
834                 case MM_PLAYER_STATE_PLAYING:
835                         {
836                                 switch (pending_state) {
837                                 case MM_PLAYER_STATE_NONE:
838                                         {
839                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
840                                                         __gst_resume(player, TRUE);
841                                         }
842                                         break;
843
844                                 case MM_PLAYER_STATE_PAUSED:
845                                         /* NOTE: It should be worked as asynchronously.
846                                          * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
847                                          */
848                                         if (current_state == MM_PLAYER_STATE_PLAYING) {
849                                                 /* NOTE: If the current state is PLAYING, it means, async __gst_pause() is not completed yet.
850                                                  * The current state should be changed to paused purposely to prevent state conflict.
851                                                  */
852                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
853                                         }
854                                         __gst_resume(player, TRUE);
855                                         break;
856
857                                 case MM_PLAYER_STATE_PLAYING:
858                                         LOGD("player is already going to playing state, there is nothing to do.\n");
859                                         break;
860
861                                 case MM_PLAYER_STATE_NULL:
862                                 case MM_PLAYER_STATE_READY:
863                                 default:
864                                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
865                                         break;
866                                 }
867                         }
868                         break;
869
870                 case MM_PLAYER_STATE_NULL:
871                 case MM_PLAYER_STATE_READY:
872                 case MM_PLAYER_STATE_NONE:
873                 default:
874                         LOGW("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state));
875                         break;
876                 }
877         } else {
878                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
879                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
880                  */
881                 switch (pending_state) {
882                 case MM_PLAYER_STATE_NONE:
883                         {
884                                 if (current_state != MM_PLAYER_STATE_PAUSED) {
885                                         /* rtsp streaming pause makes rtsp server stop sending data. */
886                                         if (!MMPLAYER_IS_RTSP_STREAMING(player)) {
887                                                 LOGD("set pause state during buffering\n");
888                                                 __gst_pause(player, TRUE);
889                                         }
890                                 }
891                         }
892                         break;
893
894                 case MM_PLAYER_STATE_PLAYING:
895                         /* rtsp streaming pause makes rtsp server stop sending data. */
896                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
897                                 __gst_pause(player, TRUE);
898                         break;
899
900                 case MM_PLAYER_STATE_PAUSED:
901                         break;
902
903                 case MM_PLAYER_STATE_NULL:
904                 case MM_PLAYER_STATE_READY:
905                 default:
906                         LOGW("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state));
907                         break;
908                 }
909         }
910
911 exit:
912         return ret;
913 }
914
915 static void
916 __mmplayer_drop_subtitle(mm_player_t* player, gboolean is_drop)
917 {
918         MMPlayerGstElement *textbin;
919         MMPLAYER_FENTER();
920
921         MMPLAYER_RETURN_IF_FAIL(player &&
922                                         player->pipeline &&
923                                         player->pipeline->textbin);
924
925         MMPLAYER_RETURN_IF_FAIL(player->pipeline->textbin[MMPLAYER_T_IDENTITY].gst);
926
927         textbin = player->pipeline->textbin;
928
929         if (is_drop) {
930                 LOGD("Drop subtitle text after getting EOS\n");
931
932                 g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", FALSE, NULL);
933                 g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)1.0, NULL);
934
935                 player->is_subtitle_force_drop = TRUE;
936         } else {
937                 if (player->is_subtitle_force_drop == TRUE) {
938                         LOGD("Enable subtitle data path without drop\n");
939
940                         g_object_set(textbin[MMPLAYER_T_IDENTITY].gst, "drop-probability", (gfloat)0.0, NULL);
941                         g_object_set(textbin[MMPLAYER_T_FAKE_SINK].gst, "async", TRUE, NULL);
942
943                         LOGD("non-connected with external display");
944
945                         player->is_subtitle_force_drop = FALSE;
946                 }
947         }
948 }
949
950 static VariantData *
951 __mmplayer_adaptive_var_info(const VariantData *self, gpointer user_data)
952 {
953         VariantData *var_info = NULL;
954         g_return_val_if_fail(self != NULL, NULL);
955
956         var_info = g_new0(VariantData, 1);
957         if (!var_info) return NULL;
958         var_info->bandwidth = self->bandwidth;
959         var_info->width = self->width;
960         var_info->height = self->height;
961         return var_info;
962 }
963
964 void _mmplayer_bus_msg_thread_destroy(MMHandleType hplayer)
965 {
966         mm_player_t* player = (mm_player_t*)hplayer;
967         GstMessage *msg = NULL;
968         GQueue *queue = NULL;
969
970         MMPLAYER_FENTER();
971         MMPLAYER_RETURN_IF_FAIL(player);
972
973         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
974
975         /* destroy the gst bus msg thread */
976         if (player->bus_msg_thread) {
977                 MMPLAYER_BUS_MSG_THREAD_LOCK(player);
978                 player->bus_msg_thread_exit = TRUE;
979                 MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
980                 MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
981
982                 LOGD("gst bus msg thread exit.");
983                 g_thread_join(player->bus_msg_thread); /* can request cmd lock */
984                 player->bus_msg_thread = NULL;
985
986                 g_mutex_clear(&player->bus_msg_thread_mutex);
987                 g_cond_clear(&player->bus_msg_thread_cond);
988         }
989
990         g_mutex_lock(&player->bus_msg_q_lock);
991         queue = player->bus_msg_q;
992         while (!g_queue_is_empty(queue)) {
993                 msg = (GstMessage *)g_queue_pop_head(queue);
994                 LOGW("remove remained %s msg", GST_MESSAGE_TYPE_NAME(msg));
995                 gst_message_unref(msg);
996         }
997         g_mutex_unlock(&player->bus_msg_q_lock);
998
999         MMPLAYER_FLEAVE();
1000 }
1001
1002 gboolean __mmplayer_gst_msg_push(GstBus *bus, GstMessage *msg, gpointer data)
1003 {
1004         mm_player_t *player = (mm_player_t *) data;
1005
1006         g_return_val_if_fail(player, FALSE);
1007         g_return_val_if_fail(msg && GST_IS_MESSAGE(msg), FALSE);
1008
1009         gst_message_ref(msg);
1010
1011         g_mutex_lock(&player->bus_msg_q_lock);
1012         g_queue_push_tail(player->bus_msg_q, msg);
1013         g_mutex_unlock(&player->bus_msg_q_lock);
1014
1015         MMPLAYER_BUS_MSG_THREAD_LOCK(player);
1016         MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
1017         MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
1018         return TRUE;
1019 }
1020
1021 static gpointer __mmplayer_gst_bus_msg_thread(gpointer data)
1022 {
1023         mm_player_t *player = (mm_player_t*)(data);
1024         GstMessage *msg = NULL;
1025         GstBus *bus = NULL;
1026
1027         MMPLAYER_FENTER();
1028         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
1029                                                 player->pipeline &&
1030                                                 player->pipeline->mainbin &&
1031                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
1032                                                 NULL);
1033
1034         bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
1035         if (!bus) {
1036                 LOGE("cannot get BUS from the pipeline");
1037                 return NULL;
1038         }
1039
1040         MMPLAYER_BUS_MSG_THREAD_LOCK(player);
1041
1042         LOGD("[handle: %p] gst bus msg thread will be started.", player);
1043         while (!player->bus_msg_thread_exit) {
1044                 g_mutex_lock(&player->bus_msg_q_lock);
1045                 msg = g_queue_pop_head(player->bus_msg_q);
1046                 g_mutex_unlock(&player->bus_msg_q_lock);
1047                 if (msg == NULL) {
1048                         MMPLAYER_BUS_MSG_THREAD_WAIT(player);
1049                         continue;
1050                 }
1051                 MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
1052                 /* handle the gst msg */
1053                 __mmplayer_gst_callback(msg, player);
1054                 MMPLAYER_BUS_MSG_THREAD_LOCK(player);
1055                 gst_message_unref(msg);
1056         }
1057
1058         MMPLAYER_BUS_MSG_THREAD_UNLOCK(player);
1059         gst_object_unref(GST_OBJECT(bus));
1060
1061         MMPLAYER_FLEAVE();
1062         return NULL;
1063 }
1064
1065 static void
1066 __mmplayer_gst_callback(GstMessage *msg, gpointer data)
1067 {
1068         mm_player_t* player = (mm_player_t*)(data);
1069         static gboolean async_done = FALSE;
1070
1071         MMPLAYER_RETURN_IF_FAIL(player);
1072         MMPLAYER_RETURN_IF_FAIL(msg && GST_IS_MESSAGE(msg));
1073
1074         switch (GST_MESSAGE_TYPE(msg)) {
1075         case GST_MESSAGE_UNKNOWN:
1076                 LOGD("unknown message received\n");
1077                 break;
1078
1079         case GST_MESSAGE_EOS:
1080                 {
1081                         MMHandleType attrs = 0;
1082                         gint count = 0;
1083
1084                         LOGD("GST_MESSAGE_EOS received\n");
1085
1086                         /* NOTE : EOS event is comming multiple time. watch out it */
1087                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1088                         if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME)) {
1089                                 LOGD("EOS received on non-playing state. ignoring it\n");
1090                                 break;
1091                         }
1092
1093                         if (player->pipeline) {
1094                                 if (player->pipeline->textbin)
1095                                         __mmplayer_drop_subtitle(player, TRUE);
1096
1097                                 if ((player->audio_stream_cb) && (player->set_mode.pcm_extraction) && (!player->audio_stream_render_cb_ex)) {
1098                                         GstPad *pad = NULL;
1099
1100                                         pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1101
1102                                         LOGD("release audio callback\n");
1103
1104                                         /* release audio callback */
1105                                         gst_pad_remove_probe(pad, player->audio_cb_probe_id);
1106                                         player->audio_cb_probe_id = 0;
1107                                         /* audio callback should be free because it can be called even though probe remove.*/
1108                                         player->audio_stream_cb = NULL;
1109                                         player->audio_stream_cb_user_param = NULL;
1110
1111                                 }
1112                         }
1113                         if ((player->audio_stream_render_cb_ex) && (!player->audio_stream_sink_sync))
1114                                 __mmplayer_audio_stream_clear_buffer(player, TRUE);
1115
1116                         /* rewind if repeat count is greater then zero */
1117                         /* get play count */
1118                         attrs = MMPLAYER_GET_ATTRS(player);
1119
1120                         if (attrs) {
1121                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1122
1123                                 LOGD("play count: %d, playback rate: %f\n", count, player->playback_rate);
1124
1125                                 if (count == -1 || player->playback_rate < 0.0) /* default value is 1 */ {
1126                                         if (player->playback_rate < 0.0) {
1127                                                 player->resumed_by_rewind = TRUE;
1128                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1129                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_RESUMED_BY_REW, NULL);
1130                                         }
1131
1132                                         __mmplayer_handle_eos_delay(player, player->ini.delay_before_repeat);
1133
1134                                         /* initialize */
1135                                         player->sent_bos = FALSE;
1136
1137                                         /* not posting eos when repeating */
1138                                         break;
1139                                 }
1140                         }
1141
1142                         if (player->pipeline)
1143                                 MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-eos");
1144
1145                         /* post eos message to application */
1146                         __mmplayer_handle_eos_delay(player, player->ini.eos_delay);
1147
1148                         /* reset last position */
1149                         player->last_position = 0;
1150                 }
1151                 break;
1152
1153         case GST_MESSAGE_ERROR:
1154                 {
1155                         GError *error = NULL;
1156                         gchar* debug = NULL;
1157
1158                         /* generating debug info before returning error */
1159                         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-error");
1160
1161                         /* get error code */
1162                         gst_message_parse_error(msg, &error, &debug);
1163
1164                         if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
1165                                 /* Note : the streaming error from the streaming source is handled
1166                                  *   using __mmplayer_handle_streaming_error.
1167                                  */
1168                                 __mmplayer_handle_streaming_error(player, msg);
1169
1170                                 /* dump state of all element */
1171                                 __mmplayer_dump_pipeline_state(player);
1172                         } else {
1173                                 /* traslate gst error code to msl error code. then post it
1174                                  * to application if needed
1175                                  */
1176                                 __mmplayer_handle_gst_error(player, msg, error);
1177
1178                                 if (debug)
1179                                         LOGE("error debug : %s", debug);
1180                         }
1181
1182                         if (MMPLAYER_IS_HTTP_PD(player))
1183                                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
1184
1185                         MMPLAYER_FREEIF(debug);
1186                         g_error_free(error);
1187                 }
1188                 break;
1189
1190         case GST_MESSAGE_WARNING:
1191                 {
1192                         char* debug = NULL;
1193                         GError* error = NULL;
1194
1195                         gst_message_parse_warning(msg, &error, &debug);
1196
1197                         LOGD("warning : %s\n", error->message);
1198                         LOGD("debug : %s\n", debug);
1199
1200                         MMPLAYER_POST_MSG(player, MM_MESSAGE_WARNING, NULL);
1201
1202                         MMPLAYER_FREEIF(debug);
1203                         g_error_free(error);
1204                 }
1205                 break;
1206
1207         case GST_MESSAGE_TAG:
1208                 {
1209                         LOGD("GST_MESSAGE_TAG\n");
1210                         if (!__mmplayer_gst_extract_tag_from_msg(player, msg))
1211                                 LOGW("failed to extract tags from gstmessage\n");
1212                 }
1213                 break;
1214
1215         case GST_MESSAGE_BUFFERING:
1216                 {
1217                         MMMessageParamType msg_param = {0, };
1218                         int bRet = MM_ERROR_NONE;
1219
1220                         if (!(player->pipeline && player->pipeline->mainbin)) {
1221                                 LOGE("player pipeline handle is null");
1222                                 break;
1223                         }
1224
1225                         if (!MMPLAYER_IS_STREAMING(player))
1226                                 break;
1227
1228                         if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
1229                                 if (!MMPLAYER_CMD_TRYLOCK(player)) {
1230                                         /* skip the playback control by buffering msg while user request is handled. */
1231                                         gint per = 0;
1232
1233                                         LOGW("[PD mode] can't get cmd lock, only post buffering msg");
1234
1235                                         gst_message_parse_buffering(msg, &per);
1236                                         LOGD("[PD mode][%s] buffering %d %%....", GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)), per);
1237
1238                                         msg_param.connection.buffering = per;
1239                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1240                                         break;
1241                                 }
1242                         } else {
1243                                 MMPLAYER_CMD_LOCK(player);
1244                         }
1245
1246                         /* ignore the prev buffering message */
1247                         if ((player->streamer) && (player->streamer->is_buffering == FALSE)
1248                                 && (player->streamer->is_buffering_done == TRUE)) {
1249                                 gint buffer_percent = 0;
1250
1251                                 gst_message_parse_buffering(msg, &buffer_percent);
1252
1253                                 if (buffer_percent == MAX_BUFFER_PERCENT) {
1254                                         LOGD("Ignored all the previous buffering msg!(got %d%%)\n", buffer_percent);
1255                                         player->streamer->is_buffering_done = FALSE;
1256                                 }
1257                                 MMPLAYER_CMD_UNLOCK(player);
1258                                 break;
1259                         }
1260
1261                         __mmplayer_update_buffer_setting(player, msg);
1262
1263                         bRet = __mmplayer_handle_buffering_message(player);
1264
1265                         if (bRet == MM_ERROR_NONE) {
1266                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1267                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1268
1269                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1270                                         player->pending_resume &&
1271                                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1272
1273                                         player->is_external_subtitle_added_now = FALSE;
1274                                         player->pending_resume = FALSE;
1275                                         _mmplayer_resume((MMHandleType)player);
1276                                 }
1277
1278                                 if (MMPLAYER_IS_RTSP_STREAMING(player) &&
1279                                         (player->streamer->buffering_percent >= MAX_BUFFER_PERCENT)) {
1280
1281                                         if (player->doing_seek) {
1282                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1283                                                         player->doing_seek = FALSE;
1284                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1285                                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1286                                                         async_done = TRUE;
1287                                                 }
1288                                         }
1289                                 }
1290                         } else if (bRet == MM_ERROR_PLAYER_INVALID_STATE) {
1291                                 if (!player->streamer) {
1292                                         LOGW("player->streamer is NULL, so discarding the buffering percent update\n");
1293                                         MMPLAYER_CMD_UNLOCK(player);
1294                                         break;
1295                                 }
1296
1297                                 if ((MMPLAYER_IS_LIVE_STREAMING(player)) && (MMPLAYER_IS_RTSP_STREAMING(player))) {
1298
1299                                         LOGD("player->last_position=%lld , player->streamer->buffering_percent=%d \n",
1300                                                         GST_TIME_AS_SECONDS(player->last_position), player->streamer->buffering_percent);
1301
1302                                         if ((GST_TIME_AS_SECONDS(player->last_position) <= 0) && (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)) {
1303                                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1304                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1305                                         } else {
1306                                                 LOGD("Not updating Buffering Message for Live RTSP case !!!\n");
1307                                         }
1308                                 } else {
1309                                         msg_param.connection.buffering = player->streamer->buffering_percent;
1310                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1311                                 }
1312                         }
1313                         MMPLAYER_CMD_UNLOCK(player);
1314                 }
1315                 break;
1316
1317         case GST_MESSAGE_STATE_CHANGED:
1318                 {
1319                         MMPlayerGstElement *mainbin;
1320                         const GValue *voldstate, *vnewstate, *vpending;
1321                         GstState oldstate = GST_STATE_NULL;
1322                         GstState newstate = GST_STATE_NULL;
1323                         GstState pending = GST_STATE_NULL;
1324
1325                         if (!(player->pipeline && player->pipeline->mainbin)) {
1326                                 LOGE("player pipeline handle is null");
1327                                 break;
1328                         }
1329
1330                         mainbin = player->pipeline->mainbin;
1331
1332                         /* we only handle messages from pipeline */
1333                         if (msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst)
1334                                 break;
1335
1336                         /* get state info from msg */
1337                         voldstate = gst_structure_get_value(gst_message_get_structure(msg), "old-state");
1338                         vnewstate = gst_structure_get_value(gst_message_get_structure(msg), "new-state");
1339                         vpending = gst_structure_get_value(gst_message_get_structure(msg), "pending-state");
1340
1341                         if (!voldstate || !vnewstate) {
1342                                 LOGE("received msg has wrong format.");
1343                                 break;
1344                         }
1345
1346                         oldstate = (GstState)voldstate->data[0].v_int;
1347                         newstate = (GstState)vnewstate->data[0].v_int;
1348                         if (vpending)
1349                                 pending = (GstState)vpending->data[0].v_int;
1350
1351                         LOGD("state changed [%s] : %s ---> %s     final : %s\n",
1352                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1353                                 gst_element_state_get_name((GstState)oldstate),
1354                                 gst_element_state_get_name((GstState)newstate),
1355                                 gst_element_state_get_name((GstState)pending));
1356
1357                         if (newstate == GST_STATE_PLAYING) {
1358                                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (player->pending_seek.is_pending)) {
1359
1360                                         int retVal = MM_ERROR_NONE;
1361                                         LOGD("trying to play from (%lu) pending position\n", player->pending_seek.pos);
1362
1363                                         retVal = __gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, TRUE);
1364
1365                                         if (MM_ERROR_NONE != retVal)
1366                                                 LOGE("failed to seek pending postion. just keep staying current position.\n");
1367
1368                                         player->pending_seek.is_pending = FALSE;
1369                                 }
1370                         }
1371
1372                         if (oldstate == newstate) {
1373                                 LOGD("pipeline reports state transition to old state");
1374                                 break;
1375                         }
1376
1377                         switch (newstate) {
1378                         case GST_STATE_VOID_PENDING:
1379                                 break;
1380
1381                         case GST_STATE_NULL:
1382                                 break;
1383
1384                         case GST_STATE_READY:
1385                                 break;
1386
1387                         case GST_STATE_PAUSED:
1388                                 {
1389                                         gboolean prepare_async = FALSE;
1390                                         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
1391
1392                                         if (!player->audio_cb_probe_id && player->set_mode.pcm_extraction && !player->audio_stream_render_cb_ex)
1393                                                 __mmplayer_configure_audio_callback(player);
1394
1395                                         if (!player->sent_bos && oldstate == GST_STATE_READY) {
1396                                                 // managed prepare async case
1397                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1398                                                 LOGD("checking prepare mode for async transition - %d", prepare_async);
1399                                         }
1400
1401                                         if (MMPLAYER_IS_STREAMING(player) || MMPLAYER_IS_MS_BUFF_SRC(player) || prepare_async) {
1402                                                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
1403
1404                                                 if (MMPLAYER_IS_STREAMING(player) && (player->streamer))
1405                                                         __mm_player_streaming_set_content_bitrate(player->streamer,
1406                                                                 player->total_maximum_bitrate, player->total_bitrate);
1407
1408                                                 if (player->pending_seek.is_pending) {
1409                                                         LOGW("trying to do pending seek");
1410                                                         MMPLAYER_CMD_LOCK(player);
1411                                                         __gst_pending_seek(player);
1412                                                         MMPLAYER_CMD_UNLOCK(player);
1413                                                 }
1414                                         }
1415                                 }
1416                                 break;
1417
1418                         case GST_STATE_PLAYING:
1419                                 {
1420                                         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
1421
1422                                         if (MMPLAYER_IS_STREAMING(player)) {
1423                                                 // managed prepare async case when buffering is completed
1424                                                 // pending state should be reset otherwise, it's still playing even though it's resumed after bufferging.
1425                                                 if ((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING) ||
1426                                                         (MMPLAYER_PENDING_STATE(player) == MM_PLAYER_STATE_PLAYING))
1427                                                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
1428
1429                                                 if (MMPLAYER_IS_RTSP_STREAMING(player) && (MMPLAYER_IS_LIVE_STREAMING(player))) {
1430
1431                                                         LOGD("Current Buffering Percent = %d", player->streamer->buffering_percent);
1432                                                         if (player->streamer->buffering_percent < 100) {
1433
1434                                                                 MMMessageParamType msg_param = {0, };
1435                                                                 LOGW("Posting Buffering Completed Message to Application !!!");
1436
1437                                                                 msg_param.connection.buffering = 100;
1438                                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_BUFFERING, &msg_param);
1439                                                         }
1440                                                 }
1441                                         }
1442
1443                                         if (player->gapless.stream_changed) {
1444                                                 _mmplayer_update_content_attrs(player, ATTR_ALL);
1445                                                 player->gapless.stream_changed = FALSE;
1446                                         }
1447
1448                                         if (player->doing_seek && async_done) {
1449                                                 player->doing_seek = FALSE;
1450                                                 async_done = FALSE;
1451                                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1452                                         }
1453                                 }
1454                                 break;
1455
1456                         default:
1457                                 break;
1458                         }
1459                 }
1460                 break;
1461
1462         case GST_MESSAGE_CLOCK_LOST:
1463                         {
1464                                 GstClock *clock = NULL;
1465                                 gboolean need_new_clock = FALSE;
1466
1467                                 gst_message_parse_clock_lost(msg, &clock);
1468                                 LOGD("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1469
1470                                 if (!player->videodec_linked)
1471                                         need_new_clock = TRUE;
1472                                 else if (!player->ini.use_system_clock)
1473                                         need_new_clock = TRUE;
1474
1475                                 if (need_new_clock) {
1476                                         LOGD("Provide clock is TRUE, do pause->resume\n");
1477                                         __gst_pause(player, FALSE);
1478                                         __gst_resume(player, FALSE);
1479                                 }
1480                         }
1481                         break;
1482
1483         case GST_MESSAGE_NEW_CLOCK:
1484                         {
1485                                 GstClock *clock = NULL;
1486                                 gst_message_parse_new_clock(msg, &clock);
1487                                 LOGD("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME(clock) : "NULL"));
1488                         }
1489                         break;
1490
1491         case GST_MESSAGE_ELEMENT:
1492                         {
1493                                 const gchar *structure_name;
1494                                 gint count = 0, idx = 0;
1495                                 MMHandleType attrs = 0;
1496
1497                                 attrs = MMPLAYER_GET_ATTRS(player);
1498                                 if (!attrs) {
1499                                         LOGE("cannot get content attribute");
1500                                         break;
1501                                 }
1502
1503                                 if (gst_message_get_structure(msg) == NULL)
1504                                         break;
1505
1506                                 structure_name = gst_structure_get_name(gst_message_get_structure(msg));
1507                                 if (!structure_name)
1508                                         break;
1509
1510                                 LOGD("GST_MESSAGE_ELEMENT %s from %s", structure_name, GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)));
1511
1512                                 if (!strcmp(structure_name, "adaptive-streaming-variant")) {
1513                                         const GValue *var_info = NULL;
1514
1515                                         var_info = gst_structure_get_value(gst_message_get_structure(msg), "video-variant-info");
1516                                         if (var_info != NULL) {
1517                                                 if (player->adaptive_info.var_list)
1518                                                         g_list_free_full(player->adaptive_info.var_list, g_free);
1519
1520                                                 /* share addr or copy the list */
1521                                                 player->adaptive_info.var_list =
1522                                                         g_list_copy_deep((GList *)g_value_get_pointer(var_info), (GCopyFunc)__mmplayer_adaptive_var_info, NULL);
1523
1524                                                 count = g_list_length(player->adaptive_info.var_list);
1525                                                 if (count > 0) {
1526                                                         VariantData *temp = NULL;
1527
1528                                                         /* print out for debug */
1529                                                         LOGD("num of variant_info %d", count);
1530                                                         for (idx = 0; idx < count; idx++) {
1531                                                                 temp = g_list_nth_data(player->adaptive_info.var_list, idx);
1532                                                                 if (temp)
1533                                                                         LOGD("variant(%d) [b]%d [w]%d [h]%d ", idx, temp->bandwidth, temp->width, temp->height);
1534                                                         }
1535                                                 }
1536                                         }
1537                                 }
1538
1539                                 if (!strcmp(structure_name, "prepare-decode-buffers")) {
1540                                         gint num_buffers = 0;
1541                                         gint extra_num_buffers = 0;
1542
1543                                         if (gst_structure_get_int(gst_message_get_structure(msg), "num_buffers", &num_buffers)) {
1544                                                 player->video_num_buffers = num_buffers;
1545                                                 LOGD("video_num_buffers : %d", player->video_num_buffers);
1546                                         }
1547
1548                                         if (gst_structure_get_int(gst_message_get_structure(msg), "extra_num_buffers", &extra_num_buffers)) {
1549                                                 player->video_extra_num_buffers = extra_num_buffers;
1550                                                 LOGD("num_of_vout_extra num buffers : %d", extra_num_buffers);
1551                                         }
1552                                         break;
1553                                 }
1554
1555                                 if (!strcmp(structure_name, "Language_list")) {
1556                                         const GValue *lang_list = NULL;
1557                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1558                                         if (lang_list != NULL) {
1559                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1560                                                 if (count > 1)
1561                                                         LOGD("Total audio tracks(from parser) = %d \n", count);
1562                                         }
1563                                 }
1564
1565                                 if (!strcmp(structure_name, "Ext_Sub_Language_List")) {
1566                                         const GValue *lang_list = NULL;
1567                                         MMPlayerLangStruct *temp = NULL;
1568
1569                                         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
1570                                         if (lang_list != NULL) {
1571                                                 count = g_list_length((GList *)g_value_get_pointer(lang_list));
1572                                                 if (count) {
1573                                                         MMPLAYER_SUBTITLE_INFO_LOCK(player);
1574                                                         player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
1575                                                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)count);
1576                                                         if (mmf_attrs_commit(attrs))
1577                                                                 LOGE("failed to commit.\n");
1578                                                         LOGD("Total subtitle tracks = %d \n", count);
1579
1580                                                         while (count) {
1581                                                                 temp = g_list_nth_data(player->subtitle_language_list, count - 1);
1582                                                                 if (temp)
1583                                                                         LOGD("value of lang_key is %s and lang_code is %s",
1584                                                                                                 temp->language_key, temp->language_code);
1585                                                                 count--;
1586                                                         }
1587                                                         MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
1588                                                         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
1589                                                 }
1590                                         }
1591                                 }
1592
1593                                 /* custom message */
1594                                 if (!strcmp(structure_name, "audio_codec_not_supported")) {
1595                                         MMMessageParamType msg_param = {0,};
1596                                         msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
1597                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
1598                                 }
1599
1600                                 /* custom message for RTSP attribute :
1601                                     RTSP case, buffer is not come from server before PLAYING state. However,we have to get attribute after PAUSE state chaged.
1602                                     sdp which has contents info is received when rtsp connection is opened.
1603                                     extract duration ,codec info , resolution from sdp and get it by GstMessage */
1604                                 if (!strcmp(structure_name, "rtspsrc_properties")) {
1605
1606                                         gchar *audio_codec = NULL;
1607                                         gchar *video_codec = NULL;
1608                                         gchar *video_frame_size = NULL;
1609
1610                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_duration", G_TYPE_UINT64, &player->duration, NULL);
1611                                         LOGD("rtsp duration : %lld msec", GST_TIME_AS_MSECONDS(player->duration));
1612                                         player->streaming_type = __mmplayer_get_stream_service_type(player);
1613                                         mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(player->duration));
1614
1615                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_audio_codec", G_TYPE_STRING, &audio_codec, NULL);
1616                                         LOGD("rtsp_audio_codec : %s", audio_codec);
1617                                         if (audio_codec)
1618                                                 mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
1619
1620                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_codec", G_TYPE_STRING, &video_codec, NULL);
1621                                         LOGD("rtsp_video_codec : %s", video_codec);
1622                                         if (video_codec)
1623                                                 mm_attrs_set_string_by_name(player->attrs, "content_video_codec", video_codec);
1624
1625                                         gst_structure_get(gst_message_get_structure(msg), "rtsp_video_frame_size", G_TYPE_STRING, &video_frame_size, NULL);
1626                                         LOGD("rtsp_video_frame_size : %s", video_frame_size);
1627                                         if (video_frame_size) {
1628
1629                                                 char *seperator = strchr(video_frame_size, '-');
1630                                                 if (seperator) {
1631
1632                                                         char video_width[10] = {0,};
1633                                                         int frame_size_len = strlen(video_frame_size);
1634                                                         int separtor_len = strlen(seperator);
1635
1636                                                         strncpy(video_width, video_frame_size, (frame_size_len - separtor_len));
1637                                                         mm_attrs_set_int_by_name(attrs, "content_video_width", atoi(video_width));
1638
1639                                                         seperator++;
1640                                                         mm_attrs_set_int_by_name(attrs, "content_video_height", atoi(seperator));
1641                                                 }
1642                                         }
1643
1644                                         if (mmf_attrs_commit(attrs))
1645                                                 LOGE("failed to commit.\n");
1646                                 }
1647                         }
1648                         break;
1649
1650         case GST_MESSAGE_DURATION_CHANGED:
1651                 {
1652                         LOGD("GST_MESSAGE_DURATION_CHANGED\n");
1653                         if (!__mmplayer_gst_handle_duration(player, msg))
1654                                 LOGW("failed to update duration");
1655                 }
1656
1657                 break;
1658
1659         case GST_MESSAGE_ASYNC_START:
1660                         LOGD("GST_MESSAGE_ASYNC_START : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1661                 break;
1662
1663         case GST_MESSAGE_ASYNC_DONE:
1664                 {
1665                         LOGD("GST_MESSAGE_ASYNC_DONE : %s\n", GST_ELEMENT_NAME(GST_MESSAGE_SRC(msg)));
1666
1667                         /* we only handle messages from pipeline */
1668                         if (msg->src != (GstObject *)player->pipeline->mainbin[MMPLAYER_M_PIPE].gst)
1669                                 break;
1670
1671                         if (player->doing_seek) {
1672                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
1673                                         player->doing_seek = FALSE;
1674                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
1675                                 } else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING) {
1676                                         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1677                                                 (player->streamer) &&
1678                                                 (player->streamer->streaming_buffer_type == BUFFER_TYPE_MUXED) &&
1679                                                 (player->streamer->is_buffering == FALSE)) {
1680                                                 GstQuery *query = NULL;
1681                                                 gboolean busy = FALSE;
1682                                                 gint percent = 0;
1683
1684                                                 if (player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer) {
1685                                                         query = gst_query_new_buffering(GST_FORMAT_PERCENT);
1686                                                         if (gst_element_query(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer, query))
1687                                                                 gst_query_parse_buffering_percent(query, &busy, &percent);
1688                                                         gst_query_unref(query);
1689
1690                                                         LOGD("buffered percent(%s): %d\n",
1691                                                                 GST_ELEMENT_NAME(player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffer), percent);
1692                                                 }
1693
1694                                                 if (percent >= 100) {
1695                                                         player->streamer->is_buffering = FALSE;
1696                                                         __mmplayer_handle_buffering_message(player);
1697                                                 }
1698                                         }
1699
1700                                         async_done = TRUE;
1701                                 }
1702                         }
1703                 }
1704                 break;
1705
1706         #if 0 /* delete unnecessary logs */
1707         case GST_MESSAGE_REQUEST_STATE:         LOGD("GST_MESSAGE_REQUEST_STATE\n"); break;
1708         case GST_MESSAGE_STEP_START:            LOGD("GST_MESSAGE_STEP_START\n"); break;
1709         case GST_MESSAGE_QOS:                           LOGD("GST_MESSAGE_QOS\n"); break;
1710         case GST_MESSAGE_PROGRESS:                      LOGD("GST_MESSAGE_PROGRESS\n"); break;
1711         case GST_MESSAGE_ANY:                           LOGD("GST_MESSAGE_ANY\n"); break;
1712         case GST_MESSAGE_INFO:                          LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1713         case GST_MESSAGE_STATE_DIRTY:           LOGD("GST_MESSAGE_STATE_DIRTY\n"); break;
1714         case GST_MESSAGE_STEP_DONE:                     LOGD("GST_MESSAGE_STEP_DONE\n"); break;
1715         case GST_MESSAGE_CLOCK_PROVIDE:         LOGD("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
1716         case GST_MESSAGE_STRUCTURE_CHANGE:      LOGD("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
1717         case GST_MESSAGE_STREAM_STATUS:         LOGD("GST_MESSAGE_STREAM_STATUS\n"); break;
1718         case GST_MESSAGE_APPLICATION:           LOGD("GST_MESSAGE_APPLICATION\n"); break;
1719         case GST_MESSAGE_SEGMENT_START:         LOGD("GST_MESSAGE_SEGMENT_START\n"); break;
1720         case GST_MESSAGE_SEGMENT_DONE:          LOGD("GST_MESSAGE_SEGMENT_DONE\n"); break;
1721         case GST_MESSAGE_LATENCY:                               LOGD("GST_MESSAGE_LATENCY\n"); break;
1722         #endif
1723
1724         default:
1725                 break;
1726         }
1727
1728         /* should not call 'gst_message_unref(msg)' */
1729         return;
1730 }
1731
1732 static gboolean
1733 __mmplayer_gst_handle_duration(mm_player_t* player, GstMessage* msg)
1734 {
1735         gint64 bytes = 0;
1736
1737         MMPLAYER_FENTER();
1738
1739         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
1740         MMPLAYER_RETURN_VAL_IF_FAIL(msg, FALSE);
1741
1742         if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
1743                 (msg->src) && (msg->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst)) {
1744                 LOGD("msg src : [%s]", GST_ELEMENT_NAME(GST_ELEMENT_CAST(msg->src)));
1745
1746                 if (gst_element_query_duration(GST_ELEMENT_CAST(msg->src), GST_FORMAT_BYTES, &bytes)) {
1747                         LOGD("data total size of http content: %lld", bytes);
1748                         player->http_content_size = (bytes > 0) ? (bytes) : (0);
1749                 }
1750         } else
1751                 /* handling audio clip which has vbr. means duration is keep changing */
1752                 _mmplayer_update_content_attrs(player, ATTR_DURATION);
1753
1754         MMPLAYER_FLEAVE();
1755
1756         return TRUE;
1757 }
1758
1759 static void __mmplayer_get_metadata_360_from_tags(GstTagList *tags,
1760                 mm_player_spherical_metadata_t *metadata) {
1761         gst_tag_list_get_int(tags, "is_spherical", &metadata->is_spherical);
1762         gst_tag_list_get_int(tags, "is_stitched", &metadata->is_stitched);
1763         gst_tag_list_get_string(tags, "stitching_software",
1764                         &metadata->stitching_software);
1765         gst_tag_list_get_string(tags, "projection_type",
1766                         &metadata->projection_type_string);
1767         gst_tag_list_get_string(tags, "stereo_mode", &metadata->stereo_mode_string);
1768         gst_tag_list_get_int(tags, "source_count", &metadata->source_count);
1769         gst_tag_list_get_int(tags, "init_view_heading",
1770                         &metadata->init_view_heading);
1771         gst_tag_list_get_int(tags, "init_view_pitch", &metadata->init_view_pitch);
1772         gst_tag_list_get_int(tags, "init_view_roll", &metadata->init_view_roll);
1773         gst_tag_list_get_int(tags, "timestamp", &metadata->timestamp);
1774         gst_tag_list_get_int(tags, "full_pano_width_pixels",
1775                         &metadata->full_pano_width_pixels);
1776         gst_tag_list_get_int(tags, "full_pano_height_pixels",
1777                         &metadata->full_pano_height_pixels);
1778         gst_tag_list_get_int(tags, "cropped_area_image_width",
1779                         &metadata->cropped_area_image_width);
1780         gst_tag_list_get_int(tags, "cropped_area_image_height",
1781                         &metadata->cropped_area_image_height);
1782         gst_tag_list_get_int(tags, "cropped_area_left",
1783                         &metadata->cropped_area_left);
1784         gst_tag_list_get_int(tags, "cropped_area_top", &metadata->cropped_area_top);
1785         gst_tag_list_get_int(tags, "ambisonic_type", &metadata->ambisonic_type);
1786         gst_tag_list_get_int(tags, "ambisonic_format", &metadata->ambisonic_format);
1787         gst_tag_list_get_int(tags, "ambisonic_order", &metadata->ambisonic_order);
1788 }
1789
1790 static gboolean
1791 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg)
1792 {
1793
1794 /* macro for better code readability */
1795 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
1796 if (gst_tag_list_get_string(tag_list, gsttag, &string)) {\
1797         if (string != NULL) { \
1798                 SECURE_LOGD("update tag string : %s\n", string); \
1799                 if (strlen(string) > MM_MAX_STRING_LENGTH) { \
1800                         char *new_string = malloc(MM_MAX_STRING_LENGTH); \
1801                         strncpy(new_string, string, MM_MAX_STRING_LENGTH-1); \
1802                         new_string[MM_MAX_STRING_LENGTH-1] = '\0'; \
1803                         mm_attrs_set_string_by_name(attribute, playertag, new_string); \
1804                         g_free(new_string); \
1805                         new_string = NULL; \
1806                 } else { \
1807                         mm_attrs_set_string_by_name(attribute, playertag, string); \
1808                 } \
1809                 g_free(string); \
1810                 string = NULL; \
1811         } \
1812 }
1813
1814 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
1815 do {    \
1816         GstSample *sample = NULL;\
1817         if (gst_tag_list_get_sample_index(tag_list, gsttag, index, &sample)) {\
1818                 GstMapInfo info = GST_MAP_INFO_INIT;\
1819                 buffer = gst_sample_get_buffer(sample);\
1820                 if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) {\
1821                         LOGD("failed to get image data from tag");\
1822                         gst_sample_unref(sample);\
1823                         return FALSE;\
1824                 } \
1825                 SECURE_LOGD("update album cover data : %p, size : %d\n", info.data, info.size);\
1826                 MMPLAYER_FREEIF(player->album_art);\
1827                 player->album_art = (gchar *)g_malloc(info.size);\
1828                 if (player->album_art) {\
1829                         memcpy(player->album_art, info.data, info.size);\
1830                         mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, info.size);\
1831                         if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)) {\
1832                                 msg_param.data = (void *)player->album_art;\
1833                                 msg_param.size = info.size;\
1834                                 MMPLAYER_POST_MSG(player, MM_MESSAGE_IMAGE_BUFFER, &msg_param);\
1835                                 SECURE_LOGD("post message image buffer data : %p, size : %d\n", info.data, info.size);\
1836                         } \
1837                 } \
1838                 gst_buffer_unmap(buffer, &info);\
1839                 gst_sample_unref(sample);\
1840         }       \
1841 } while (0)
1842
1843 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
1844 do {    \
1845         if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint)) { \
1846                 if (v_uint) { \
1847                         int i = 0; \
1848                         gchar *tag_list_str = NULL; \
1849                         MMPlayerTrackType track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
1850                         if (strstr(GST_OBJECT_NAME(msg->src), "audio")) \
1851                                 track_type = MM_PLAYER_TRACK_TYPE_AUDIO; \
1852                         else if (strstr(GST_OBJECT_NAME(msg->src), "video")) \
1853                                 track_type = MM_PLAYER_TRACK_TYPE_VIDEO; \
1854                         else \
1855                                 track_type = MM_PLAYER_TRACK_TYPE_TEXT; \
1856                         if (!strncmp(gsttag, GST_TAG_BITRATE, strlen(GST_TAG_BITRATE))) { \
1857                                 if (track_type == MM_PLAYER_TRACK_TYPE_AUDIO) \
1858                                         mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
1859                                 player->bitrate[track_type] = v_uint; \
1860                                 player->total_bitrate = 0; \
1861                                 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
1862                                         player->total_bitrate += player->bitrate[i]; \
1863                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate); \
1864                                 SECURE_LOGD("update bitrate %d[bps] of stream #%d.\n", v_uint, (int)track_type); \
1865                         } else if (!strncmp(gsttag, GST_TAG_MAXIMUM_BITRATE, strlen(GST_TAG_MAXIMUM_BITRATE))) { \
1866                                 player->maximum_bitrate[track_type] = v_uint; \
1867                                 player->total_maximum_bitrate = 0; \
1868                                 for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) \
1869                                         player->total_maximum_bitrate += player->maximum_bitrate[i]; \
1870                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate);\
1871                                 SECURE_LOGD("update maximum bitrate %d[bps] of stream #%d\n", v_uint, (int)track_type);\
1872                         } else { \
1873                                 mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
1874                         } \
1875                         v_uint = 0;\
1876                         g_free(tag_list_str); \
1877                 } \
1878         } \
1879 } while (0)
1880
1881 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
1882 if (gst_tag_list_get_date(tag_list, gsttag, &date)) {\
1883         if (date != NULL) {\
1884                 string = g_strdup_printf("%d", g_date_get_year(date));\
1885                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1886                 SECURE_LOGD("metainfo year : %s\n", string);\
1887                 MMPLAYER_FREEIF(string);\
1888                 g_date_free(date);\
1889         } \
1890 }
1891
1892 #define MMPLAYER_UPDATE_TAG_DATE_TIME(gsttag, attribute, playertag) \
1893 if (gst_tag_list_get_date_time(tag_list, gsttag, &datetime)) {\
1894         if (datetime != NULL) {\
1895                 string = g_strdup_printf("%d", gst_date_time_get_year(datetime));\
1896                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1897                 SECURE_LOGD("metainfo year : %s\n", string);\
1898                 MMPLAYER_FREEIF(string);\
1899                 gst_date_time_unref(datetime);\
1900         } \
1901 }
1902
1903 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
1904 if (gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64)) {\
1905         if (v_uint64) {\
1906                 /* FIXIT : don't know how to store date */\
1907                 g_assert(1);\
1908                 v_uint64 = 0;\
1909         } \
1910 }
1911
1912 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
1913 if (gst_tag_list_get_double(tag_list, gsttag, &v_double)) {\
1914         if (v_double) {\
1915                 /* FIXIT : don't know how to store date */\
1916                 g_assert(1);\
1917                 v_double = 0;\
1918         } \
1919 }
1920
1921         /* function start */
1922         GstTagList* tag_list = NULL;
1923
1924         MMHandleType attrs = 0;
1925
1926         char *string = NULL;
1927         guint v_uint = 0;
1928         GDate *date = NULL;
1929         GstDateTime *datetime = NULL;
1930         /* album cover */
1931         GstBuffer *buffer = NULL;
1932         gint index = 0;
1933         MMMessageParamType msg_param = {0, };
1934
1935         /* currently not used. but those are needed for above macro */
1936         //guint64 v_uint64 = 0;
1937         //gdouble v_double = 0;
1938
1939         MMPLAYER_RETURN_VAL_IF_FAIL(player && msg, FALSE);
1940
1941         attrs = MMPLAYER_GET_ATTRS(player);
1942
1943         MMPLAYER_RETURN_VAL_IF_FAIL(attrs, FALSE);
1944
1945         /* get tag list from gst message */
1946         gst_message_parse_tag(msg, &tag_list);
1947
1948         /* store tags to player attributes */
1949         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
1950         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
1951         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
1952         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
1953         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
1954         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
1955         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
1956         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
1957         MMPLAYER_UPDATE_TAG_DATE_TIME(GST_TAG_DATE_TIME, attrs, "tag_date");
1958         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
1959         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
1960         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
1961         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
1962         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
1963         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
1964         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
1965         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
1966         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
1967         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
1968         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
1969         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
1970         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
1971         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
1972         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
1973         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
1974         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
1975         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
1976         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
1977         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
1978         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
1979         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
1980         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
1981         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
1982         MMPLAYER_UPDATE_TAG_LOCK(player);
1983         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
1984         MMPLAYER_UPDATE_TAG_UNLOCK(player);
1985         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
1986         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
1987         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
1988         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
1989         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
1990         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
1991         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
1992         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
1993         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
1994         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
1995         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
1996         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
1997         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_IMAGE_ORIENTATION, attrs, "content_video_orientation");
1998
1999         if (strstr(GST_OBJECT_NAME(msg->src), "demux")) {
2000                 if (player->video360_metadata.is_spherical == -1) {
2001                         __mmplayer_get_metadata_360_from_tags(tag_list, &player->video360_metadata);
2002                         mm_attrs_set_int_by_name(attrs, "content_video_is_spherical",
2003                                         player->video360_metadata.is_spherical);
2004                         if (player->video360_metadata.is_spherical == 1) {
2005                                 LOGD("This is spherical content for 360 playback.");
2006                                 player->is_content_spherical = TRUE;
2007                         } else {
2008                                 LOGD("This is not spherical content");
2009                                 player->is_content_spherical = FALSE;
2010                         }
2011
2012                         if (player->video360_metadata.projection_type_string) {
2013                                 if (!strcmp(player->video360_metadata.projection_type_string, "equirectangular")) {
2014                                         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
2015                                 } else {
2016                                         LOGE("Projection %s: code not implemented.\n", player->video360_metadata.projection_type_string);
2017                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
2018                                 }
2019                         }
2020
2021                         if (player->video360_metadata.stereo_mode_string) {
2022                                 if (!strcmp(player->video360_metadata.stereo_mode_string, "mono")) {
2023                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
2024                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "left-right")) {
2025                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_LEFT_RIGHT;
2026                                 } else if (!strcmp(player->video360_metadata.stereo_mode_string, "top-bottom")) {
2027                                         player->video360_metadata.stereo_mode = VIDEO360_MODE_STEREOSCOPIC_TOP_BOTTOM;
2028                                 } else {
2029                                         LOGE("Stereo mode %s: code not implemented.\n", player->video360_metadata.stereo_mode_string);
2030                                         player->is_content_spherical = player->is_video360_enabled = FALSE;
2031                                 }
2032                         }
2033                 }
2034         }
2035
2036         if (mmf_attrs_commit(attrs))
2037                 LOGE("failed to commit.\n");
2038
2039         gst_tag_list_free(tag_list);
2040
2041         return TRUE;
2042 }
2043
2044 static void
2045 __mmplayer_gst_rtp_no_more_pads(GstElement *element,  gpointer data)
2046 {
2047         mm_player_t* player = (mm_player_t*) data;
2048
2049         MMPLAYER_FENTER();
2050
2051         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
2052           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
2053           * num_dynamic_pad. and this is no-more-pad situation which means no more pad will be added.
2054           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
2055
2056           * [1] audio and video will be dumped with filesink.
2057           * [2] autoplugging is done by just using pad caps.
2058           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
2059           * and the video will be dumped via filesink.
2060           */
2061         if (player->num_dynamic_pad == 0) {
2062                 LOGD("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
2063
2064                 if (!__mmplayer_gst_remove_fakesink(player,
2065                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]))
2066                         /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
2067                          * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
2068                          * source element are not same. To overcome this situation, this function will called
2069                          * several places and several times. Therefore, this is not an error case.
2070                          */
2071                         return;
2072         }
2073
2074         /* create dot before error-return. for debugging */
2075         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-no-more-pad");
2076
2077         player->no_more_pad = TRUE;
2078
2079         MMPLAYER_FLEAVE();
2080 }
2081
2082 static gboolean
2083 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink)
2084 {
2085         GstElement* parent = NULL;
2086
2087         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, FALSE);
2088
2089         /* if we have no fakesink. this meas we are using decodebin which doesn'
2090         t need to add extra fakesink */
2091         MMPLAYER_RETURN_VAL_IF_FAIL(fakesink, TRUE);
2092
2093         /* lock */
2094         MMPLAYER_FSINK_LOCK(player);
2095
2096         if (!fakesink->gst)
2097                 goto ERROR;
2098
2099         /* get parent of fakesink */
2100         parent = (GstElement*)gst_object_get_parent((GstObject*)fakesink->gst);
2101         if (!parent) {
2102                 LOGD("fakesink already removed\n");
2103                 goto ERROR;
2104         }
2105
2106         gst_element_set_locked_state(fakesink->gst, TRUE);
2107
2108         /* setting the state to NULL never returns async
2109          * so no need to wait for completion of state transiton
2110          */
2111         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(fakesink->gst, GST_STATE_NULL))
2112                 LOGE("fakesink state change failure!\n");
2113                 /* FIXIT : should I return here? or try to proceed to next? */
2114                 /* return FALSE; */
2115
2116         /* remove fakesink from it's parent */
2117         if (!gst_bin_remove(GST_BIN(parent), fakesink->gst)) {
2118                 LOGE("failed to remove fakesink\n");
2119
2120                 gst_object_unref(parent);
2121
2122                 goto ERROR;
2123         }
2124
2125         gst_object_unref(parent);
2126
2127         LOGD("state-holder removed\n");
2128
2129         gst_element_set_locked_state(fakesink->gst, FALSE);
2130
2131         MMPLAYER_FSINK_UNLOCK(player);
2132         return TRUE;
2133
2134 ERROR:
2135         if (fakesink->gst)
2136                 gst_element_set_locked_state(fakesink->gst, FALSE);
2137
2138         MMPLAYER_FSINK_UNLOCK(player);
2139         return FALSE;
2140 }
2141
2142
2143 static void
2144 __mmplayer_gst_rtp_dynamic_pad(GstElement *element, GstPad *pad, gpointer data)
2145 {
2146         GstPad *sinkpad = NULL;
2147         GstCaps* caps = NULL;
2148         GstElement* new_element = NULL;
2149         GstStructure* str = NULL;
2150         const gchar* name = NULL;
2151
2152         mm_player_t* player = (mm_player_t*) data;
2153
2154         MMPLAYER_FENTER();
2155
2156         MMPLAYER_RETURN_IF_FAIL(element && pad);
2157         MMPLAYER_RETURN_IF_FAIL(player &&
2158                                         player->pipeline &&
2159                                         player->pipeline->mainbin);
2160
2161
2162         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2163          * num_dynamic_pad will decreased after creating a sinkbin.
2164          */
2165         player->num_dynamic_pad++;
2166         LOGD("stream count inc : %d\n", player->num_dynamic_pad);
2167
2168         caps = gst_pad_query_caps(pad, NULL);
2169
2170         MMPLAYER_CHECK_NULL(caps);
2171
2172         /* clear  previous result*/
2173         player->have_dynamic_pad = FALSE;
2174
2175         str = gst_caps_get_structure(caps, 0);
2176
2177         if (!str) {
2178                 LOGE("cannot get structure from caps.\n");
2179                 goto ERROR;
2180         }
2181
2182         name = gst_structure_get_name(str);
2183         if (!name) {
2184                 LOGE("cannot get mimetype from structure.\n");
2185                 goto ERROR;
2186         }
2187
2188         if (strstr(name, "video")) {
2189                 gint stype = 0;
2190                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2191
2192                 if (stype == MM_DISPLAY_SURFACE_NULL || stype == MM_DISPLAY_SURFACE_REMOTE) {
2193                         if (player->v_stream_caps) {
2194                                 gst_caps_unref(player->v_stream_caps);
2195                                 player->v_stream_caps = NULL;
2196                         }
2197
2198                         new_element = gst_element_factory_make("fakesink", NULL);
2199                         player->num_dynamic_pad--;
2200                         goto NEW_ELEMENT;
2201                 }
2202         }
2203
2204         /* clear  previous result*/
2205         player->have_dynamic_pad = FALSE;
2206
2207         if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
2208                 LOGE("failed to autoplug for caps");
2209                 goto ERROR;
2210         }
2211
2212         /* check if there's dynamic pad*/
2213         if (player->have_dynamic_pad) {
2214                 LOGE("using pad caps assums there's no dynamic pad !\n");
2215                 goto ERROR;
2216         }
2217
2218         gst_caps_unref(caps);
2219         caps = NULL;
2220
2221 NEW_ELEMENT:
2222
2223         /* excute new_element if created*/
2224         if (new_element) {
2225                 LOGD("adding new element to pipeline\n");
2226
2227                 /* set state to READY before add to bin */
2228                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_READY);
2229
2230                 /* add new element to the pipeline */
2231                 if (FALSE == gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)) {
2232                         LOGE("failed to add autoplug element to bin\n");
2233                         goto ERROR;
2234                 }
2235
2236                 /* get pad from element */
2237                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(new_element), "sink");
2238                 if (!sinkpad) {
2239                         LOGE("failed to get sinkpad from autoplug element\n");
2240                         goto ERROR;
2241                 }
2242
2243                 /* link it */
2244                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2245                         LOGE("failed to link autoplug element\n");
2246                         goto ERROR;
2247                 }
2248
2249                 gst_object_unref(sinkpad);
2250                 sinkpad = NULL;
2251
2252                 /* run. setting PLAYING here since streamming source is live source */
2253                 MMPLAYER_ELEMENT_SET_STATE(new_element, GST_STATE_PLAYING);
2254         }
2255
2256         if (caps)
2257                 gst_caps_unref(caps);
2258
2259         MMPLAYER_FLEAVE();
2260
2261         return;
2262
2263 STATE_CHANGE_FAILED:
2264 ERROR:
2265         /* FIXIT : take care if new_element has already added to pipeline */
2266         if (new_element)
2267                 gst_object_unref(GST_OBJECT(new_element));
2268
2269         if (sinkpad)
2270                 gst_object_unref(GST_OBJECT(sinkpad));
2271
2272         if (caps)
2273                 gst_caps_unref(caps);
2274
2275         /* FIXIT : how to inform this error to MSL ????? */
2276         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2277          * then post an error to application
2278          */
2279 }
2280
2281 static GstPadProbeReturn
2282 __mmplayer_gst_selector_blocked(GstPad* pad, GstPadProbeInfo *info, gpointer data)
2283 {
2284         LOGD("pad(%s:%s) is blocked", GST_DEBUG_PAD_NAME(pad));
2285         return GST_PAD_PROBE_OK;
2286 }
2287
2288 static GstPadProbeReturn
2289 __mmplayer_gst_selector_event_probe(GstPad * pad, GstPadProbeInfo * info, gpointer data)
2290 {
2291         GstPadProbeReturn ret = GST_PAD_PROBE_OK;
2292         GstEvent *event = GST_PAD_PROBE_INFO_DATA(info);
2293         mm_player_t* player = (mm_player_t*)data;
2294         GstCaps* caps = NULL;
2295         GstStructure* str = NULL;
2296         const gchar* name = NULL;
2297         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2298
2299
2300         if (GST_EVENT_IS_DOWNSTREAM(event)) {
2301                 if (GST_EVENT_TYPE(event) != GST_EVENT_STREAM_START &&
2302                         GST_EVENT_TYPE(event) != GST_EVENT_FLUSH_STOP &&
2303                         GST_EVENT_TYPE(event) != GST_EVENT_SEGMENT &&
2304                         GST_EVENT_TYPE(event) != GST_EVENT_EOS)
2305                         return ret;
2306         } else if (GST_EVENT_IS_UPSTREAM(event)) {
2307                 if (GST_EVENT_TYPE(event) != GST_EVENT_QOS)
2308                         return ret;
2309         }
2310
2311         caps = gst_pad_query_caps(pad, NULL);
2312         if (!caps) {
2313                 LOGE("failed to get caps from pad[%s:%s]", GST_DEBUG_PAD_NAME(pad));
2314                 return ret;
2315         }
2316
2317         str = gst_caps_get_structure(caps, 0);
2318         if (!str) {
2319                 LOGE("failed to get structure from caps");
2320                 goto ERROR;
2321         }
2322
2323         name = gst_structure_get_name(str);
2324         if (!name) {
2325                 LOGE("failed to get name from str");
2326                 goto ERROR;
2327         }
2328
2329         if (strstr(name, "audio")) {
2330                 stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2331         } else if (strstr(name, "video")) {
2332                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2333         } else {
2334                 /* text track is not supportable */
2335                 LOGE("invalid name %s", name);
2336                 goto ERROR;
2337         }
2338
2339         switch (GST_EVENT_TYPE(event)) {
2340         case GST_EVENT_EOS:
2341                 {
2342                         /* in case of gapless, drop eos event not to send it to sink */
2343                         if (player->gapless.reconfigure && !player->msg_posted) {
2344                                 LOGD("[%d] %s:%s EOS received but will be drop", stream_type, GST_DEBUG_PAD_NAME(pad));
2345                                 ret = GST_PAD_PROBE_DROP;
2346                         }
2347                         break;
2348                 }
2349         case GST_EVENT_STREAM_START:
2350                 {
2351                         gint64 stop_running_time = 0;
2352                         gint64 position_running_time = 0;
2353                         gint64 position = 0;
2354                         gint idx = 0;
2355
2356                         for (idx = MM_PLAYER_TRACK_TYPE_AUDIO; idx < MM_PLAYER_TRACK_TYPE_TEXT; idx++) {
2357                                 if ((player->gapless.update_segment[idx] == TRUE) ||
2358                                         !(player->selector[idx].event_probe_id)) {
2359                                         /* LOGW("[%d] skip", idx); */
2360                                         continue;
2361                                 }
2362
2363                                 if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].stop)) {
2364                                         stop_running_time =
2365                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2366                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].stop);
2367                                 } else if (GST_CLOCK_TIME_IS_VALID(player->gapless.segment[idx].duration)) {
2368                                         stop_running_time =
2369                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2370                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].duration);
2371                                 } else {
2372                                         LOGD("duration: %"GST_TIME_FORMAT, GST_TIME_ARGS(player->duration));
2373                                         stop_running_time =
2374                                                 gst_segment_to_running_time(&player->gapless.segment[idx],
2375                                                                 GST_FORMAT_TIME, player->duration);
2376                                 }
2377
2378                                 position_running_time =
2379                                         gst_segment_to_running_time(&player->gapless.segment[idx],
2380                                         GST_FORMAT_TIME, player->gapless.segment[idx].position);
2381
2382                                 LOGD("[type:%d] time info %" GST_TIME_FORMAT " , %"
2383                                         GST_TIME_FORMAT" , %" GST_TIME_FORMAT,
2384                                         idx,
2385                                         GST_TIME_ARGS(stop_running_time),
2386                                         GST_TIME_ARGS(position_running_time),
2387                                         GST_TIME_ARGS(gst_segment_to_running_time(&player->gapless.segment[idx],
2388                                         GST_FORMAT_TIME, player->gapless.segment[idx].start)));
2389
2390                                 position_running_time = MAX(position_running_time, stop_running_time);
2391                                 position_running_time -= gst_segment_to_running_time(&player->gapless.segment[idx],
2392                                                                                                 GST_FORMAT_TIME, player->gapless.segment[idx].start);
2393                                 position_running_time = MAX(0, position_running_time);
2394                                 position = MAX(position, position_running_time);
2395                         }
2396
2397                         if (position != 0) {
2398                                 LOGD("[%d]GST_EVENT_STREAM_START: start_time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2399                                         stream_type, GST_TIME_ARGS(player->gapless.start_time[stream_type]),
2400                                         GST_TIME_ARGS(player->gapless.start_time[stream_type] + position));
2401
2402                                 player->gapless.start_time[stream_type] += position;
2403                         }
2404                         break;
2405                 }
2406         case GST_EVENT_FLUSH_STOP:
2407                 {
2408                         LOGD("[%d] GST_EVENT_FLUSH_STOP", stream_type);
2409                         gst_segment_init(&player->gapless.segment[stream_type], GST_FORMAT_UNDEFINED);
2410                         player->gapless.start_time[stream_type] = 0;
2411                         break;
2412                 }
2413         case GST_EVENT_SEGMENT:
2414                 {
2415                         GstSegment segment;
2416                         GstEvent *tmpev;
2417
2418                         LOGD("[%d] GST_EVENT_SEGMENT", stream_type);
2419                         gst_event_copy_segment(event, &segment);
2420
2421                         if (segment.format == GST_FORMAT_TIME) {
2422                                 LOGD("segment base:%" GST_TIME_FORMAT ", offset:%" GST_TIME_FORMAT
2423                                          ", start:%" GST_TIME_FORMAT ", stop: %" GST_TIME_FORMAT
2424                                          ", time: %" GST_TIME_FORMAT ", pos: %" GST_TIME_FORMAT ", dur: %" GST_TIME_FORMAT,
2425                                         GST_TIME_ARGS(segment.base), GST_TIME_ARGS(segment.offset),
2426                                         GST_TIME_ARGS(segment.start), GST_TIME_ARGS(segment.stop),
2427                                         GST_TIME_ARGS(segment.time), GST_TIME_ARGS(segment.position), GST_TIME_ARGS(segment.duration));
2428
2429                                 /* keep the all the segment ev to cover the seeking */
2430                                 gst_segment_copy_into(&segment, &player->gapless.segment[stream_type]);
2431                                 player->gapless.update_segment[stream_type] = TRUE;
2432
2433                                 if (!player->gapless.running)
2434                                         break;
2435
2436                                 player->gapless.segment[stream_type].base = player->gapless.start_time[stream_type];
2437
2438                                 LOGD("[%d] new base: %" GST_TIME_FORMAT, stream_type, GST_TIME_ARGS(player->gapless.segment[stream_type].base));
2439
2440                                 tmpev = gst_event_new_segment(&player->gapless.segment[stream_type]);
2441                                 gst_event_set_seqnum(tmpev, gst_event_get_seqnum(event));
2442                                 gst_event_unref(event);
2443                                 GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2444                         }
2445                         break;
2446                 }
2447         case GST_EVENT_QOS:
2448                 {
2449                         gdouble proportion = 0.0;
2450                         GstClockTimeDiff diff = 0;
2451                         GstClockTime timestamp = 0;
2452                         gint64 running_time_diff = -1;
2453                         GstQOSType type = 0;
2454                         GstEvent *tmpev = NULL;
2455
2456                         running_time_diff = player->gapless.segment[stream_type].base;
2457
2458                         if (running_time_diff <= 0) /* don't need to adjust */
2459                                 break;
2460
2461                         gst_event_parse_qos(event, &type, &proportion, &diff, &timestamp);
2462                         gst_event_unref(event);
2463
2464                         if (timestamp < running_time_diff) {
2465                                 LOGW("QOS event from previous group");
2466                                 ret = GST_PAD_PROBE_DROP;
2467                                 break;
2468                         }
2469
2470                         LOGD("[%d] Adjusting QOS event: %" GST_TIME_FORMAT
2471                                  " - %" GST_TIME_FORMAT " = %" GST_TIME_FORMAT,
2472                                                 stream_type, GST_TIME_ARGS(timestamp),
2473                                                 GST_TIME_ARGS(running_time_diff),
2474                                                 GST_TIME_ARGS(timestamp - running_time_diff));
2475
2476                         timestamp -= running_time_diff;
2477
2478                         /* That case is invalid for QoS events */
2479                         if (diff < 0 && -diff > timestamp) {
2480                                 LOGW("QOS event from previous group");
2481                                 ret = GST_PAD_PROBE_DROP;
2482                                 break;
2483                         }
2484
2485                         tmpev = gst_event_new_qos(GST_QOS_TYPE_UNDERFLOW, proportion, diff, timestamp);
2486                         GST_PAD_PROBE_INFO_DATA(info) = tmpev;
2487
2488                         break;
2489                 }
2490         default:
2491                 break;
2492         }
2493
2494 ERROR:
2495         if (caps)
2496                 gst_caps_unref(caps);
2497         return ret;
2498 }
2499
2500 static void
2501 __mmplayer_gst_decode_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2502 {
2503         mm_player_t* player = NULL;
2504         GstElement* pipeline = NULL;
2505         GstElement* selector = NULL;
2506         GstElement* fakesink = NULL;
2507         GstCaps* caps = NULL;
2508         GstStructure* str = NULL;
2509         const gchar* name = NULL;
2510         GstPad* sinkpad = NULL;
2511         GstPad* srcpad = NULL;
2512         gboolean first_track = FALSE;
2513
2514         enum MainElementID elemId = MMPLAYER_M_NUM;
2515         MMPlayerTrackType stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2516
2517         /* check handles */
2518         player = (mm_player_t*)data;
2519
2520         MMPLAYER_RETURN_IF_FAIL(elem && pad);
2521         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2522
2523         //LOGD("pad-added signal handling\n");
2524
2525         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2526
2527         /* get mimetype from caps */
2528         caps = gst_pad_query_caps(pad, NULL);
2529         if (!caps) {
2530                 LOGE("cannot get caps from pad.\n");
2531                 goto ERROR;
2532         }
2533
2534         str = gst_caps_get_structure(caps, 0);
2535         if (!str) {
2536                 LOGE("cannot get structure from caps.\n");
2537                 goto ERROR;
2538         }
2539
2540         name = gst_structure_get_name(str);
2541         if (!name) {
2542                 LOGE("cannot get mimetype from structure.\n");
2543                 goto ERROR;
2544         }
2545
2546         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2547         //LOGD("detected mimetype : %s\n", name);
2548
2549         if (strstr(name, "video")) {
2550                 gint stype = 0;
2551
2552                 mm_attrs_set_int_by_name(player->attrs, "content_video_found", TRUE);
2553                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
2554
2555                 /* don't make video because of not required, and not support multiple track */
2556                 if (stype == MM_DISPLAY_SURFACE_NULL) {
2557                         LOGD("no video sink by null surface");
2558
2559                         gchar *caps_str = gst_caps_to_string(caps);
2560                         if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
2561                                 strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
2562                                 player->set_mode.video_zc = TRUE;
2563
2564                         MMPLAYER_FREEIF(caps_str);
2565
2566                         if (player->v_stream_caps) {
2567                                 gst_caps_unref(player->v_stream_caps);
2568                                 player->v_stream_caps = NULL;
2569                         }
2570
2571                         LOGD("create fakesink instead of videobin");
2572
2573                         /* fake sink */
2574                         fakesink = gst_element_factory_make("fakesink", NULL);
2575                         if (fakesink == NULL) {
2576                                 LOGE("ERROR : fakesink create error\n");
2577                                 goto ERROR;
2578                         }
2579
2580                         if (player->ini.set_dump_element_flag)
2581                                 __mmplayer_add_dump_buffer_probe(player, fakesink);
2582
2583                         player->video_fakesink = fakesink;
2584
2585                         /* store it as it's sink element */
2586                         __mmplayer_add_sink(player, player->video_fakesink);
2587
2588                         gst_bin_add(GST_BIN(pipeline), fakesink);
2589
2590                         // link
2591                         sinkpad = gst_element_get_static_pad(fakesink, "sink");
2592
2593                         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2594                                 LOGW("failed to link fakesink\n");
2595                                 gst_object_unref(GST_OBJECT(fakesink));
2596                                 goto ERROR;
2597                         }
2598
2599                         if (stype == MM_DISPLAY_SURFACE_REMOTE) {
2600                                 MMPLAYER_SIGNAL_CONNECT(player, sinkpad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2601                                                 "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
2602                         }
2603
2604                         if (player->set_mode.media_packet_video_stream) {
2605                                 g_object_set(G_OBJECT(fakesink), "signal-handoffs", TRUE, NULL);
2606
2607                                 MMPLAYER_SIGNAL_CONNECT(player,
2608                                                                                 G_OBJECT(fakesink),
2609                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2610                                                                                 "handoff",
2611                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
2612                                                                                 (gpointer)player);
2613
2614                                 MMPLAYER_SIGNAL_CONNECT(player,
2615                                                                                 G_OBJECT(fakesink),
2616                                                                                 MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
2617                                                                                 "preroll-handoff",
2618                                                                                 G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
2619                                                                                 (gpointer)player);
2620                         }
2621
2622                         g_object_set(G_OBJECT(fakesink), "async", TRUE, "sync", TRUE, NULL);
2623                         gst_element_set_state(fakesink, GST_STATE_PAUSED);
2624                         goto DONE;
2625                 }
2626
2627                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2628                         __mmplayer_gst_decode_callback(elem, pad, player);
2629                         goto DONE;
2630                 }
2631
2632                 LOGD("video selector \n");
2633                 elemId = MMPLAYER_M_V_INPUT_SELECTOR;
2634                 stream_type = MM_PLAYER_TRACK_TYPE_VIDEO;
2635         } else {
2636                 if (strstr(name, "audio")) {
2637                         gint samplerate = 0;
2638                         gint channels = 0;
2639
2640                         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
2641                                 __mmplayer_gst_decode_callback(elem, pad, player);
2642                                 goto DONE;
2643                         }
2644
2645                         LOGD("audio selector \n");
2646                         elemId = MMPLAYER_M_A_INPUT_SELECTOR;
2647                         stream_type = MM_PLAYER_TRACK_TYPE_AUDIO;
2648
2649                         gst_structure_get_int(str, "rate", &samplerate);
2650                         gst_structure_get_int(str, "channels", &channels);
2651
2652                         if ((channels > 0 && samplerate == 0)) {//exclude audio decoding
2653                                 /* fake sink */
2654                                 fakesink = gst_element_factory_make("fakesink", NULL);
2655                                 if (fakesink == NULL) {
2656                                         LOGE("ERROR : fakesink create error\n");
2657                                         goto ERROR;
2658                                 }
2659
2660                                 gst_bin_add(GST_BIN(pipeline), fakesink);
2661
2662                                 /* link */
2663                                 sinkpad = gst_element_get_static_pad(fakesink, "sink");
2664
2665                                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2666                                         LOGW("failed to link fakesink\n");
2667                                         gst_object_unref(GST_OBJECT(fakesink));
2668                                         goto ERROR;
2669                                 }
2670
2671                                 g_object_set(G_OBJECT(fakesink), "async", TRUE, NULL);
2672                                 g_object_set(G_OBJECT(fakesink), "sync", TRUE, NULL);
2673                                 gst_element_set_state(fakesink, GST_STATE_PAUSED);
2674
2675                                 goto DONE;
2676                         }
2677                 } else if (strstr(name, "text")) {
2678                         LOGD("text selector \n");
2679                         elemId = MMPLAYER_M_T_INPUT_SELECTOR;
2680                         stream_type = MM_PLAYER_TRACK_TYPE_TEXT;
2681                 } else {
2682                         LOGE("wrong elem id \n");
2683                         goto ERROR;
2684                 }
2685         }
2686
2687         selector = player->pipeline->mainbin[elemId].gst;
2688         if (selector == NULL) {
2689                 selector = gst_element_factory_make("input-selector", NULL);
2690                 LOGD("Creating input-selector\n");
2691                 if (selector == NULL) {
2692                         LOGE("ERROR : input-selector create error\n");
2693                         goto ERROR;
2694                 }
2695                 g_object_set(selector, "sync-streams", TRUE, NULL);
2696
2697                 player->pipeline->mainbin[elemId].id = elemId;
2698                 player->pipeline->mainbin[elemId].gst = selector;
2699
2700                 first_track = TRUE;
2701                 // player->selector[stream_type].active_pad_index = DEFAULT_TRACK;      // default
2702
2703                 srcpad = gst_element_get_static_pad(selector, "src");
2704
2705                 LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2706                 player->selector[stream_type].block_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
2707                         __mmplayer_gst_selector_blocked, NULL, NULL);
2708                 player->selector[stream_type].event_probe_id = gst_pad_add_probe(srcpad, GST_PAD_PROBE_TYPE_EVENT_BOTH|GST_PAD_PROBE_TYPE_EVENT_FLUSH,
2709                         __mmplayer_gst_selector_event_probe, player, NULL);
2710
2711                 gst_element_set_state(selector, GST_STATE_PAUSED);
2712                 gst_bin_add(GST_BIN(pipeline), selector);
2713         } else
2714                 LOGD("input-selector is already created.\n");
2715
2716         // link
2717         LOGD("Calling request pad with selector %p \n", selector);
2718         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2719
2720         LOGD("got pad %s:%s from selector", GST_DEBUG_PAD_NAME(sinkpad));
2721
2722         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
2723                 LOGW("failed to link selector\n");
2724                 gst_object_unref(GST_OBJECT(selector));
2725                 goto ERROR;
2726         }
2727
2728         if (first_track) {
2729                 LOGD("this is first track --> active track \n");
2730                 g_object_set(selector, "active-pad", sinkpad, NULL);
2731         }
2732
2733         _mmplayer_track_update_info(player, stream_type, sinkpad);
2734
2735
2736 DONE:
2737 ERROR:
2738
2739         if (caps)
2740                 gst_caps_unref(caps);
2741
2742         if (sinkpad) {
2743                 gst_object_unref(GST_OBJECT(sinkpad));
2744                 sinkpad = NULL;
2745         }
2746
2747         if (srcpad) {
2748                 gst_object_unref(GST_OBJECT(srcpad));
2749                 srcpad = NULL;
2750         }
2751
2752         return;
2753 }
2754
2755 static void __mmplayer_handle_text_decode_path(mm_player_t* player, GstElement* text_selector)
2756 {
2757         GstPad* srcpad = NULL;
2758         MMHandleType attrs = 0;
2759         gint active_index = 0;
2760
2761         // [link] input-selector :: textbin
2762         srcpad = gst_element_get_static_pad(text_selector, "src");
2763         if (!srcpad) {
2764                 LOGE("failed to get srcpad from selector\n");
2765                 return;
2766         }
2767
2768         LOGD("got pad %s:%s from text selector\n", GST_DEBUG_PAD_NAME(srcpad));
2769
2770         active_index = player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index;
2771         if ((active_index != DEFAULT_TRACK) &&
2772                 (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_TEXT, active_index) != MM_ERROR_NONE)) {
2773                 LOGW("failed to change text track\n");
2774                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].active_pad_index = DEFAULT_TRACK;
2775         }
2776
2777         player->no_more_pad = TRUE;
2778         __mmplayer_gst_decode_callback(text_selector, srcpad, player);
2779
2780         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
2781         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id) {
2782                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id);
2783                 player->selector[MM_PLAYER_TRACK_TYPE_TEXT].block_id = 0;
2784         }
2785
2786         LOGD("Total text tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2787
2788         if (player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num > 0)
2789                 player->has_closed_caption = TRUE;
2790
2791         attrs = MMPLAYER_GET_ATTRS(player);
2792         if (attrs) {
2793                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_TEXT].total_track_num);
2794                 if (mmf_attrs_commit(attrs))
2795                         LOGE("failed to commit.\n");
2796         } else
2797                 LOGE("cannot get content attribute");
2798
2799         if (srcpad) {
2800                 gst_object_unref(GST_OBJECT(srcpad));
2801                 srcpad = NULL;
2802         }
2803 }
2804
2805 static void
2806 __mmplayer_gst_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
2807 {
2808         mm_player_t* player = (mm_player_t*)data;
2809         GstElement* selector = NULL;
2810         GstElement* queue = NULL;
2811
2812         GstPad* srcpad = NULL;
2813         GstPad* sinkpad = NULL;
2814         GstCaps* caps = NULL;
2815         gchar* caps_str = NULL;
2816
2817         MMPLAYER_FENTER();
2818         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2819
2820         caps = gst_pad_get_current_caps(pad);
2821         caps_str = gst_caps_to_string(caps);
2822         LOGD("deinterleave new caps : %s\n", caps_str);
2823         MMPLAYER_FREEIF(caps_str);
2824         gst_caps_unref(caps);
2825
2826         if ((queue = __mmplayer_element_create_and_link(player, pad, "queue")) == NULL) {
2827                 LOGE("ERROR : queue create error\n");
2828                 goto ERROR;
2829         }
2830
2831         g_object_set(G_OBJECT(queue),
2832                                 "max-size-buffers", 10,
2833                                 "max-size-bytes", 0,
2834                                 "max-size-time", (guint64)0,
2835                                 NULL);
2836
2837         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
2838
2839         if (!selector) {
2840                 LOGE("there is no audio channel selector.\n");
2841                 goto ERROR;
2842         }
2843
2844         srcpad = gst_element_get_static_pad(queue, "src");
2845         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
2846
2847         LOGD("link(%s:%s - %s:%s)\n", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
2848
2849         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
2850                 LOGW("failed to link deinterleave - selector\n");
2851                 goto ERROR;
2852         }
2853
2854         gst_element_set_state(queue, GST_STATE_PAUSED);
2855         player->audio_mode.total_track_num++;
2856
2857 ERROR:
2858
2859         if (srcpad) {
2860                 gst_object_unref(GST_OBJECT(srcpad));
2861                 srcpad = NULL;
2862         }
2863
2864         if (sinkpad) {
2865                 gst_object_unref(GST_OBJECT(sinkpad));
2866                 sinkpad = NULL;
2867         }
2868
2869         MMPLAYER_FLEAVE();
2870         return;
2871 }
2872
2873 static void
2874 __mmplayer_gst_deinterleave_no_more_pads(GstElement *elem, gpointer data)
2875 {
2876         mm_player_t* player = NULL;
2877         GstElement* selector = NULL;
2878         GstPad* sinkpad = NULL;
2879         gint active_index = 0;
2880         gchar* change_pad_name = NULL;
2881         GstCaps* caps = NULL;   // no need to unref
2882         gint default_audio_ch = 0;
2883
2884         MMPLAYER_FENTER();
2885         player = (mm_player_t*) data;
2886
2887         selector = player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst;
2888
2889         if (!selector) {
2890                 LOGE("there is no audio channel selector.\n");
2891                 goto ERROR;
2892         }
2893
2894         active_index = player->audio_mode.active_pad_index;
2895
2896         if (active_index != default_audio_ch) {
2897                 gint audio_ch = default_audio_ch;
2898
2899                 /*To get the new pad from the selector*/
2900                 change_pad_name = g_strdup_printf("sink%d", active_index);
2901                 if (change_pad_name != NULL) {
2902                         sinkpad = gst_element_get_static_pad(selector, change_pad_name);
2903                         if (sinkpad != NULL) {
2904                                 LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
2905                                 g_object_set(selector, "active-pad", sinkpad, NULL);
2906
2907                                 audio_ch = active_index;
2908
2909                                 caps = gst_pad_get_current_caps(sinkpad);
2910                                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
2911
2912                                 __mmplayer_set_audio_attrs(player, caps);
2913                                 gst_caps_unref(caps);
2914                         }
2915                         MMPLAYER_FREEIF(change_pad_name);
2916                 }
2917
2918                 player->audio_mode.active_pad_index = audio_ch;
2919                 LOGD("audio LR info(0:stereo) = %d\n", player->audio_mode.active_pad_index);
2920         }
2921
2922 ERROR:
2923
2924         if (sinkpad)
2925                 gst_object_unref(sinkpad);
2926
2927         MMPLAYER_FLEAVE();
2928         return;
2929 }
2930
2931 static void
2932 __mmplayer_gst_build_deinterleave_path(GstElement *elem, GstPad *pad, gpointer data)
2933 {
2934         mm_player_t* player = NULL;
2935         MMPlayerGstElement *mainbin = NULL;
2936
2937         GstElement* tee = NULL;
2938         GstElement* stereo_queue = NULL;
2939         GstElement* mono_queue = NULL;
2940         GstElement* conv = NULL;
2941         GstElement* filter = NULL;
2942         GstElement* deinterleave = NULL;
2943         GstElement* selector = NULL;
2944
2945         GstPad* srcpad = NULL;
2946         GstPad* selector_srcpad = NULL;
2947         GstPad* sinkpad = NULL;
2948         GstCaps* caps = NULL;
2949         gulong block_id = 0;
2950
2951         MMPLAYER_FENTER();
2952
2953         /* check handles */
2954         player = (mm_player_t*) data;
2955
2956         MMPLAYER_RETURN_IF_FAIL(elem && pad);
2957         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
2958
2959         mainbin = player->pipeline->mainbin;
2960
2961         /* tee */
2962         if ((tee = __mmplayer_element_create_and_link(player, pad, "tee")) == NULL) {
2963                 LOGE("ERROR : tee create error\n");
2964                 goto ERROR;
2965         }
2966
2967         mainbin[MMPLAYER_M_A_TEE].id = MMPLAYER_M_A_TEE;
2968         mainbin[MMPLAYER_M_A_TEE].gst = tee;
2969
2970         gst_element_set_state(tee, GST_STATE_PAUSED);
2971
2972         /* queue */
2973         srcpad = gst_element_get_request_pad(tee, "src_%u");
2974         if ((stereo_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
2975                 LOGE("ERROR : stereo queue create error\n");
2976                 goto ERROR;
2977         }
2978
2979         g_object_set(G_OBJECT(stereo_queue),
2980                                 "max-size-buffers", 10,
2981                                 "max-size-bytes", 0,
2982                                 "max-size-time", (guint64)0,
2983                                 NULL);
2984
2985         player->pipeline->mainbin[MMPLAYER_M_A_Q1].id = MMPLAYER_M_A_Q1;
2986         player->pipeline->mainbin[MMPLAYER_M_A_Q1].gst = stereo_queue;
2987
2988         if (srcpad) {
2989                 gst_object_unref(GST_OBJECT(srcpad));
2990                 srcpad = NULL;
2991         }
2992
2993         srcpad = gst_element_get_request_pad(tee, "src_%u");
2994
2995         if ((mono_queue = __mmplayer_element_create_and_link(player, srcpad, "queue")) == NULL) {
2996                 LOGE("ERROR : mono queue create error\n");
2997                 goto ERROR;
2998         }
2999
3000         g_object_set(G_OBJECT(mono_queue),
3001                                 "max-size-buffers", 10,
3002                                 "max-size-bytes", 0,
3003                                 "max-size-time", (guint64)0,
3004                                 NULL);
3005
3006         player->pipeline->mainbin[MMPLAYER_M_A_Q2].id = MMPLAYER_M_A_Q2;
3007         player->pipeline->mainbin[MMPLAYER_M_A_Q2].gst = mono_queue;
3008
3009         gst_element_set_state(stereo_queue, GST_STATE_PAUSED);
3010         gst_element_set_state(mono_queue, GST_STATE_PAUSED);
3011
3012         /* audioconvert */
3013         srcpad = gst_element_get_static_pad(mono_queue, "src");
3014         if ((conv = __mmplayer_element_create_and_link(player, srcpad, "audioconvert")) == NULL) {
3015                 LOGE("ERROR : audioconvert create error\n");
3016                 goto ERROR;
3017         }
3018
3019         player->pipeline->mainbin[MMPLAYER_M_A_CONV].id = MMPLAYER_M_A_CONV;
3020         player->pipeline->mainbin[MMPLAYER_M_A_CONV].gst = conv;
3021
3022         /* caps filter */
3023         if (srcpad) {
3024                 gst_object_unref(GST_OBJECT(srcpad));
3025                 srcpad = NULL;
3026         }
3027         srcpad = gst_element_get_static_pad(conv, "src");
3028
3029         if ((filter = __mmplayer_element_create_and_link(player, srcpad, "capsfilter")) == NULL) {
3030                 LOGE("ERROR : capsfilter create error\n");
3031                 goto ERROR;
3032         }
3033
3034         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].id = MMPLAYER_M_A_FILTER;
3035         player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst = filter;
3036
3037         caps = gst_caps_from_string("audio/x-raw-int, "
3038                                 "width = (int) 16, "
3039                                 "depth = (int) 16, "
3040                                 "channels = (int) 2");
3041
3042         g_object_set(GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_A_FILTER].gst), "caps", caps, NULL);
3043         gst_caps_unref(caps);
3044
3045         gst_element_set_state(conv, GST_STATE_PAUSED);
3046         gst_element_set_state(filter, GST_STATE_PAUSED);
3047
3048         /* deinterleave */
3049         if (srcpad) {
3050                 gst_object_unref(GST_OBJECT(srcpad));
3051                 srcpad = NULL;
3052         }
3053         srcpad = gst_element_get_static_pad(filter, "src");
3054
3055         if ((deinterleave = __mmplayer_element_create_and_link(player, srcpad, "deinterleave")) == NULL) {
3056                 LOGE("ERROR : deinterleave create error\n");
3057                 goto ERROR;
3058         }
3059
3060         g_object_set(deinterleave, "keep-positions", TRUE, NULL);
3061
3062         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
3063                                                         G_CALLBACK(__mmplayer_gst_deinterleave_pad_added), player);
3064
3065         MMPLAYER_SIGNAL_CONNECT(player, deinterleave, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
3066                                                         G_CALLBACK(__mmplayer_gst_deinterleave_no_more_pads), player);
3067
3068         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].id = MMPLAYER_M_A_DEINTERLEAVE;
3069         player->pipeline->mainbin[MMPLAYER_M_A_DEINTERLEAVE].gst = deinterleave;
3070
3071         /* selector */
3072         selector = gst_element_factory_make("input-selector", "audio-channel-selector");
3073         if (selector == NULL) {
3074                 LOGE("ERROR : audio-selector create error\n");
3075                 goto ERROR;
3076         }
3077
3078         g_object_set(selector, "sync-streams", TRUE, NULL);
3079         gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), selector);
3080
3081         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].id = MMPLAYER_M_A_SELECTOR;
3082         player->pipeline->mainbin[MMPLAYER_M_A_SELECTOR].gst = selector;
3083
3084         selector_srcpad = gst_element_get_static_pad(selector, "src");
3085
3086         LOGD("blocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3087         block_id =
3088                 gst_pad_add_probe(selector_srcpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
3089                         __mmplayer_gst_selector_blocked, NULL, NULL);
3090
3091         if (srcpad) {
3092                 gst_object_unref(GST_OBJECT(srcpad));
3093                 srcpad = NULL;
3094         }
3095
3096         srcpad = gst_element_get_static_pad(stereo_queue, "src");
3097         sinkpad = gst_element_get_request_pad(selector, "sink_%u");
3098
3099         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
3100                 LOGW("failed to link queue_stereo - selector\n");
3101                 goto ERROR;
3102         }
3103
3104         player->audio_mode.total_track_num++;
3105
3106         g_object_set(selector, "active-pad", sinkpad, NULL);
3107         gst_element_set_state(deinterleave, GST_STATE_PAUSED);
3108         gst_element_set_state(selector, GST_STATE_PAUSED);
3109
3110         __mmplayer_gst_decode_callback(selector, selector_srcpad, player);
3111
3112 ERROR:
3113
3114         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(selector_srcpad));
3115         if (block_id != 0) {
3116                 gst_pad_remove_probe(selector_srcpad, block_id);
3117                 block_id = 0;
3118         }
3119
3120         if (sinkpad) {
3121                 gst_object_unref(GST_OBJECT(sinkpad));
3122                 sinkpad = NULL;
3123         }
3124
3125         if (srcpad) {
3126                 gst_object_unref(GST_OBJECT(srcpad));
3127                 srcpad = NULL;
3128         }
3129
3130         if (selector_srcpad) {
3131                 gst_object_unref(GST_OBJECT(selector_srcpad));
3132                 selector_srcpad = NULL;
3133         }
3134
3135         MMPLAYER_FLEAVE();
3136         return;
3137 }
3138
3139 static void
3140 __mmplayer_gst_decode_no_more_pads(GstElement *elem, gpointer data)
3141 {
3142         mm_player_t* player = NULL;
3143         GstPad* srcpad = NULL;
3144         GstElement* video_selector = NULL;
3145         GstElement* audio_selector = NULL;
3146         GstElement* text_selector = NULL;
3147         MMHandleType attrs = 0;
3148         gint active_index = 0;
3149         gint64 dur_bytes = 0L;
3150
3151         player = (mm_player_t*) data;
3152
3153         LOGD("no-more-pad signal handling\n");
3154
3155         if ((player->cmd == MMPLAYER_COMMAND_DESTROY) ||
3156                 (player->cmd == MMPLAYER_COMMAND_UNREALIZE)) {
3157                 LOGW("no need to go more");
3158
3159                 if (player->gapless.reconfigure) {
3160                         player->gapless.reconfigure = FALSE;
3161                         MMPLAYER_PLAYBACK_UNLOCK(player);
3162                 }
3163
3164                 return;
3165         }
3166
3167         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
3168                 (MMPLAYER_IS_HTTP_STREAMING(player)) &&
3169                 (!player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) &&
3170                 (player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst)) {
3171                 #define ESTIMATED_BUFFER_UNIT (1*1024*1024)
3172
3173                 if (NULL == player->streamer) {
3174                         LOGW("invalid state for buffering");
3175                         goto ERROR;
3176                 }
3177
3178                 gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
3179                 guint buffer_bytes = (guint)(init_buffering_time/1000) * ESTIMATED_BUFFER_UNIT;
3180
3181                 buffer_bytes = MAX(buffer_bytes, player->streamer->buffer_handle[BUFFER_TYPE_MUXED].buffering_bytes);
3182                 LOGD("[Decodebin2] set use-buffering on Q2(pre buffer time: %d ms, buffer size : %d)\n", init_buffering_time, buffer_bytes);
3183
3184                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
3185
3186                 if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
3187                         LOGE("fail to get duration.\n");
3188
3189                 // enable use-buffering on queue2 instead of multiqueue(ex)audio only streaming
3190                 // use file information was already set on Q2 when it was created.
3191                 __mm_player_streaming_set_queue2(player->streamer,
3192                                                 player->pipeline->mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst,
3193                                                 TRUE,                                                           // use_buffering
3194                                                 buffer_bytes,
3195                                                 init_buffering_time,
3196                                                 1.0,                                                            // low percent
3197                                                 player->ini.http_buffering_limit,       // high percent
3198                                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
3199                                                 NULL,
3200                                                 ((dur_bytes > 0) ? ((guint64)dur_bytes) : 0));
3201         }
3202
3203         video_selector = player->pipeline->mainbin[MMPLAYER_M_V_INPUT_SELECTOR].gst;
3204         audio_selector = player->pipeline->mainbin[MMPLAYER_M_A_INPUT_SELECTOR].gst;
3205         text_selector = player->pipeline->mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3206         if (video_selector) {
3207                 // [link] input-selector :: videobin
3208                 srcpad = gst_element_get_static_pad(video_selector, "src");
3209                 if (!srcpad) {
3210                         LOGE("failed to get srcpad from video selector\n");
3211                         goto ERROR;
3212                 }
3213
3214                 LOGD("got pad %s:%s from video selector\n", GST_DEBUG_PAD_NAME(srcpad));
3215                 if (!text_selector && !audio_selector)
3216                         player->no_more_pad = TRUE;
3217
3218                 __mmplayer_gst_decode_callback(video_selector, srcpad, player);
3219
3220                 LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3221                 if (player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id) {
3222                         gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id);
3223                         player->selector[MM_PLAYER_TRACK_TYPE_VIDEO].block_id = 0;
3224                 }
3225         }
3226
3227         if (audio_selector) {
3228                 active_index = player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index;
3229                 if ((active_index != DEFAULT_TRACK) &&
3230                         (__mmplayer_change_selector_pad(player, MM_PLAYER_TRACK_TYPE_AUDIO, active_index) != MM_ERROR_NONE)) {
3231                         LOGW("failed to change audio track\n");
3232                         player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].active_pad_index = DEFAULT_TRACK;
3233                 }
3234
3235                 // [link] input-selector :: audiobin
3236                 srcpad = gst_element_get_static_pad(audio_selector, "src");
3237                 if (!srcpad) {
3238                         LOGE("failed to get srcpad from selector\n");
3239                         goto ERROR;
3240                 }
3241
3242                 LOGD("got pad %s:%s from selector\n", GST_DEBUG_PAD_NAME(srcpad));
3243                 if (!text_selector)
3244                         player->no_more_pad = TRUE;
3245
3246                 if ((player->use_deinterleave == TRUE) && (player->max_audio_channels >= 2)) {
3247                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3248                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3249                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3250                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3251                         }
3252
3253                         __mmplayer_gst_build_deinterleave_path(audio_selector, srcpad, player);
3254                 } else {
3255                         __mmplayer_gst_decode_callback(audio_selector, srcpad, player);
3256
3257                         LOGD("unblocking %s:%s", GST_DEBUG_PAD_NAME(srcpad));
3258                         if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id) {
3259                                 gst_pad_remove_probe(srcpad, player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id);
3260                                 player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].block_id = 0;
3261                         }
3262                 }
3263
3264                 LOGD("Total audio tracks = %d \n", player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3265
3266                 attrs = MMPLAYER_GET_ATTRS(player);
3267                 if (attrs) {
3268                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", (gint)player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num);
3269                         if (mmf_attrs_commit(attrs))
3270                                 LOGE("failed to commit.\n");
3271                 } else
3272                         LOGE("cannot get content attribute");
3273         } else {
3274                 if ((player->pipeline->audiobin) && (player->pipeline->audiobin[MMPLAYER_A_BIN].gst)) {
3275                         LOGD("There is no audio track : remove audiobin");
3276
3277                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
3278                         __mmplayer_del_sink(player, player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
3279
3280                         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->audiobin, MMPLAYER_A_BIN);
3281                         MMPLAYER_FREEIF(player->pipeline->audiobin);
3282                 }
3283
3284                 if (player->num_dynamic_pad == 0)
3285                         __mmplayer_pipeline_complete(NULL, player);
3286         }
3287
3288         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
3289                 if (text_selector)
3290                         __mmplayer_handle_text_decode_path(player, text_selector);
3291         }
3292
3293         MMPLAYER_FLEAVE();
3294
3295 ERROR:
3296         if (srcpad) {
3297                 gst_object_unref(GST_OBJECT(srcpad));
3298                 srcpad = NULL;
3299         }
3300
3301         if (player->gapless.reconfigure) {
3302                 player->gapless.reconfigure = FALSE;
3303                 MMPLAYER_PLAYBACK_UNLOCK(player);
3304         }
3305 }
3306
3307 static void
3308 __mmplayer_gst_decode_callback(GstElement *elem, GstPad *pad, gpointer data)
3309 {
3310         mm_player_t* player = NULL;
3311         MMHandleType attrs = 0;
3312         GstElement* pipeline = NULL;
3313         GstCaps* caps = NULL;
3314         gchar* caps_str = NULL;
3315         GstStructure* str = NULL;
3316         const gchar* name = NULL;
3317         GstPad* sinkpad = NULL;
3318         GstElement* sinkbin = NULL;
3319         gboolean reusing = FALSE;
3320         GstElement *text_selector = NULL;
3321
3322         /* check handles */
3323         player = (mm_player_t*) data;
3324
3325         MMPLAYER_RETURN_IF_FAIL(elem && pad);
3326         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
3327
3328         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
3329
3330         attrs = MMPLAYER_GET_ATTRS(player);
3331         if (!attrs) {
3332                 LOGE("cannot get content attribute\n");
3333                 goto ERROR;
3334         }
3335
3336         /* get mimetype from caps */
3337         caps = gst_pad_query_caps(pad, NULL);
3338         if (!caps) {
3339                 LOGE("cannot get caps from pad.\n");
3340                 goto ERROR;
3341         }
3342         caps_str = gst_caps_to_string(caps);
3343
3344         str = gst_caps_get_structure(caps, 0);
3345         if (!str) {
3346                 LOGE("cannot get structure from caps.\n");
3347                 goto ERROR;
3348         }
3349
3350         name = gst_structure_get_name(str);
3351         if (!name) {
3352                 LOGE("cannot get mimetype from structure.\n");
3353                 goto ERROR;
3354         }
3355
3356         //LOGD("detected mimetype : %s\n", name);
3357
3358         if (strstr(name, "audio")) {
3359                 if (player->pipeline->audiobin == NULL) {
3360                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player)) {
3361                                 LOGE("failed to create audiobin. continuing without audio\n");
3362                                 goto ERROR;
3363                         }
3364
3365                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3366                         LOGD("creating audiosink bin success\n");
3367                 } else {
3368                         reusing = TRUE;
3369                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
3370                         LOGD("reusing audiobin\n");
3371                         _mmplayer_update_content_attrs(player, ATTR_AUDIO);
3372                 }
3373
3374                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) // should not update if content have multi audio tracks
3375                         mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
3376
3377                 player->audiosink_linked  = 1;
3378
3379                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3380                 if (!sinkpad) {
3381                         LOGE("failed to get pad from sinkbin\n");
3382                         goto ERROR;
3383                 }
3384         } else if (strstr(name, "video")) {
3385                 if (caps_str && (strstr(caps_str, "ST12") || strstr(caps_str, "SN12") ||
3386                         strstr(caps_str, "SN21") || strstr(caps_str, "S420") || strstr(caps_str, "SR32")))
3387                         player->set_mode.video_zc = TRUE;
3388
3389                 if (player->pipeline->videobin == NULL) {
3390                         /* NOTE : not make videobin because application dose not want to play it even though file has video stream. */
3391                         /* get video surface type */
3392                         int surface_type = 0;
3393                         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3394                         LOGD("display_surface_type(%d)\n", surface_type);
3395
3396                         if (surface_type == MM_DISPLAY_SURFACE_NULL) {
3397                                 LOGD("not make videobin because it dose not want\n");
3398                                 goto ERROR;
3399                         }
3400
3401                         if (surface_type == MM_DISPLAY_SURFACE_OVERLAY) {
3402                                 /* mark video overlay for acquire */
3403                                 if (player->video_overlay_resource == NULL) {
3404                                         if (mm_resource_manager_mark_for_acquire(player->resource_manager,
3405                                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
3406                                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
3407                                                         &player->video_overlay_resource)
3408                                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
3409                                                 LOGE("could not mark video_overlay resource for acquire\n");
3410                                                 goto ERROR;
3411                                         }
3412                                 }
3413                         }
3414
3415                         player->interrupted_by_resource = FALSE;
3416                         /* acquire resources for video overlay */
3417                         if (mm_resource_manager_commit(player->resource_manager) !=
3418                                         MM_RESOURCE_MANAGER_ERROR_NONE) {
3419                                 LOGE("could not acquire resources for video playing\n");
3420                                 goto ERROR;
3421                         }
3422
3423                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type)) {
3424                                 LOGE("failed to create videobin. continuing without video\n");
3425                                 goto ERROR;
3426                         }
3427
3428                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3429                         LOGD("creating videosink bin success\n");
3430                 } else {
3431                         reusing = TRUE;
3432                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
3433                         LOGD("re-using videobin\n");
3434                         _mmplayer_update_content_attrs(player, ATTR_VIDEO);
3435                 }
3436
3437                 player->videosink_linked  = 1;
3438
3439                 sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "sink");
3440                 if (!sinkpad) {
3441                         LOGE("failed to get pad from sinkbin\n");
3442                         goto ERROR;
3443                 }
3444         } else if (strstr(name, "text")) {
3445                 if (player->pipeline->textbin == NULL) {
3446                         MMPlayerGstElement* mainbin = NULL;
3447
3448                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_sink_bin(player)) {
3449                                 LOGE("failed to create text sink bin. continuing without text\n");
3450                                 goto ERROR;
3451                         }
3452
3453                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3454                         LOGD("creating textsink bin success\n");
3455
3456                         /* FIXIT : track number shouldn't be hardcoded */
3457                         mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
3458
3459                         player->textsink_linked  = 1;
3460                         LOGI("player->textsink_linked set to 1\n");
3461
3462                         sinkpad = gst_element_get_static_pad(GST_ELEMENT(sinkbin), "text_sink");
3463                         if (!sinkpad) {
3464                                 LOGE("failed to get pad from sinkbin\n");
3465                                 goto ERROR;
3466                         }
3467
3468                         mainbin = player->pipeline->mainbin;
3469
3470                         if (!mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst) {
3471                                 /* input selector */
3472                                 text_selector = gst_element_factory_make("input-selector", "subtitle_inselector");
3473                                 if (!text_selector) {
3474                                         LOGE("failed to create subtitle input selector element\n");
3475                                         goto ERROR;
3476                                 }
3477                                 g_object_set(text_selector, "sync-streams", TRUE, NULL);
3478
3479                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].id = MMPLAYER_M_T_INPUT_SELECTOR;
3480                                 mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst = text_selector;
3481
3482                                 /* warm up */
3483                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_READY)) {
3484                                         LOGE("failed to set state(READY) to sinkbin\n");
3485                                         goto ERROR;
3486                                 }
3487
3488                                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), text_selector)) {
3489                                         LOGW("failed to add subtitle input selector\n");
3490                                         goto ERROR;
3491                                 }
3492
3493                                 LOGD("created element input-selector");
3494
3495                         } else {
3496                                 LOGD("already having subtitle input selector");
3497                                 text_selector = mainbin[MMPLAYER_M_T_INPUT_SELECTOR].gst;
3498                         }
3499                 } else {
3500                         if (!player->textsink_linked) {
3501                                 LOGD("re-using textbin\n");
3502
3503                                 reusing = TRUE;
3504                                 sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
3505
3506                                 player->textsink_linked  = 1;
3507                                 LOGI("player->textsink_linked set to 1\n");
3508                         } else
3509                                 LOGD("ignoring internal subtutle since external subtitle is available");
3510                 }
3511         } else {
3512                 LOGW("unknown type of elementary stream!ignoring it...\n");
3513                 goto ERROR;
3514         }
3515
3516         if (sinkbin) {
3517                 if (!reusing) {
3518                         /* warm up */
3519                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_READY)) {
3520                                 LOGE("failed to set state(READY) to sinkbin\n");
3521                                 goto ERROR;
3522                         }
3523
3524                         /* Added for multi audio support to avoid adding audio bin again*/
3525                         /* add */
3526                         if (FALSE == gst_bin_add(GST_BIN(pipeline), sinkbin)) {
3527                                 LOGE("failed to add sinkbin to pipeline\n");
3528                                 goto ERROR;
3529                         }
3530                 }
3531
3532                 /* link */
3533                 if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
3534                         LOGE("failed to get pad from sinkbin\n");
3535                         goto ERROR;
3536                 }
3537
3538                 if (!reusing) {
3539                         /* run */
3540                         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkbin, GST_STATE_PAUSED)) {
3541                                 LOGE("failed to set state(PAUSED) to sinkbin\n");
3542                                 goto ERROR;
3543                         }
3544
3545                         if (text_selector) {
3546                                 if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(text_selector, GST_STATE_PAUSED)) {
3547                                         LOGE("failed to set state(PAUSED) to sinkbin\n");
3548                                         goto ERROR;
3549                                 }
3550                         }
3551                 }
3552
3553                 gst_object_unref(sinkpad);
3554                 sinkpad = NULL;
3555         }
3556
3557         LOGD("[handle: %p] linking sink bin success", player);
3558
3559         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
3560          * streaming task. if the task blocked, then buffer will not flow to the next element
3561          *(autoplugging element). so this is special hack for streaming. please try to remove it
3562          */
3563         /* dec stream count. we can remove fakesink if it's zero */
3564         if (player->num_dynamic_pad)
3565                 player->num_dynamic_pad--;
3566
3567         LOGD("no more pads: %d stream count dec : %d(num of dynamic pad)\n", player->no_more_pad, player->num_dynamic_pad);
3568
3569         if ((player->no_more_pad) && (player->num_dynamic_pad == 0))
3570                 __mmplayer_pipeline_complete(NULL, player);
3571
3572 ERROR:
3573
3574         MMPLAYER_FREEIF(caps_str);
3575
3576         if (caps)
3577                 gst_caps_unref(caps);
3578
3579         if (sinkpad)
3580                 gst_object_unref(GST_OBJECT(sinkpad));
3581
3582         /* flusing out new attributes */
3583         if (mmf_attrs_commit(attrs))
3584                 LOGE("failed to comit attributes\n");
3585
3586         return;
3587 }
3588
3589 static gboolean
3590 __mmplayer_get_property_value_for_rotation(mm_player_t* player, int rotation_angle, int *value)
3591 {
3592         int pro_value = 0; // in the case of expection, default will be returned.
3593         int dest_angle = rotation_angle;
3594         int rotation_type = -1;
3595
3596         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
3597         MMPLAYER_RETURN_VAL_IF_FAIL(value, FALSE);
3598         MMPLAYER_RETURN_VAL_IF_FAIL(rotation_angle >= 0, FALSE);
3599
3600         if (rotation_angle >= 360)
3601                 dest_angle = rotation_angle - 360;
3602
3603         /* chech if supported or not */
3604         if (dest_angle % 90) {
3605                 LOGD("not supported rotation angle = %d", rotation_angle);
3606                 return FALSE;
3607         }
3608
3609         /*
3610           * tizenwlsink (A)
3611           * custom_convert - none (B)
3612           * videoflip - none (C)
3613           */
3614         if (player->set_mode.video_zc) {
3615                 if (player->pipeline->videobin[MMPLAYER_V_CONV].gst) // B
3616                         rotation_type = ROTATION_USING_CUSTOM;
3617                 else // A
3618                         rotation_type = ROTATION_USING_SINK;
3619         } else {
3620                 int surface_type = 0;
3621                 rotation_type = ROTATION_USING_FLIP;
3622
3623                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
3624                 LOGD("check display surface type attribute: %d", surface_type);
3625
3626                 if (surface_type == MM_DISPLAY_SURFACE_OVERLAY)
3627                         rotation_type = ROTATION_USING_SINK;
3628                 else
3629                         rotation_type = ROTATION_USING_FLIP; //C
3630
3631                 LOGD("using %d type for rotation", rotation_type);
3632         }
3633
3634         /* get property value for setting */
3635         switch (rotation_type) {
3636         case ROTATION_USING_SINK: // tizenwlsink
3637                 {
3638                         switch (dest_angle) {
3639                         case 0:
3640                                 break;
3641                         case 90:
3642                                 pro_value = 3; // clockwise 90
3643                                 break;
3644                         case 180:
3645                                 pro_value = 2;
3646                                 break;
3647                         case 270:
3648                                 pro_value = 1; // counter-clockwise 90
3649                                 break;
3650                         }
3651                 }
3652                 break;
3653         case ROTATION_USING_CUSTOM:
3654                 {
3655                         gchar *ename = NULL;
3656                         ename = GST_OBJECT_NAME(gst_element_get_factory(player->pipeline->videobin[MMPLAYER_V_CONV].gst));
3657
3658                         if (g_strrstr(ename, "fimcconvert")) {
3659                                 switch (dest_angle) {
3660                                 case 0:
3661                                         break;
3662                                 case 90:
3663                                         pro_value = 90; // clockwise 90
3664                                         break;
3665                                 case 180:
3666                                         pro_value = 180;
3667                                         break;
3668                                 case 270:
3669                                         pro_value = 270; // counter-clockwise 90
3670                                         break;
3671                                 }
3672                         }
3673                 }
3674                 break;
3675         case ROTATION_USING_FLIP: // videoflip
3676                 {
3677                                 switch (dest_angle) {
3678                                 case 0:
3679                                         break;
3680                                 case 90:
3681                                         pro_value = 1; // clockwise 90
3682                                         break;
3683                                 case 180:
3684                                         pro_value = 2;
3685                                         break;
3686                                 case 270:
3687                                         pro_value = 3; // counter-clockwise 90
3688                                         break;
3689                                 }
3690                 }
3691                 break;
3692         }
3693
3694         LOGD("setting rotation property value : %d, used rotation type : %d", pro_value, rotation_type);
3695
3696         *value = pro_value;
3697
3698         return TRUE;
3699 }
3700
3701 int
3702 __mmplayer_video_param_check_video_sink_bin(mm_player_t* player)
3703 {
3704         /* check video sinkbin is created */
3705         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
3706                 player->pipeline &&
3707                 player->pipeline->videobin &&
3708                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
3709                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3710                 MM_ERROR_PLAYER_NOT_INITIALIZED);
3711
3712         return MM_ERROR_NONE;
3713 }
3714
3715 void
3716 __mmplayer_video_param_set_display_rotation(mm_player_t* player)
3717 {
3718         int rotation_value = 0;
3719         int org_angle = 0; // current supported angle values are 0, 90, 180, 270
3720         int user_angle = 0;
3721         MMPLAYER_FENTER();
3722
3723         /* check video sinkbin is created */
3724         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3725                 return;
3726
3727         __mmplayer_get_video_angle(player, &user_angle, &org_angle);
3728
3729         /* get rotation value to set */
3730         __mmplayer_get_property_value_for_rotation(player, org_angle+user_angle, &rotation_value);
3731         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotation_value, NULL);
3732         LOGD("set video param : rotate %d", rotation_value);
3733 }
3734
3735 void
3736 __mmplayer_video_param_set_display_visible(mm_player_t* player)
3737 {
3738         MMHandleType attrs = 0;
3739         int visible = 0;
3740         MMPLAYER_FENTER();
3741
3742         /* check video sinkbin is created */
3743         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3744                 return;
3745
3746         attrs = MMPLAYER_GET_ATTRS(player);
3747         MMPLAYER_RETURN_IF_FAIL(attrs);
3748
3749         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
3750         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "visible", visible, NULL);
3751         LOGD("set video param : visible %d", visible);
3752 }
3753
3754 void
3755 __mmplayer_video_param_set_display_method(mm_player_t* player)
3756 {
3757         MMHandleType attrs = 0;
3758         int display_method = 0;
3759         MMPLAYER_FENTER();
3760
3761         /* check video sinkbin is created */
3762         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3763                 return;
3764
3765         attrs = MMPLAYER_GET_ATTRS(player);
3766         MMPLAYER_RETURN_IF_FAIL(attrs);
3767
3768         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
3769         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "display-geometry-method", display_method, NULL);
3770         LOGD("set video param : method %d", display_method);
3771 }
3772
3773 void
3774 __mmplayer_video_param_set_render_rectangle(mm_player_t* player)
3775 {
3776         MMHandleType attrs = 0;
3777         void *handle = NULL;
3778         /*set wl_display*/
3779         int wl_window_x = 0;
3780         int wl_window_y = 0;
3781         int wl_window_width = 0;
3782         int wl_window_height = 0;
3783         MMPLAYER_FENTER();
3784
3785         /* check video sinkbin is created */
3786         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3787                 return;
3788
3789         attrs = MMPLAYER_GET_ATTRS(player);
3790         MMPLAYER_RETURN_IF_FAIL(attrs);
3791
3792         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
3793
3794         if (handle) {
3795                 /*It should be set after setting window*/
3796                 mm_attrs_get_int_by_name(attrs, "wl_window_render_x", &wl_window_x);
3797                 mm_attrs_get_int_by_name(attrs, "wl_window_render_y", &wl_window_y);
3798                 mm_attrs_get_int_by_name(attrs, "wl_window_render_width", &wl_window_width);
3799                 mm_attrs_get_int_by_name(attrs, "wl_window_render_height", &wl_window_height);
3800
3801                 /* After setting window handle, set render      rectangle */
3802                 gst_video_overlay_set_render_rectangle(
3803                          GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3804                          wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3805                 LOGD("set video param : render rectangle : x(%d) y(%d) width(%d) height(%d)",
3806                         wl_window_x, wl_window_y, wl_window_width, wl_window_height);
3807
3808         }
3809 }
3810 void
3811 __mmplayer_video_param_set_display_overlay(mm_player_t* player)
3812 {
3813         MMHandleType attrs = 0;
3814         void *handle = NULL;
3815
3816         /* check video sinkbin is created */
3817         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3818                 return;
3819
3820         attrs = MMPLAYER_GET_ATTRS(player);
3821         MMPLAYER_RETURN_IF_FAIL(attrs);
3822
3823         /* common case if using overlay surface */
3824         mm_attrs_get_data_by_name(attrs, "display_overlay", &handle);
3825
3826         if (handle) {
3827                 /* default is using wl_surface_id */
3828                 unsigned int wl_surface_id      = 0;
3829                 wl_surface_id = *(int*)handle;
3830                 LOGD("set video param : wl_surface_id %d %p", wl_surface_id, *(int*)handle);
3831                 gst_video_overlay_set_wl_window_wl_surface_id(
3832                                 GST_VIDEO_OVERLAY(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
3833                                 *(int*)handle);
3834         } else
3835                 /* FIXIT : is it error case? */
3836                 LOGW("still we don't have a window handle on player attribute. create it's own surface.");
3837 }
3838
3839
3840 int
3841 __mmplayer_update_wayland_videosink_video_param(mm_player_t* player, char *param_name)
3842 {
3843         bool update_all_param = FALSE;
3844         MMPLAYER_FENTER();
3845
3846         /* check video sinkbin is created */
3847         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3848                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3849
3850         if (strcmp(player->ini.videosink_element_overlay, "tizenwlsink")) {
3851                 LOGE("can not find tizenwlsink");
3852                 return MM_ERROR_PLAYER_INTERNAL;
3853         }
3854
3855         LOGD("param_name : %s", param_name);
3856         if (!g_strcmp0(param_name, "update_all_param"))
3857                 update_all_param = TRUE;
3858
3859         if (update_all_param || !g_strcmp0(param_name, "display_overlay"))
3860                 __mmplayer_video_param_set_display_overlay(player);
3861         if (update_all_param || !g_strcmp0(param_name, "display_method"))
3862                 __mmplayer_video_param_set_display_method(player);
3863         if (update_all_param || !g_strcmp0(param_name, "wl_window_render_x"))
3864                 __mmplayer_video_param_set_render_rectangle(player);
3865         if (update_all_param || !g_strcmp0(param_name, "display_visible"))
3866                 __mmplayer_video_param_set_display_visible(player);
3867         if (update_all_param || !g_strcmp0(param_name, "display_rotation"))
3868                 __mmplayer_video_param_set_display_rotation(player);
3869
3870         return MM_ERROR_NONE;
3871 }
3872
3873 int
3874 _mmplayer_update_video_param(mm_player_t* player, char *param_name)
3875 {
3876         MMHandleType attrs = 0;
3877         int surface_type = 0;
3878         int ret = MM_ERROR_NONE;
3879
3880         MMPLAYER_FENTER();
3881
3882         /* check video sinkbin is created */
3883         if (MM_ERROR_NONE != __mmplayer_video_param_check_video_sink_bin(player))
3884                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
3885
3886         attrs = MMPLAYER_GET_ATTRS(player);
3887         if (!attrs) {
3888                 LOGE("cannot get content attribute");
3889                 return MM_ERROR_PLAYER_INTERNAL;
3890         }
3891         LOGD("param_name : %s", param_name);
3892
3893         /* update display surface */
3894         mm_attrs_get_int_by_name(attrs, "display_surface_type", &surface_type);
3895         LOGD("check display surface type attribute: %d", surface_type);
3896
3897         /* configuring display */
3898         switch (surface_type) {
3899         case MM_DISPLAY_SURFACE_OVERLAY:
3900                 {
3901                         ret = __mmplayer_update_wayland_videosink_video_param(player, param_name);
3902                         if (ret != MM_ERROR_NONE)
3903                                 return ret;
3904                 }
3905                 break;
3906         }
3907
3908         MMPLAYER_FLEAVE();
3909
3910         return MM_ERROR_NONE;
3911 }
3912
3913 int
3914 _mmplayer_set_audio_only(MMHandleType hplayer, bool audio_only)
3915 {
3916         gboolean disable_overlay = FALSE;
3917         mm_player_t* player = (mm_player_t*) hplayer;
3918         int ret = MM_ERROR_NONE;
3919
3920         MMPLAYER_FENTER();
3921         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3922         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
3923                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
3924                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
3925
3926         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
3927                 LOGW("Display control is not supported");
3928                 return MM_ERROR_PLAYER_INTERNAL;
3929         }
3930
3931         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
3932
3933         if (audio_only == (bool)disable_overlay) {
3934                 LOGE("It's the same with current setting: (%d)", audio_only);
3935                 return MM_ERROR_NONE;
3936         }
3937
3938         if (audio_only) {
3939                 LOGE("disable overlay");
3940                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", TRUE, NULL);
3941
3942                 /* release overlay resource */
3943                 if (player->video_overlay_resource != NULL) {
3944                         ret = mm_resource_manager_mark_for_release(player->resource_manager,
3945                                         player->video_overlay_resource);
3946                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3947                                 LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
3948                                 goto ERROR;
3949                         }
3950                         player->video_overlay_resource = NULL;
3951                 }
3952
3953                 ret = mm_resource_manager_commit(player->resource_manager);
3954                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3955                         LOGE("failed to commit acquiring of overlay resource, ret(0x%x)\n", ret);
3956                         goto ERROR;
3957                 }
3958         } else {
3959                 /* mark video overlay for acquire */
3960                 if (player->video_overlay_resource == NULL) {
3961                         ret = mm_resource_manager_mark_for_acquire(player->resource_manager,
3962                                         MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_OVERLAY,
3963                                         MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
3964                                         &player->video_overlay_resource);
3965                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3966                                 LOGE("could not prepare for video_overlay resource\n");
3967                                 goto ERROR;
3968                         }
3969                 }
3970
3971                 player->interrupted_by_resource = FALSE;
3972                 /* acquire resources for video overlay */
3973                 ret = mm_resource_manager_commit(player->resource_manager);
3974                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
3975                         LOGE("could not acquire resources for video playing\n");
3976                         goto ERROR;
3977                 }
3978
3979                 LOGD("enable overlay");
3980                 __mmplayer_video_param_set_display_overlay(player);
3981                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", FALSE, NULL);
3982         }
3983
3984 ERROR:
3985         MMPLAYER_FLEAVE();
3986         return MM_ERROR_NONE;
3987 }
3988
3989 int
3990 _mmplayer_get_audio_only(MMHandleType hplayer, bool *paudio_only)
3991 {
3992         mm_player_t* player = (mm_player_t*) hplayer;
3993         gboolean disable_overlay = FALSE;
3994
3995         MMPLAYER_FENTER();
3996
3997         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3998         MMPLAYER_RETURN_VAL_IF_FAIL(paudio_only, MM_ERROR_INVALID_ARGUMENT);
3999         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->videobin &&
4000                                                                 player->pipeline->videobin[MMPLAYER_V_SINK].gst,
4001                                                                 MM_ERROR_PLAYER_NO_OP); /* invalid op */
4002
4003         if (!g_object_class_find_property(G_OBJECT_GET_CLASS(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "disable-overlay")) {
4004                 LOGW("Display control is not supported");
4005                 return MM_ERROR_PLAYER_INTERNAL;
4006         }
4007
4008         g_object_get(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "disable-overlay", &disable_overlay, NULL);
4009
4010         *paudio_only = (bool)(disable_overlay);
4011
4012         LOGD("audio_only : %d", *paudio_only);
4013
4014         MMPLAYER_FLEAVE();
4015
4016         return MM_ERROR_NONE;
4017 }
4018
4019 static int
4020 __mmplayer_gst_element_link_bucket(GList* element_bucket)
4021 {
4022         GList* bucket = element_bucket;
4023         MMPlayerGstElement* element = NULL;
4024         MMPlayerGstElement* prv_element = NULL;
4025         gint successful_link_count = 0;
4026
4027         MMPLAYER_FENTER();
4028
4029         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, -1);
4030
4031         prv_element = (MMPlayerGstElement*)bucket->data;
4032         bucket = bucket->next;
4033
4034         for (; bucket; bucket = bucket->next) {
4035                 element = (MMPlayerGstElement*)bucket->data;
4036
4037                 if (element && element->gst) {
4038                         /* If next element is audio appsrc then make a separate audio pipeline */
4039                         if (!strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "audio_appsrc") ||
4040                                 !strcmp(GST_ELEMENT_NAME(GST_ELEMENT(element->gst)), "subtitle_appsrc")) {
4041                                 prv_element = element;
4042                                 continue;
4043                         }
4044
4045                         if (prv_element && prv_element->gst) {
4046                                 if (gst_element_link(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst))) {
4047                                         LOGD("linking [%s] to [%s] success\n",
4048                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4049                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4050                                         successful_link_count++;
4051                                 } else {
4052                                         LOGD("linking [%s] to [%s] failed\n",
4053                                                 GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
4054                                                 GST_ELEMENT_NAME(GST_ELEMENT(element->gst)));
4055                                         return -1;
4056                                 }
4057                         }
4058                 }
4059
4060                 prv_element = element;
4061         }
4062
4063         MMPLAYER_FLEAVE();
4064
4065         return successful_link_count;
4066 }
4067
4068 static int
4069 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket)
4070 {
4071         GList* bucket = element_bucket;
4072         MMPlayerGstElement* element = NULL;
4073         int successful_add_count = 0;
4074
4075         MMPLAYER_FENTER();
4076
4077         MMPLAYER_RETURN_VAL_IF_FAIL(element_bucket, 0);
4078         MMPLAYER_RETURN_VAL_IF_FAIL(bin, 0);
4079
4080         for (; bucket; bucket = bucket->next) {
4081                 element = (MMPlayerGstElement*)bucket->data;
4082
4083                 if (element && element->gst) {
4084                         if (!gst_bin_add(bin, GST_ELEMENT(element->gst))) {
4085                                 LOGD("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
4086                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
4087                                         GST_ELEMENT_NAME(GST_ELEMENT(bin)));
4088                                 return 0;
4089                         }
4090                         successful_add_count++;
4091                 }
4092         }
4093
4094         MMPLAYER_FLEAVE();
4095
4096         return successful_add_count;
4097 }
4098
4099 static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data)
4100 {
4101         mm_player_t* player = (mm_player_t*) data;
4102         GstCaps *caps = NULL;
4103         GstStructure *str = NULL;
4104         const char *name;
4105
4106         MMPLAYER_FENTER();
4107
4108         MMPLAYER_RETURN_IF_FAIL(pad)
4109         MMPLAYER_RETURN_IF_FAIL(unused)
4110         MMPLAYER_RETURN_IF_FAIL(data)
4111
4112         caps = gst_pad_get_current_caps(pad);
4113         if (!caps)
4114                 return;
4115
4116         str = gst_caps_get_structure(caps, 0);
4117         if (!str)
4118                 goto ERROR;
4119
4120         name = gst_structure_get_name(str);
4121         if (!name)
4122                 goto ERROR;
4123
4124         LOGD("name = %s\n", name);
4125
4126         if (strstr(name, "audio")) {
4127                 _mmplayer_update_content_attrs(player, ATTR_AUDIO);
4128
4129                 if (player->audio_stream_changed_cb) {
4130                         LOGE("call the audio stream changed cb\n");
4131                         player->audio_stream_changed_cb(player->audio_stream_changed_cb_user_param);
4132                 }
4133         } else if (strstr(name, "video")) {
4134                 if ((name = gst_structure_get_string(str, "format")))
4135                         player->set_mode.video_zc = name[0] == 'S';
4136
4137                 _mmplayer_update_content_attrs(player, ATTR_VIDEO);
4138
4139                 if (player->video_stream_changed_cb) {
4140                         LOGE("call the video stream changed cb\n");
4141                         player->video_stream_changed_cb(player->video_stream_changed_cb_user_param);
4142                 }
4143         } else
4144                 goto ERROR;
4145
4146 ERROR:
4147
4148         gst_caps_unref(caps);
4149
4150         MMPLAYER_FLEAVE();
4151
4152         return;
4153 }
4154
4155
4156
4157 /**
4158  * This function is to create audio pipeline for playing.
4159  *
4160  * @param       player          [in]    handle of player
4161  *
4162  * @return      This function returns zero on success.
4163  * @remark
4164  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
4165  */
4166 /* macro for code readability. just for sinkbin-creation functions */
4167 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket, x_player) \
4168 do {\
4169         x_bin[x_id].id = x_id;\
4170         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
4171         if (!x_bin[x_id].gst) {\
4172                 LOGE("failed to create %s \n", x_factory);\
4173                 goto ERROR;\
4174         } else {\
4175                 if (x_player->ini.set_dump_element_flag)\
4176                         __mmplayer_add_dump_buffer_probe(x_player, x_bin[x_id].gst);\
4177         } \
4178         if (x_add_bucket)\
4179                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
4180 } while (0);
4181
4182 static void
4183 __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all)
4184 {
4185         GList *l = NULL;
4186
4187         MMPLAYER_FENTER();
4188         MMPLAYER_RETURN_IF_FAIL(player);
4189
4190         if (player->audio_stream_buff_list) {
4191                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4192                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4193                         if (tmp) {
4194                                 if (send_all) {
4195                                         LOGD("[%lld] send remained data.", tmp->channel_mask);
4196                                         __mmplayer_audio_stream_send_data(player, tmp);
4197                                 }
4198                                 if (tmp->pcm_data)
4199                                         g_free(tmp->pcm_data);
4200                                 g_free(tmp);
4201                         }
4202                 }
4203                 g_list_free(player->audio_stream_buff_list);
4204                 player->audio_stream_buff_list = NULL;
4205         }
4206
4207         MMPLAYER_FLEAVE();
4208 }
4209
4210 static void
4211 __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer)
4212 {
4213         MMPlayerAudioStreamDataType audio_stream = { 0, };
4214
4215         MMPLAYER_FENTER();
4216         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4217
4218         audio_stream.bitrate = a_buffer->bitrate;
4219         audio_stream.channel = a_buffer->channel;
4220         audio_stream.depth = a_buffer->depth;
4221         audio_stream.is_little_endian = a_buffer->is_little_endian;
4222         audio_stream.channel_mask = a_buffer->channel_mask;
4223         audio_stream.data_size = a_buffer->data_size;
4224         audio_stream.data = a_buffer->pcm_data;
4225
4226         /* LOGD("[%lld] send data size:%d, %p", audio_stream.channel_mask, audio_stream.data_size, player->audio_stream_cb_user_param); */
4227         player->audio_stream_render_cb_ex(&audio_stream, player->audio_stream_cb_user_param);
4228
4229         MMPLAYER_FLEAVE();
4230 }
4231
4232 static void
4233 __mmplayer_audio_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4234 {
4235         mm_player_t* player = (mm_player_t*) data;
4236
4237         gint channel = 0;
4238         gint rate = 0;
4239         gint depth = 0;
4240         gint endianness = 0;
4241         guint64 channel_mask = 0;
4242         void *a_data = NULL;
4243         gint a_size = 0;
4244         mm_player_audio_stream_buff_t *a_buffer = NULL;
4245         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
4246         GList *l = NULL;
4247
4248         MMPLAYER_FENTER();
4249         MMPLAYER_RETURN_IF_FAIL(player && player->audio_stream_render_cb_ex);
4250
4251         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
4252         a_data = mapinfo.data;
4253         a_size = mapinfo.size;
4254
4255         GstCaps *caps = gst_pad_get_current_caps(pad);
4256         GstStructure *structure = gst_caps_get_structure(caps, 0);
4257
4258         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
4259         gst_structure_get_int(structure, "rate", &rate);
4260         gst_structure_get_int(structure, "channels", &channel);
4261         gst_structure_get_int(structure, "depth", &depth);
4262         gst_structure_get_int(structure, "endianness", &endianness);
4263         gst_structure_get(structure, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL);
4264         gst_caps_unref(GST_CAPS(caps));
4265
4266         /* In case of the sync is false, use buffer list.              *
4267          * The num of buffer list depends on the num of audio channels */
4268         if (player->audio_stream_buff_list) {
4269                 for (l = g_list_first(player->audio_stream_buff_list); l; l = g_list_next(l)) {
4270                         mm_player_audio_stream_buff_t *tmp = (mm_player_audio_stream_buff_t *)l->data;
4271                         if (tmp) {
4272                                 if (channel_mask == tmp->channel_mask) {
4273                                         /* LOGD("[%lld] total: %d, data: %d, buffer: %d", channel_mask, tmp->data_size, a_size, tmp->buff_size); */
4274                                         if (tmp->data_size + a_size < tmp->buff_size) {
4275                                                 memcpy(tmp->pcm_data + tmp->data_size, a_data, a_size);
4276                                                 tmp->data_size += a_size;
4277                                         } else {
4278                                                 /* send data to client */
4279                                                 __mmplayer_audio_stream_send_data(player, tmp);
4280
4281                                                 if (a_size > tmp->buff_size) {
4282                                                         LOGD("[%lld] adj buffer size %d -> %d", channel_mask, tmp->buff_size, a_size);
4283                                                         tmp->pcm_data = g_realloc(tmp->pcm_data, a_size);
4284                                                         if (tmp->pcm_data == NULL) {
4285                                                                 LOGE("failed to realloc data.");
4286                                                                 goto DONE;
4287                                                         }
4288                                                         tmp->buff_size = a_size;
4289                                                 }
4290                                                 memset(tmp->pcm_data, 0x00, tmp->buff_size);
4291                                                 memcpy(tmp->pcm_data, a_data, a_size);
4292                                                 tmp->data_size = a_size;
4293                                         }
4294                                         goto DONE;
4295                                 }
4296                         } else {
4297                                 LOGE("data is empty in list.");
4298                                 goto DONE;
4299                         }
4300                 }
4301         }
4302
4303         /* create new audio stream data */
4304         a_buffer = (mm_player_audio_stream_buff_t*)g_malloc0(sizeof(mm_player_audio_stream_buff_t));
4305         if (a_buffer == NULL) {
4306                 LOGE("failed to alloc data.");
4307                 goto DONE;
4308         }
4309         a_buffer->bitrate = rate;
4310         a_buffer->channel = channel;
4311         a_buffer->depth = depth;
4312         a_buffer->is_little_endian = (endianness == 1234 ? 1 : 0);
4313         a_buffer->channel_mask = channel_mask;
4314         a_buffer->data_size = a_size;
4315
4316         if (!player->audio_stream_sink_sync) {
4317                 /* If sync is FALSE, use buffer list to reduce the IPC. */
4318                 a_buffer->buff_size = (a_size > player->ini.pcm_buffer_size) ? (a_size) : (player->ini.pcm_buffer_size);
4319                 a_buffer->pcm_data = g_malloc(a_buffer->buff_size);
4320                 if (a_buffer->pcm_data == NULL) {
4321                         LOGE("failed to alloc data.");
4322                         g_free(a_buffer);
4323                         goto DONE;
4324                 }
4325                 memcpy(a_buffer->pcm_data, a_data, a_size);
4326                 /* LOGD("new [%lld] total:%d buff:%d", channel_mask, a_buffer->data_size, a_buffer->buff_size); */
4327                 player->audio_stream_buff_list = g_list_append(player->audio_stream_buff_list, a_buffer);
4328         } else {
4329                 /* If sync is TRUE, send data directly. */
4330                 a_buffer->pcm_data = a_data;
4331                 __mmplayer_audio_stream_send_data(player, a_buffer);
4332                 g_free(a_buffer);
4333         }
4334
4335 DONE:
4336         gst_buffer_unmap(buffer, &mapinfo);
4337         MMPLAYER_FLEAVE();
4338 }
4339
4340 static void
4341 __mmplayer_gst_audio_deinterleave_pad_added(GstElement *elem, GstPad *pad, gpointer data)
4342 {
4343         mm_player_t* player = (mm_player_t*)data;
4344         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4345         GstPad* sinkpad = NULL;
4346         GstElement *queue = NULL, *sink = NULL;
4347
4348         MMPLAYER_FENTER();
4349         MMPLAYER_RETURN_IF_FAIL(player && player->pipeline && player->pipeline->mainbin);
4350
4351         queue = gst_element_factory_make("queue", NULL);
4352         if (queue == NULL) {
4353                 LOGD("fail make queue\n");
4354                 goto ERROR;
4355         }
4356
4357         sink = gst_element_factory_make("fakesink", NULL);
4358         if (sink == NULL) {
4359                 LOGD("fail make fakesink\n");
4360                 goto ERROR;
4361         }
4362
4363         gst_bin_add_many(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), queue, sink, NULL);
4364
4365         if (!gst_element_link_pads_full(queue, "src", sink, "sink", GST_PAD_LINK_CHECK_NOTHING)) {
4366                 LOGW("failed to link queue & sink\n");
4367                 goto ERROR;
4368         }
4369
4370         sinkpad = gst_element_get_static_pad(queue, "sink");
4371
4372         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
4373                 LOGW("failed to link [%s:%s] to queue\n", GST_DEBUG_PAD_NAME(pad));
4374                 goto ERROR;
4375         }
4376
4377         LOGE("player->audio_stream_sink_sync: %d\n", player->audio_stream_sink_sync);
4378
4379         gst_object_unref(sinkpad);
4380         g_object_set(sink, "sync", player->audio_stream_sink_sync, NULL);
4381         g_object_set(sink, "signal-handoffs", TRUE, NULL);
4382
4383         gst_element_set_state(sink, GST_STATE_PAUSED);
4384         gst_element_set_state(queue, GST_STATE_PAUSED);
4385
4386         MMPLAYER_SIGNAL_CONNECT(player,
4387                 G_OBJECT(sink),
4388                 MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4389                 "handoff",
4390                 G_CALLBACK(__mmplayer_audio_stream_decoded_render_cb),
4391                 (gpointer)player);
4392
4393         MMPLAYER_FLEAVE();
4394         return;
4395
4396 ERROR:
4397         LOGE("__mmplayer_gst_audio_deinterleave_pad_added ERROR\n");
4398         if (queue) {
4399                 gst_object_unref(GST_OBJECT(queue));
4400                 queue = NULL;
4401         }
4402         if (sink) {
4403                 gst_object_unref(GST_OBJECT(sink));
4404                 sink = NULL;
4405         }
4406         if (sinkpad) {
4407                 gst_object_unref(GST_OBJECT(sinkpad));
4408                 sinkpad = NULL;
4409         }
4410
4411         return;
4412 }
4413
4414 void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType attrs)
4415 {
4416         #define MAX_PROPS_LEN 128
4417         gint latency_mode = 0;
4418         gchar *stream_type = NULL;
4419         gchar *latency = NULL;
4420         gint stream_id = 0;
4421         gchar stream_props[MAX_PROPS_LEN] = {0,};
4422         GstStructure *props = NULL;
4423
4424         /* set volume table
4425          * It should be set after player creation through attribute.
4426          * But, it can not be changed during playing.
4427          */
4428         MMPLAYER_FENTER();
4429         mm_attrs_get_int_by_name(attrs, "sound_stream_index", &stream_id);
4430         mm_attrs_get_string_by_name(attrs, "sound_stream_type", &stream_type);
4431
4432         if (!stream_type) {
4433                 LOGE("stream_type is null.\n");
4434         } else {
4435                 if (player->sound.focus_id)
4436                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d, media.focus_id=%d",
4437                                         stream_type, stream_id, player->sound.focus_id);
4438                 else
4439                         snprintf(stream_props, sizeof(stream_props)-1, "props,media.role=%s, media.parent_id=%d",
4440                                         stream_type, stream_id);
4441                 props = gst_structure_from_string(stream_props, NULL);
4442                 g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "stream-properties", props, NULL);
4443                 LOGI("stream_type[%s], stream_id[%d], focus_id[%d], result[%s].\n",
4444                         stream_type, stream_id, player->sound.focus_id, stream_props);
4445                 gst_structure_free(props);
4446         }
4447
4448         mm_attrs_get_int_by_name(attrs, "sound_latency_mode", &latency_mode);
4449
4450         switch (latency_mode) {
4451         case AUDIO_LATENCY_MODE_LOW:
4452                 latency = g_strndup("low", 3);
4453                 break;
4454         case AUDIO_LATENCY_MODE_MID:
4455                 latency = g_strndup("mid", 3);
4456                 break;
4457         case AUDIO_LATENCY_MODE_HIGH:
4458                 latency = g_strndup("high", 4);
4459                 break;
4460         };
4461
4462         g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
4463                         "latency", latency,
4464                         NULL);
4465
4466         LOGD("audiosink property - latency=%s \n", latency);
4467
4468         g_free(latency);
4469
4470         MMPLAYER_FLEAVE();
4471 }
4472
4473 static int
4474 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
4475 {
4476         MMPlayerGstElement* first_element = NULL;
4477         MMPlayerGstElement* audiobin = NULL;
4478         MMHandleType attrs = 0;
4479         GstPad *pad = NULL;
4480         GstPad *ghostpad = NULL;
4481         GList* element_bucket = NULL;
4482         gboolean link_audio_sink_now = TRUE;
4483         int i = 0;
4484         GstCaps *acaps;
4485
4486         MMPLAYER_FENTER();
4487
4488         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4489
4490         /* alloc handles */
4491         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
4492         if (!audiobin) {
4493                 LOGE("failed to allocate memory for audiobin\n");
4494                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
4495         }
4496
4497         attrs = MMPLAYER_GET_ATTRS(player);
4498
4499         /* create bin */
4500         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
4501         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
4502         if (!audiobin[MMPLAYER_A_BIN].gst) {
4503                 LOGE("failed to create audiobin\n");
4504                 goto ERROR;
4505         }
4506
4507         /* take it */
4508         player->pipeline->audiobin = audiobin;
4509
4510         player->set_mode.pcm_extraction = __mmplayer_can_extract_pcm(player);
4511
4512         /* Adding audiotp plugin for reverse trickplay feature */
4513 //      MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audio trickplay", TRUE, player);
4514
4515         /* converter */
4516         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audio converter", TRUE, player);
4517
4518         /* replaygain volume */
4519         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RGVOL, "rgvolume", "audio rgvolume", TRUE, player);
4520         if (player->sound.rg_enable)
4521                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", TRUE, NULL);
4522         else
4523                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_RGVOL].gst), "enable-rgvolume", FALSE, NULL);
4524
4525         /* resampler */
4526         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER,  player->ini.audioresampler_element, "audio resampler", TRUE, player);
4527
4528         if (player->set_mode.pcm_extraction) {
4529                 // pcm extraction only and no sound output
4530                 if (player->audio_stream_render_cb_ex) {
4531                         char *caps_str = NULL;
4532                         GstCaps* caps = NULL;
4533                         gchar *format = NULL;
4534
4535                         /* capsfilter */
4536                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4537
4538                         mm_attrs_get_string_by_name(player->attrs, "pcm_audioformat", &format);
4539
4540                         LOGD("contents : format: %s samplerate : %d pcm_channel: %d", format, player->pcm_samplerate, player->pcm_channel);
4541
4542                         caps = gst_caps_new_simple("audio/x-raw",
4543                                         "format", G_TYPE_STRING, format,
4544                                         "rate", G_TYPE_INT, player->pcm_samplerate,
4545                                         "channels", G_TYPE_INT, player->pcm_channel,
4546                                         NULL);
4547                         caps_str = gst_caps_to_string(caps);
4548                         LOGD("new caps : %s\n", caps_str);
4549
4550                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4551
4552                         /* clean */
4553                         gst_caps_unref(caps);
4554                         MMPLAYER_FREEIF(caps_str);
4555
4556                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_DEINTERLEAVE, "deinterleave", "deinterleave", TRUE, player);
4557
4558                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_DEINTERLEAVE].gst), "keep-positions", TRUE, NULL);
4559                         /* raw pad handling signal */
4560                         MMPLAYER_SIGNAL_CONNECT(player,
4561                                 (audiobin[MMPLAYER_A_DEINTERLEAVE].gst),
4562                                 MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
4563                                                                                                 G_CALLBACK(__mmplayer_gst_audio_deinterleave_pad_added), player);
4564                 } else {
4565                         int dst_samplerate = 0;
4566                         int dst_channels = 0;
4567                         int dst_depth = 0;
4568                         char *caps_str = NULL;
4569                         GstCaps* caps = NULL;
4570
4571                         /* get conf. values */
4572                         mm_attrs_multiple_get(player->attrs,
4573                                                 NULL,
4574                                                 "pcm_extraction_samplerate", &dst_samplerate,
4575                                                 "pcm_extraction_channels", &dst_channels,
4576                                                 "pcm_extraction_depth", &dst_depth,
4577                                                 NULL);
4578
4579                         /* capsfilter */
4580                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audio capsfilter", TRUE, player);
4581                         caps = gst_caps_new_simple("audio/x-raw",
4582                                         "rate", G_TYPE_INT, dst_samplerate,
4583                                         "channels", G_TYPE_INT, dst_channels,
4584                                         "depth", G_TYPE_INT, dst_depth,
4585                                         NULL);
4586                         caps_str = gst_caps_to_string(caps);
4587                         LOGD("new caps : %s\n", caps_str);
4588
4589                         g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4590
4591                         /* clean */
4592                         gst_caps_unref(caps);
4593                         MMPLAYER_FREEIF(caps_str);
4594
4595                         /* fake sink */
4596                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE, player);
4597
4598                         /* set sync */
4599                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
4600                 }
4601         } else {
4602                 // normal playback
4603                 //GstCaps* caps = NULL;
4604                 gint channels = 0;
4605
4606                 /* for logical volume control */
4607                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE, player);
4608                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
4609
4610                 if (player->sound.mute) {
4611                         LOGD("mute enabled\n");
4612                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
4613                 }
4614
4615 #if 0
4616                 /*capsfilter */
4617                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE, player);
4618                 caps = gst_caps_from_string("audio/x-raw-int, "
4619                                         "endianness = (int) LITTLE_ENDIAN, "
4620                                         "signed = (boolean) true, "
4621                                         "width = (int) 16, "
4622                                         "depth = (int) 16");
4623                 g_object_set(GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL);
4624                 gst_caps_unref(caps);
4625 #endif
4626
4627                 /* check if multi-channels */
4628                 if (player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) {
4629                         GstPad *srcpad = NULL;
4630                         GstCaps *caps = NULL;
4631
4632                         if ((srcpad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst, "src"))) {
4633                                 if ((caps = gst_pad_query_caps(srcpad, NULL))) {
4634                                         //MMPLAYER_LOG_GST_CAPS_TYPE(caps);
4635                                         GstStructure *str = gst_caps_get_structure(caps, 0);
4636                                         if (str)
4637                                                 gst_structure_get_int(str, "channels", &channels);
4638                                         gst_caps_unref(caps);
4639                                 }
4640                                 gst_object_unref(srcpad);
4641                         }
4642                 }
4643
4644                 /* audio effect element. if audio effect is enabled */
4645                 if ((strcmp(player->ini.audioeffect_element, ""))
4646                         && (channels <= 2)
4647                         && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4648                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, player->ini.audioeffect_element, "audio effect filter", TRUE, player);
4649
4650                         LOGD("audio effect config. bypass = %d, effect type  = %d", player->bypass_audio_effect, player->audio_effect_info.effect_type);
4651
4652                         if ((!player->bypass_audio_effect)
4653                                 && (player->ini.use_audio_effect_preset || player->ini.use_audio_effect_custom)) {
4654                                 if (MM_AUDIO_EFFECT_TYPE_CUSTOM == player->audio_effect_info.effect_type) {
4655                                         if (!_mmplayer_audio_effect_custom_apply(player))
4656                                                 LOGI("apply audio effect(custom) setting success\n");
4657                                 }
4658                         }
4659
4660                         if ((strcmp(player->ini.audioeffect_element_custom, ""))
4661                                 && (player->set_mode.rich_audio))
4662                                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER_SEC, player->ini.audioeffect_element_custom, "audio effect filter custom", TRUE, player);
4663                 }
4664
4665                 /* create audio sink */
4666                 LOGD("360 spherical %d, channels %d, ambisonic type %d, format %d, order %d",
4667                                 player->is_content_spherical, channels, player->video360_metadata.ambisonic_type,
4668                                 player->video360_metadata.ambisonic_format, player->video360_metadata.ambisonic_order);
4669
4670                 /* Note: qtdemux converts audio metadata defaults to openalsink defaults. */
4671                 if (player->is_360_feature_enabled &&
4672                         player->is_content_spherical &&
4673                         channels == 4 &&
4674                         player->video360_metadata.ambisonic_type == MMFILE_AMBISONIC_TYPE_PERIPHONIC &&
4675                         player->video360_metadata.ambisonic_format == MMFILE_AMBISONIC_FORMAT_AMB &&
4676                         player->video360_metadata.ambisonic_order == MMFILE_AMBISONIC_ORDER_FOA) {
4677
4678                         strncpy(player->ini.audiosink_element, "openalsink", PLAYER_INI_MAX_STRLEN - 1);
4679
4680                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV_BFORMAT, "audioconvert", "audio-converter-bformat", link_audio_sink_now, player);
4681
4682                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_360, "capsfilter", "audio-caps-filter", link_audio_sink_now, player);
4683                         acaps = gst_caps_from_string(SPATIAL_AUDIO_CAPS);
4684                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_CAPS_360].gst), "caps", acaps, NULL);
4685                         gst_caps_unref(acaps);
4686
4687                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "openalsink", "audiosink", link_audio_sink_now, player);
4688                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "source-ambisonics-type", 1, NULL);
4689                         sound_manager_create_stream_information(SOUND_STREAM_TYPE_MEDIA, NULL, NULL, &stream_info);
4690                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "stream-info", stream_info, NULL);
4691
4692                         player->is_openal_plugin_used = TRUE;
4693
4694                         if (player->video360_yaw_radians <= M_PI &&
4695                                         player->video360_yaw_radians >= -M_PI &&
4696                                         player->video360_pitch_radians <= M_PI_2 &&
4697                                         player->video360_pitch_radians >= -M_PI_2) {
4698                                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
4699                                                 "source-orientation-y", (int) (player->video360_yaw_radians * 180.0 / M_PI),
4700                                                 "source-orientation-x", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
4701                         } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
4702                                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst),
4703                                                 "source-orientation-y", player->video360_metadata.init_view_heading,
4704                                                 "source-orientation-x", player->video360_metadata.init_view_pitch, NULL);
4705                         }
4706                 } else {
4707                         if (player->is_360_feature_enabled && player->is_content_spherical)
4708                                 LOGW("Audio track isn't of the ambisonic type and can't be played back as a spatial sound.\n");
4709                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, player->ini.audiosink_element, "audiosink", link_audio_sink_now, player);
4710                 }
4711
4712                 /* qos on */
4713                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);       /* qos on */
4714                 g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "slave-method", GST_AUDIO_BASE_SINK_SLAVE_NONE, NULL);
4715
4716
4717                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) ||
4718                         (player->videodec_linked && player->ini.use_system_clock)) {
4719                         LOGD("system clock will be used.\n");
4720                         g_object_set(G_OBJECT(audiobin[MMPLAYER_A_SINK].gst), "provide-clock", FALSE,  NULL);
4721                 }
4722
4723                 if (g_strrstr(player->ini.audiosink_element, "pulsesink"))
4724                         __mmplayer_gst_set_audiosink_property(player, attrs);
4725         }
4726
4727         if (audiobin[MMPLAYER_A_SINK].gst) {
4728                 GstPad *sink_pad = NULL;
4729                 sink_pad = gst_element_get_static_pad(audiobin[MMPLAYER_A_SINK].gst, "sink");
4730                 MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN,
4731                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
4732                 gst_object_unref(GST_OBJECT(sink_pad));
4733         }
4734
4735         __mmplayer_add_sink(player, audiobin[MMPLAYER_A_SINK].gst);
4736
4737         /* adding created elements to bin */
4738         LOGD("adding created elements to bin\n");
4739         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket)) {
4740                 LOGE("failed to add elements\n");
4741                 goto ERROR;
4742         }
4743
4744         /* linking elements in the bucket by added order. */
4745         LOGD("Linking elements in the bucket by added order.\n");
4746         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
4747                 LOGE("failed to link elements\n");
4748                 goto ERROR;
4749         }
4750
4751         /* get first element's sinkpad for creating ghostpad */
4752         first_element = (MMPlayerGstElement *)element_bucket->data;
4753         if (!first_element) {
4754                 LOGE("failed to get first elem\n");
4755                 goto ERROR;
4756         }
4757
4758         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
4759         if (!pad) {
4760                 LOGE("failed to get pad from first element of audiobin\n");
4761                 goto ERROR;
4762         }
4763
4764         ghostpad = gst_ghost_pad_new("sink", pad);
4765         if (!ghostpad) {
4766                 LOGE("failed to create ghostpad\n");
4767                 goto ERROR;
4768         }
4769
4770         if (FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad)) {
4771                 LOGE("failed to add ghostpad to audiobin\n");
4772                 goto ERROR;
4773         }
4774
4775         gst_object_unref(pad);
4776
4777         g_list_free(element_bucket);
4778         MMPLAYER_FLEAVE();
4779
4780         return MM_ERROR_NONE;
4781
4782 ERROR:
4783
4784         LOGD("ERROR : releasing audiobin\n");
4785
4786         if (pad)
4787                 gst_object_unref(GST_OBJECT(pad));
4788
4789         if (ghostpad)
4790                 gst_object_unref(GST_OBJECT(ghostpad));
4791
4792         if (element_bucket)
4793                 g_list_free(element_bucket);
4794
4795         /* release element which are not added to bin */
4796         for (i = 1; i < MMPLAYER_A_NUM; i++) {
4797                 /* NOTE : skip bin */
4798                 if (audiobin[i].gst) {
4799                         GstObject* parent = NULL;
4800                         parent = gst_element_get_parent(audiobin[i].gst);
4801
4802                         if (!parent) {
4803                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
4804                                 audiobin[i].gst = NULL;
4805                         } else
4806                                 gst_object_unref(GST_OBJECT(parent));
4807                 }
4808         }
4809
4810         /* release audiobin with it's childs */
4811         if (audiobin[MMPLAYER_A_BIN].gst)
4812                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
4813
4814         MMPLAYER_FREEIF(audiobin);
4815
4816         player->pipeline->audiobin = NULL;
4817
4818         return MM_ERROR_PLAYER_INTERNAL;
4819 }
4820
4821 static GstPadProbeReturn
4822 __mmplayer_audio_stream_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
4823 {
4824         mm_player_t* player = (mm_player_t*) u_data;
4825         GstBuffer *pad_buffer = gst_pad_probe_info_get_buffer(info);
4826         GstMapInfo probe_info = GST_MAP_INFO_INIT;
4827
4828         gst_buffer_map(pad_buffer, &probe_info, GST_MAP_READ);
4829
4830         if (player->audio_stream_cb && probe_info.size && probe_info.data)
4831                 player->audio_stream_cb((void *)probe_info.data, probe_info.size, player->audio_stream_cb_user_param);
4832
4833         return GST_PAD_PROBE_OK;
4834 }
4835
4836 static guint32 _mmplayer_convert_fourcc_string_to_value(const gchar* format_name)
4837 {
4838         return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24);
4839 }
4840
4841 int _mmplayer_video_stream_release_bo(mm_player_t* player, void* bo)
4842 {
4843         int ret = MM_ERROR_NONE;
4844         GList *l = NULL;
4845         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4846         MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_INVALID_ARGUMENT);
4847
4848         MMPLAYER_VIDEO_BO_LOCK(player);
4849
4850         if (player->video_bo_list) {
4851                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4852                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4853                         if (tmp && tmp->bo == bo) {
4854                                 tmp->using = FALSE;
4855                                 LOGD("release bo %p", bo);
4856                                 tbm_bo_unref(tmp->bo);
4857                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
4858                                 MMPLAYER_VIDEO_BO_SIGNAL(player);
4859                                 return ret;
4860                         }
4861                 }
4862         } else {
4863                 /* hw codec is running or the list was reset for DRC. */
4864                 LOGW("there is no bo list.");
4865         }
4866         MMPLAYER_VIDEO_BO_UNLOCK(player);
4867
4868         LOGW("failed to find bo %p", bo);
4869         return ret;
4870 }
4871
4872 static void
4873 __mmplayer_video_stream_destroy_bo_list(mm_player_t* player)
4874 {
4875         GList *l = NULL;
4876
4877         MMPLAYER_FENTER();
4878         MMPLAYER_RETURN_IF_FAIL(player);
4879
4880         MMPLAYER_VIDEO_BO_LOCK(player);
4881         if (player->video_bo_list) {
4882                 LOGD("destroy video_bo_list : %d", g_list_length(player->video_bo_list));
4883                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4884                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4885                         if (tmp) {
4886                                 if (tmp->bo)
4887                                         tbm_bo_unref(tmp->bo);
4888                                 g_free(tmp);
4889                         }
4890                 }
4891                 g_list_free(player->video_bo_list);
4892                 player->video_bo_list = NULL;
4893         }
4894         player->video_bo_size = 0;
4895         MMPLAYER_VIDEO_BO_UNLOCK(player);
4896
4897         MMPLAYER_FLEAVE();
4898         return;
4899 }
4900
4901 static void*
4902 __mmplayer_video_stream_get_bo(mm_player_t* player, int size)
4903 {
4904         GList *l = NULL;
4905         MMPLAYER_RETURN_VAL_IF_FAIL(player, NULL);
4906         gboolean ret = TRUE;
4907
4908         /* check DRC, if it is, destroy the prev bo list to create again */
4909         if (player->video_bo_size != size) {
4910                 LOGD("video size is changed: %d -> %d", player->video_bo_size, size);
4911                 __mmplayer_video_stream_destroy_bo_list(player);
4912                 player->video_bo_size = size;
4913         }
4914
4915         MMPLAYER_VIDEO_BO_LOCK(player);
4916
4917         if ((!player->video_bo_list) ||
4918                 (g_list_length(player->video_bo_list) < player->ini.num_of_video_bo)) {
4919
4920                 /* create bo list */
4921                 int idx = 0;
4922                 LOGD("Create bo list for decoded video stream(num:%d)", player->ini.num_of_video_bo);
4923
4924                 if (player->video_bo_list) {
4925                         /* if bo list did not created all, try it again. */
4926                         idx = g_list_length(player->video_bo_list);
4927                         LOGD("bo list exist(len: %d)", idx);
4928                 }
4929
4930                 for (; idx < player->ini.num_of_video_bo; idx++) {
4931                         mm_player_video_bo_info_t* bo_info = g_new(mm_player_video_bo_info_t, 1);
4932                         if (!bo_info) {
4933                                 LOGE("Fail to alloc bo_info.");
4934                                 break;
4935                         }
4936                         bo_info->bo = tbm_bo_alloc(player->bufmgr, size, TBM_BO_DEFAULT);
4937                         if (!bo_info->bo) {
4938                                 LOGE("Fail to tbm_bo_alloc.");
4939                                 g_free(bo_info);
4940                                 break;
4941                         }
4942                         bo_info->using = FALSE;
4943                         player->video_bo_list = g_list_append(player->video_bo_list, bo_info);
4944                 }
4945
4946                 /* update video num buffers */
4947                 player->video_num_buffers = idx;
4948                 if (idx == player->ini.num_of_video_bo)
4949                         player->video_extra_num_buffers = player->ini.num_of_video_bo/2;
4950
4951                 if (idx == 0) {
4952                         MMPLAYER_VIDEO_BO_UNLOCK(player);
4953                         return NULL;
4954                 }
4955
4956                 LOGD("Num of video buffers(%d/%d)", player->video_num_buffers, player->video_extra_num_buffers);
4957         }
4958
4959         while (TRUE) {
4960                 /* get bo from list*/
4961                 for (l = g_list_first(player->video_bo_list); l; l = g_list_next(l)) {
4962                         mm_player_video_bo_info_t* tmp = (mm_player_video_bo_info_t *)l->data;
4963                         if (tmp && (tmp->using == FALSE)) {
4964                                 LOGD("found bo %p to use", tmp->bo);
4965                                 tmp->using = TRUE;
4966                                 MMPLAYER_VIDEO_BO_UNLOCK(player);
4967                                 return tbm_bo_ref(tmp->bo);
4968                         }
4969                 }
4970                 if (!ret) {
4971                         LOGE("failed to get bo in %d timeout", player->ini.video_bo_timeout);
4972                         MMPLAYER_VIDEO_BO_UNLOCK(player);
4973                         return NULL;
4974                 }
4975
4976                 if (player->ini.video_bo_timeout <= 0) {
4977                         MMPLAYER_VIDEO_BO_WAIT(player);
4978                 } else {
4979                         gint64 timeout = g_get_monotonic_time() + player->ini.video_bo_timeout*G_TIME_SPAN_SECOND;
4980                         ret = MMPLAYER_VIDEO_BO_WAIT_UNTIL(player, timeout);
4981                 }
4982                 continue;
4983         }
4984 }
4985
4986 static void
4987 __mmplayer_video_stream_decoded_preroll_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
4988 {
4989         mm_player_t* player = (mm_player_t*)data;
4990         MMPLAYER_FENTER();
4991         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
4992
4993         /* send prerolled pkt */
4994         player->video_stream_prerolled = FALSE;
4995
4996         __mmplayer_video_stream_decoded_render_cb(object, buffer, pad, data);
4997
4998         /* not to send prerolled pkt again */
4999         player->video_stream_prerolled = TRUE;
5000 }
5001
5002 static void
5003 __mmplayer_video_stream_decoded_render_cb(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5004 {
5005         mm_player_t* player = (mm_player_t*)data;
5006         GstCaps *caps = NULL;
5007         MMPlayerVideoStreamDataType *stream = NULL;
5008         MMVideoBuffer *video_buffer = NULL;
5009         GstMemory *dataBlock = NULL;
5010         GstMemory *metaBlock = NULL;
5011         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5012         GstStructure *structure = NULL;
5013         const gchar *string_format = NULL;
5014         unsigned int fourcc = 0;
5015
5016         MMPLAYER_FENTER();
5017         MMPLAYER_RETURN_IF_FAIL(player && player->video_stream_cb);
5018
5019         if (player->video_stream_prerolled) {
5020                 player->video_stream_prerolled = FALSE;
5021                 LOGD("skip the prerolled pkt not to send it again");
5022                 return;
5023         }
5024
5025         caps = gst_pad_get_current_caps(pad);
5026         if (caps == NULL) {
5027                 LOGE("Caps is NULL.");
5028                 return;
5029         }
5030
5031         /* MMPLAYER_LOG_GST_CAPS_TYPE(caps); */
5032
5033         /* clear stream data structure */
5034         stream = (MMPlayerVideoStreamDataType *)g_malloc0(sizeof(MMPlayerVideoStreamDataType));
5035         if (!stream) {
5036                 LOGE("failed to alloc mem for video data");
5037                 return;
5038         }
5039
5040         structure = gst_caps_get_structure(caps, 0);
5041         gst_structure_get_int(structure, "width", &(stream->width));
5042         gst_structure_get_int(structure, "height", &(stream->height));
5043         string_format = gst_structure_get_string(structure, "format");
5044         if (string_format)
5045                 fourcc = _mmplayer_convert_fourcc_string_to_value(string_format);
5046         stream->format = util_get_pixtype(fourcc);
5047         gst_caps_unref(caps);
5048         caps = NULL;
5049
5050         __mmplayer_get_video_angle(player, NULL, &stream->orientation);
5051
5052     /*
5053         LOGD("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
5054                 GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format);
5055     */
5056
5057         if (stream->width == 0 || stream->height == 0 || stream->format == MM_PIXEL_FORMAT_INVALID) {
5058                 LOGE("Wrong condition!!");
5059                 goto ERROR;
5060         }
5061
5062         /* set size and timestamp */
5063         dataBlock = gst_buffer_peek_memory(buffer, 0);
5064         stream->length_total = gst_memory_get_sizes(dataBlock, NULL, NULL);
5065         stream->timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */
5066
5067         /* check zero-copy */
5068         if (player->set_mode.video_zc &&
5069                 player->set_mode.media_packet_video_stream &&
5070                 gst_buffer_n_memory(buffer) > 1) {
5071                 metaBlock = gst_buffer_peek_memory(buffer, 1);
5072                 gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ);
5073                 video_buffer = (MMVideoBuffer *)mapinfo.data;
5074         }
5075
5076         if (video_buffer) { /* hw codec */
5077                 /* set tbm bo */
5078                 if (video_buffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
5079                         int i = 0;
5080
5081                         /* copy pointer of tbm bo, stride, elevation */
5082                         while (i < MM_VIDEO_BUFFER_PLANE_MAX && video_buffer->handle.bo[i]) {
5083                                 stream->bo[i] = tbm_bo_ref(video_buffer->handle.bo[i]);
5084                                 i++;
5085                         }
5086                 } else {
5087                         LOGE("Not support video buffer format");
5088                         goto ERROR;
5089                 }
5090                 memcpy(stream->stride, video_buffer->stride_width,
5091                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5092                 memcpy(stream->elevation, video_buffer->stride_height,
5093                                 sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
5094
5095                 /* will be released, by calling _mm_player_video_stream_internal_buffer_unref() */
5096                 stream->internal_buffer = gst_buffer_ref(buffer);
5097         } else { /* sw codec */
5098                 int i = 0;
5099                 int j = 0;
5100                 int k = 0;
5101                 int ret = TBM_SURFACE_ERROR_NONE;
5102                 int src_stride[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
5103                 int src_offset[MM_PLAYER_IMGB_MPLANE_MAX] = { 0, };
5104                 int size = 0;
5105                 unsigned char *src = NULL;
5106                 unsigned char *dest = NULL;
5107                 tbm_bo_handle thandle;
5108                 tbm_surface_h surface;
5109                 tbm_surface_info_s info;
5110                 gboolean gst_ret;
5111
5112                 gst_ret = gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE);
5113                 if (!gst_ret) {
5114                         LOGE("fail to gst_memory_map");
5115                         goto ERROR;
5116                 }
5117
5118
5119                 if (stream->format == MM_PIXEL_FORMAT_I420) {
5120                         surface = tbm_surface_create(stream->width, stream->height, TBM_FORMAT_YUV420);
5121
5122                         ret = tbm_surface_get_info(surface, &info);
5123
5124                         if (ret != TBM_SURFACE_ERROR_NONE) {
5125                                 tbm_surface_destroy(surface);
5126                                 goto ERROR;
5127                         }
5128                         tbm_surface_destroy(surface);
5129
5130                         src_stride[0] = GST_ROUND_UP_4(stream->width);
5131                         src_stride[1] = src_stride[2] = GST_ROUND_UP_4(stream->width>>1);
5132                         src_offset[1] = src_stride[0] * GST_ROUND_UP_2(stream->height);
5133                         src_offset[2] = src_offset[1] + (src_stride[1] * (GST_ROUND_UP_2(stream->height)>>1));
5134                         stream->stride[0] = info.planes[0].stride;
5135                         stream->elevation[0] = info.planes[0].size / info.planes[0].stride;
5136                         stream->stride[1] = info.planes[1].stride;
5137                         stream->elevation[1] = info.planes[1].size / info.planes[1].stride;
5138                         stream->stride[2] = info.planes[2].stride;
5139                         stream->elevation[2] = info.planes[2].size / info.planes[2].stride;
5140                         size = info.planes[0].size + info.planes[1].size + info.planes[2].size;
5141                 } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
5142                         stream->stride[0] = stream->width * 4;
5143                         stream->elevation[0] = stream->height;
5144                         size = stream->stride[0] * stream->height;
5145                 } else {
5146                         LOGE("Not support format %d", stream->format);
5147                         goto ERROR;
5148                 }
5149
5150                 stream->bo[0] = __mmplayer_video_stream_get_bo(player, size);
5151                 if (!stream->bo[0]) {
5152                         LOGE("Fail to tbm_bo_alloc!!");
5153                         goto ERROR;
5154                 }
5155
5156                 thandle = tbm_bo_map(stream->bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE);
5157                 if (thandle.ptr && mapinfo.data) {
5158                         if (stream->format == MM_PIXEL_FORMAT_I420) {
5159                                 for (i = 0; i < 3; i++) {
5160                                         src = mapinfo.data + src_offset[i];
5161                                         dest = thandle.ptr + info.planes[i].offset;
5162
5163                                         if (i > 0) k = 1;
5164                                         for (j = 0; j < stream->height>>k; j++) {
5165                                                 memcpy(dest, src, stream->width>>k);
5166                                                 src += src_stride[i];
5167                                                 dest += stream->stride[i];
5168                                         }
5169                                 }
5170                         } else if (stream->format == MM_PIXEL_FORMAT_RGBA) {
5171                                 memcpy(thandle.ptr, mapinfo.data, size);
5172                         } else {
5173                                 LOGE("Not support format %d", stream->format);
5174                                 goto ERROR;
5175                         }
5176                 } else {
5177                         LOGE("data pointer is wrong. dest : %p, src : %p",
5178                                         thandle.ptr, mapinfo.data);
5179                         goto ERROR;
5180                 }
5181                 tbm_bo_unmap(stream->bo[0]);
5182         }
5183
5184         if (player->video_stream_cb) { /* This has been already checked at the entry */
5185                 if (!player->video_stream_cb(stream, player->video_stream_cb_user_param)) {
5186                         LOGE("failed to send video stream data.");
5187                         goto ERROR;
5188                 }
5189         }
5190
5191         if (metaBlock)
5192                 gst_memory_unmap(metaBlock, &mapinfo);
5193         else
5194                 gst_memory_unmap(dataBlock, &mapinfo);
5195
5196         return;
5197
5198 ERROR:
5199         LOGE("release video stream resource.");
5200         if (metaBlock) {
5201                 int i = 0;
5202                 for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
5203                         if (stream->bo[i])
5204                                 tbm_bo_unref(stream->bo[i]);
5205                 }
5206                 gst_memory_unmap(metaBlock, &mapinfo);
5207
5208                 /* unref gst buffer */
5209                 if (stream->internal_buffer)
5210                         gst_buffer_unref(stream->internal_buffer);
5211         } else if (dataBlock) {
5212                 if (stream->bo[0])
5213                         _mmplayer_video_stream_release_bo(player, stream->bo[0]);
5214                 gst_memory_unmap(dataBlock, &mapinfo);
5215         }
5216
5217         g_free(stream);
5218         return;
5219 }
5220
5221 static int
5222 __mmplayer_gst_create_video_filters(mm_player_t* player, GList** bucket)
5223 {
5224         gchar* video_csc = "videoconvert"; /* default colorspace converter */
5225         GList* element_bucket = NULL;
5226
5227         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->videobin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5228
5229         MMPLAYER_FENTER();
5230
5231         if (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical)) {
5232                 LOGD("do not need to add video filters.");
5233                 return MM_ERROR_NONE;
5234         }
5235
5236         /* in case of sw codec except 360 playback,
5237          * if libav video decoder is selected, videoconvert is required to render the shm wl-buffer which support RGB only via tizenwlsink. */
5238         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_CONV, video_csc, "video converter", TRUE, player);
5239         LOGD("using video converter: %s", video_csc);
5240
5241         /* set video rotator */
5242         MMPLAYER_CREATE_ELEMENT(player->pipeline->videobin, MMPLAYER_V_FLIP, "videoflip", "video rotator", TRUE, player);
5243
5244         *bucket = element_bucket;
5245         MMPLAYER_FLEAVE();
5246         return MM_ERROR_NONE;
5247
5248 ERROR: /* refer MMPLAYER_CREATE_ELEMENT */
5249         g_list_free(element_bucket);
5250
5251         *bucket = NULL;
5252         MMPLAYER_FLEAVE();
5253         return MM_ERROR_PLAYER_INTERNAL;
5254 }
5255
5256 /**
5257  * This function is to create video pipeline.
5258  *
5259  * @param       player          [in]    handle of player
5260  *              caps            [in]    src caps of decoder
5261  *              surface_type    [in]    surface type for video rendering
5262  *
5263  * @return      This function returns zero on success.
5264  * @remark
5265  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
5266  */
5267 /**
5268   * VIDEO PIPELINE
5269   * - video overlay surface(arm/x86) : tizenwlsink
5270   */
5271 static int
5272 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
5273 {
5274         GstPad *pad = NULL;
5275         MMHandleType attrs;
5276         GList*element_bucket = NULL;
5277         MMPlayerGstElement* first_element = NULL;
5278         MMPlayerGstElement* videobin = NULL;
5279         gchar *videosink_element = NULL;
5280
5281         MMPLAYER_FENTER();
5282
5283         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5284
5285         /* alloc handles */
5286         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
5287         if (!videobin)
5288                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5289
5290         player->pipeline->videobin = videobin;
5291
5292         attrs = MMPLAYER_GET_ATTRS(player);
5293         if (!attrs) {
5294                 LOGE("cannot get content attribute");
5295                 return MM_ERROR_PLAYER_INTERNAL;
5296         }
5297
5298         /* create bin */
5299         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
5300         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
5301         if (!videobin[MMPLAYER_V_BIN].gst) {
5302                 LOGE("failed to create videobin");
5303                 goto ERROR;
5304         }
5305
5306         int enable_video_decoded_cb = 0;
5307         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable_video_decoded_cb);
5308
5309         if (player->is_360_feature_enabled && player->is_content_spherical) {
5310                 LOGD("video360 elem will be added.");
5311
5312                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_360, "video360",
5313                                 "video-360", TRUE, player);
5314
5315                 /* Set spatial media metadata and/or user settings to the element.
5316                  * */
5317                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5318                                 "projection-type", player->video360_metadata.projection_type, NULL);
5319
5320                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5321                                 "stereo-mode", player->video360_metadata.stereo_mode, NULL);
5322
5323                 if (player->video360_metadata.full_pano_width_pixels &&
5324                                 player->video360_metadata.full_pano_height_pixels &&
5325                                 player->video360_metadata.cropped_area_image_width &&
5326                                 player->video360_metadata.cropped_area_image_height) {
5327                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5328                                         "projection-bounds-top", player->video360_metadata.cropped_area_top,
5329                                         "projection-bounds-bottom", player->video360_metadata.full_pano_height_pixels -
5330                                                         player->video360_metadata.cropped_area_top - player->video360_metadata.cropped_area_image_height,
5331                                         "projection-bounds-left", player->video360_metadata.cropped_area_left,
5332                                         "projection-bounds-right", player->video360_metadata.full_pano_width_pixels -
5333                                                         player->video360_metadata.cropped_area_left - player->video360_metadata.cropped_area_image_width,
5334                                         NULL);
5335                 }
5336
5337                 if (player->video360_horizontal_fov && player->video360_vertical_fov) {
5338                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5339                                         "horizontal-fov", player->video360_horizontal_fov,
5340                                         "vertical-fov", player->video360_vertical_fov, NULL);
5341                 }
5342
5343                 if (player->video360_zoom <= VIDEO360_MAX_ZOOM && player->video360_zoom > 1.0f) {
5344                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5345                                         "zoom", 1.0f / player->video360_zoom, NULL);
5346                 }
5347
5348                 if (player->video360_yaw_radians <= M_PI &&
5349                                 player->video360_yaw_radians >= -M_PI &&
5350                                 player->video360_pitch_radians <= M_PI_2 &&
5351                                 player->video360_pitch_radians >= -M_PI_2) {
5352                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5353                                         "pose-yaw", (int) (player->video360_yaw_radians * 180.0 / M_PI),
5354                                         "pose-pitch", (int) (player->video360_pitch_radians * 180.0 / M_PI), NULL);
5355                 } else if (player->video360_metadata.init_view_heading || player->video360_metadata.init_view_pitch) {
5356                         g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5357                                         "pose-yaw", player->video360_metadata.init_view_heading,
5358                                         "pose-pitch", player->video360_metadata.init_view_pitch, NULL);
5359                 }
5360
5361                 g_object_set(G_OBJECT(videobin[MMPLAYER_V_360].gst),
5362                                 "passthrough", !player->is_video360_enabled, NULL);
5363         }
5364
5365         /* set video sink */
5366         switch (surface_type) {
5367         case MM_DISPLAY_SURFACE_OVERLAY:
5368                 if (__mmplayer_gst_create_video_filters(player, &element_bucket) != MM_ERROR_NONE)
5369                         goto ERROR;
5370                 if (strlen(player->ini.videosink_element_overlay) > 0)
5371                         videosink_element = player->ini.videosink_element_overlay;
5372                 else
5373                         goto ERROR;
5374                 break;
5375         case MM_DISPLAY_SURFACE_NULL:
5376                 if (strlen(player->ini.videosink_element_fake) > 0)
5377                         videosink_element = player->ini.videosink_element_fake;
5378                 else
5379                         goto ERROR;
5380                 break;
5381         case MM_DISPLAY_SURFACE_REMOTE:
5382                 if (strlen(player->ini.videosink_element_fake) > 0)
5383                         videosink_element = player->ini.videosink_element_fake;
5384                 else
5385                         goto ERROR;
5386                 break;
5387         default:
5388                 LOGE("unidentified surface type");
5389                 goto ERROR;
5390         }
5391         LOGD("surface_type %d, selected videosink name: %s", surface_type, videosink_element);
5392
5393         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, "videosink", TRUE, player);
5394
5395         /* additional setting for sink plug-in */
5396         switch (surface_type) {
5397         case MM_DISPLAY_SURFACE_OVERLAY:
5398         {
5399                 bool use_tbm = (player->set_mode.video_zc || (player->is_360_feature_enabled && player->is_content_spherical));
5400                 if (!use_tbm) {
5401                         LOGD("selected videosink name: %s", videosink_element);
5402
5403                         /* support shard memory with S/W codec on HawkP */
5404                         if (strncmp(videosink_element, "tizenwlsink", strlen(videosink_element)) == 0) {
5405                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
5406                                         "use-tbm", use_tbm, NULL);
5407                         }
5408                 } else {
5409                         if (attrs) {
5410                                 int gapless = 0;
5411
5412                                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
5413
5414                                 if (gapless > 0) {
5415                                         LOGD("disable last-sample");
5416                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
5417                                 }
5418                         }
5419                 }
5420                 if (player->set_mode.media_packet_video_stream) {
5421                         int enable = 0;
5422                         mm_attrs_get_int_by_name(player->attrs, "enable_video_decoded_cb", &enable);
5423                         if (enable)
5424                                 g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "signal-handoffs", TRUE, NULL);
5425
5426                         MMPLAYER_SIGNAL_CONNECT(player,
5427                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5428                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5429                                                                         "handoff",
5430                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5431                                                                         (gpointer)player);
5432
5433                         MMPLAYER_SIGNAL_CONNECT(player,
5434                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5435                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5436                                                                         "preroll-handoff",
5437                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5438                                                                         (gpointer)player);
5439                 }
5440                 break;
5441         }
5442         case MM_DISPLAY_SURFACE_REMOTE:
5443         {
5444                 if (player->set_mode.media_packet_video_stream) {
5445                         LOGE("add data probe at videosink");
5446                         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5447                                                                                         "sync", TRUE, "signal-handoffs", TRUE, NULL);
5448
5449                         MMPLAYER_SIGNAL_CONNECT(player,
5450                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5451                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5452                                                                         "handoff",
5453                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_render_cb),
5454                                                                         (gpointer)player);
5455
5456                         MMPLAYER_SIGNAL_CONNECT(player,
5457                                                                         G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst),
5458                                                                         MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5459                                                                         "preroll-handoff",
5460                                                                         G_CALLBACK(__mmplayer_video_stream_decoded_preroll_cb),
5461                                                                         (gpointer)player);
5462                         if (attrs) {
5463                                 int gapless = 0;
5464
5465                                 mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless);
5466
5467                                 if (gapless > 0) {
5468                                         LOGD("disable last-sample");
5469                                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "enable-last-sample", FALSE, NULL);
5470                                 }
5471                         }
5472                 }
5473                 break;
5474         }
5475         default:
5476                 break;
5477         }
5478
5479         if (_mmplayer_update_video_param(player, "update_all_param") != MM_ERROR_NONE)
5480                 goto ERROR;
5481
5482         if (videobin[MMPLAYER_V_SINK].gst) {
5483                 GstPad *sink_pad = NULL;
5484                 sink_pad = gst_element_get_static_pad(videobin[MMPLAYER_V_SINK].gst, "sink");
5485                 if (sink_pad) {
5486                         MMPLAYER_SIGNAL_CONNECT(player, sink_pad, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN,
5487                                         "notify::caps", G_CALLBACK(__mmplayer_gst_caps_notify_cb), player);
5488                         gst_object_unref(GST_OBJECT(sink_pad));
5489                 } else
5490                         LOGW("failed to get sink pad from videosink\n");
5491         }
5492
5493         /* store it as it's sink element */
5494         __mmplayer_add_sink(player, videobin[MMPLAYER_V_SINK].gst);
5495
5496         /* adding created elements to bin */
5497         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket)) {
5498                 LOGE("failed to add elements\n");
5499                 goto ERROR;
5500         }
5501
5502         /* Linking elements in the bucket by added order */
5503         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5504                 LOGE("failed to link elements\n");
5505                 goto ERROR;
5506         }
5507
5508         /* get first element's sinkpad for creating ghostpad */
5509         if (element_bucket)
5510                 first_element = (MMPlayerGstElement *)element_bucket->data;
5511         if (!first_element) {
5512                 LOGE("failed to get first element from bucket\n");
5513                 goto ERROR;
5514         }
5515
5516         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
5517         if (!pad) {
5518                 LOGE("failed to get pad from first element\n");
5519                 goto ERROR;
5520         }
5521
5522         /* create ghostpad */
5523         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", pad);
5524         if (FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
5525                 LOGE("failed to add ghostpad to videobin\n");
5526                 goto ERROR;
5527         }
5528         gst_object_unref(pad);
5529
5530         /* done. free allocated variables */
5531         if (element_bucket)
5532                 g_list_free(element_bucket);
5533
5534         MMPLAYER_FLEAVE();
5535
5536         return MM_ERROR_NONE;
5537
5538 ERROR:
5539         LOGE("ERROR : releasing videobin\n");
5540
5541         g_list_free(element_bucket);
5542
5543         if (pad)
5544                 gst_object_unref(GST_OBJECT(pad));
5545
5546         /* release videobin with it's childs */
5547         if (videobin[MMPLAYER_V_BIN].gst)
5548                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
5549
5550
5551         MMPLAYER_FREEIF(videobin);
5552
5553         player->pipeline->videobin = NULL;
5554
5555         return MM_ERROR_PLAYER_INTERNAL;
5556 }
5557
5558 static int __mmplayer_gst_create_plain_text_elements(mm_player_t* player)
5559 {
5560         GList *element_bucket = NULL;
5561         MMPlayerGstElement *textbin = player->pipeline->textbin;
5562
5563         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_QUEUE, "queue", "text_queue", TRUE, player);
5564         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_IDENTITY, "identity", "text_identity", TRUE, player);
5565         g_object_set(G_OBJECT(textbin[MMPLAYER_T_IDENTITY].gst),
5566                                                         "signal-handoffs", FALSE,
5567                                                         NULL);
5568
5569         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_FAKE_SINK, "fakesink", "text_fakesink", TRUE, player);
5570         MMPLAYER_SIGNAL_CONNECT(player,
5571                                                         G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst),
5572                                                         MM_PLAYER_SIGNAL_TYPE_TEXTBIN,
5573                                                         "handoff",
5574                                                         G_CALLBACK(__mmplayer_update_subtitle),
5575                                                         (gpointer)player);
5576
5577         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "async", TRUE, NULL);
5578         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "sync", TRUE, NULL);
5579         g_object_set(G_OBJECT(textbin[MMPLAYER_T_FAKE_SINK].gst), "signal-handoffs", TRUE, NULL);
5580
5581         if (!player->play_subtitle) {
5582                 LOGD("add textbin sink as sink element of whole pipeline.\n");
5583                 __mmplayer_add_sink(player, GST_ELEMENT(textbin[MMPLAYER_T_FAKE_SINK].gst));
5584         }
5585
5586         /* adding created elements to bin */
5587         LOGD("adding created elements to bin\n");
5588         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket)) {
5589                 LOGE("failed to add elements\n");
5590                 goto ERROR;
5591         }
5592
5593         /* unset sink flag from textbin. not to hold eos when video data is shorter than subtitle */
5594         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_BIN].gst, GST_ELEMENT_FLAG_SINK);
5595         GST_OBJECT_FLAG_UNSET(textbin[MMPLAYER_T_FAKE_SINK].gst, GST_ELEMENT_FLAG_SINK);
5596
5597         /* linking elements in the bucket by added order. */
5598         LOGD("Linking elements in the bucket by added order.\n");
5599         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
5600                 LOGE("failed to link elements\n");
5601                 goto ERROR;
5602         }
5603
5604         /* done. free allocated variables */
5605         g_list_free(element_bucket);
5606
5607         if (textbin[MMPLAYER_T_QUEUE].gst) {
5608                 GstPad *pad = NULL;
5609                 GstPad *ghostpad = NULL;
5610
5611                 pad = gst_element_get_static_pad(GST_ELEMENT(textbin[MMPLAYER_T_QUEUE].gst), "sink");
5612                 if (!pad) {
5613                         LOGE("failed to get sink pad of text queue");
5614                         goto ERROR;
5615                 }
5616
5617                 ghostpad = gst_ghost_pad_new("text_sink", pad);
5618                 gst_object_unref(pad);
5619
5620                 if (!ghostpad) {
5621                         LOGE("failed to create ghostpad of textbin\n");
5622                         goto ERROR;
5623                 }
5624
5625                 if (!gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad)) {
5626                         LOGE("failed to add ghostpad to textbin\n");
5627                         gst_object_unref(ghostpad);
5628                         goto ERROR;
5629                 }
5630         }
5631
5632         return MM_ERROR_NONE;
5633
5634 ERROR:
5635         g_list_free(element_bucket);
5636
5637         if (!player->play_subtitle && textbin[MMPLAYER_T_FAKE_SINK].gst) {
5638                 LOGE("remove textbin sink from sink list");
5639                 __mmplayer_del_sink(player, textbin[MMPLAYER_T_FAKE_SINK].gst);
5640         }
5641
5642         /* release element at __mmplayer_gst_create_text_sink_bin */
5643         return MM_ERROR_PLAYER_INTERNAL;
5644 }
5645
5646 static int __mmplayer_gst_create_text_sink_bin(mm_player_t* player)
5647 {
5648         MMPlayerGstElement *textbin = NULL;
5649         GList *element_bucket = NULL;
5650         int surface_type = 0;
5651         gint i = 0;
5652
5653         MMPLAYER_FENTER();
5654
5655         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
5656
5657         /* alloc handles */
5658         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
5659         if (!textbin) {
5660                 LOGE("failed to allocate memory for textbin\n");
5661                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
5662         }
5663
5664         /* create bin */
5665         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
5666         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
5667         if (!textbin[MMPLAYER_T_BIN].gst) {
5668                 LOGE("failed to create textbin\n");
5669                 goto ERROR;
5670         }
5671
5672         /* take it */
5673         player->pipeline->textbin = textbin;
5674
5675         /* fakesink */
5676         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
5677         LOGD("surface type for subtitle : %d", surface_type);
5678         switch (surface_type) {
5679         case MM_DISPLAY_SURFACE_OVERLAY:
5680         case MM_DISPLAY_SURFACE_NULL:
5681         case MM_DISPLAY_SURFACE_REMOTE:
5682                 if (__mmplayer_gst_create_plain_text_elements(player) != MM_ERROR_NONE) {
5683                         LOGE("failed to make plain text elements\n");
5684                         goto ERROR;
5685                 }
5686                 break;
5687         default:
5688                 goto ERROR;
5689                 break;
5690         }
5691
5692         MMPLAYER_FLEAVE();
5693
5694         return MM_ERROR_NONE;
5695
5696 ERROR:
5697
5698         LOGD("ERROR : releasing textbin\n");
5699
5700         g_list_free(element_bucket);
5701
5702         /* release signal */
5703         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5704
5705         /* release element which are not added to bin */
5706         for (i = 1; i < MMPLAYER_T_NUM; i++) {
5707                 /* NOTE : skip bin */
5708                 if (textbin[i].gst) {
5709                         GstObject* parent = NULL;
5710                         parent = gst_element_get_parent(textbin[i].gst);
5711
5712                         if (!parent) {
5713                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
5714                                 textbin[i].gst = NULL;
5715                         } else {
5716                                 gst_object_unref(GST_OBJECT(parent));
5717                         }
5718                 }
5719         }
5720
5721         /* release textbin with it's childs */
5722         if (textbin[MMPLAYER_T_BIN].gst)
5723                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5724
5725         MMPLAYER_FREEIF(player->pipeline->textbin);
5726         player->pipeline->textbin = NULL;
5727
5728         MMPLAYER_FLEAVE();
5729         return MM_ERROR_PLAYER_INTERNAL;
5730 }
5731
5732
5733 static int
5734 __mmplayer_gst_create_text_pipeline(mm_player_t* player)
5735 {
5736         MMPlayerGstElement* mainbin = NULL;
5737         MMPlayerGstElement* textbin = NULL;
5738         MMHandleType attrs = 0;
5739         GstElement *subsrc = NULL;
5740         GstElement *subparse = NULL;
5741         gchar *subtitle_uri = NULL;
5742         const gchar *charset = NULL;
5743         GstPad *pad = NULL;
5744
5745         MMPLAYER_FENTER();
5746
5747         /* get mainbin */
5748         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
5749                                                                 player->pipeline &&
5750                                                                 player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
5751
5752         mainbin = player->pipeline->mainbin;
5753
5754         attrs = MMPLAYER_GET_ATTRS(player);
5755         if (!attrs) {
5756                 LOGE("cannot get content attribute\n");
5757                 return MM_ERROR_PLAYER_INTERNAL;
5758         }
5759
5760         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
5761         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
5762                 LOGE("subtitle uri is not proper filepath.\n");
5763                 return MM_ERROR_PLAYER_INVALID_URI;
5764         }
5765
5766         if (!util_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) {
5767                 LOGE("failed to get storage info of subtitle path");
5768                 return MM_ERROR_PLAYER_INVALID_URI;
5769         }
5770
5771         SECURE_LOGD("subtitle file path is [%s].\n", subtitle_uri);
5772
5773         MMPLAYER_SUBTITLE_INFO_LOCK(player);
5774         player->subtitle_language_list = NULL;
5775         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
5776
5777         /* create the subtitle source */
5778         subsrc = gst_element_factory_make("filesrc", "subtitle_source");
5779         if (!subsrc) {
5780                 LOGE("failed to create filesrc element\n");
5781                 goto ERROR;
5782         }
5783         g_object_set(G_OBJECT(subsrc), "location", subtitle_uri, NULL);
5784
5785         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
5786         mainbin[MMPLAYER_M_SUBSRC].gst = subsrc;
5787
5788         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subsrc)) {
5789                 LOGW("failed to add queue\n");
5790                 gst_object_unref(mainbin[MMPLAYER_M_SUBSRC].gst);
5791                 mainbin[MMPLAYER_M_SUBSRC].gst = NULL;
5792                 mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_NUM;
5793                 goto ERROR;
5794         }
5795
5796         /* subparse */
5797         subparse = gst_element_factory_make("subparse", "subtitle_parser");
5798         if (!subparse) {
5799                 LOGE("failed to create subparse element\n");
5800                 goto ERROR;
5801         }
5802
5803         charset = util_get_charset(subtitle_uri);
5804         if (charset) {
5805                 LOGD("detected charset is %s\n", charset);
5806                 g_object_set(G_OBJECT(subparse), "subtitle-encoding", charset, NULL);
5807         }
5808
5809         mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_SUBPARSE;
5810         mainbin[MMPLAYER_M_SUBPARSE].gst = subparse;
5811
5812         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), subparse)) {
5813                 LOGW("failed to add subparse\n");
5814                 gst_object_unref(mainbin[MMPLAYER_M_SUBPARSE].gst);
5815                 mainbin[MMPLAYER_M_SUBPARSE].gst = NULL;
5816                 mainbin[MMPLAYER_M_SUBPARSE].id = MMPLAYER_M_NUM;
5817                 goto ERROR;
5818         }
5819
5820         if (!gst_element_link_pads(subsrc, "src", subparse, "sink")) {
5821                 LOGW("failed to link subsrc and subparse\n");
5822                 goto ERROR;
5823         }
5824
5825         player->play_subtitle = TRUE;
5826         player->adjust_subtitle_pos = 0;
5827
5828         LOGD("play subtitle using subtitle file\n");
5829
5830         if (player->pipeline->textbin == NULL) {
5831                 if (MM_ERROR_NONE != __mmplayer_gst_create_text_sink_bin(player)) {
5832                         LOGE("failed to create text sink bin. continuing without text\n");
5833                         goto ERROR;
5834                 }
5835
5836                 textbin = player->pipeline->textbin;
5837
5838                 if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), GST_ELEMENT(textbin[MMPLAYER_T_BIN].gst))) {
5839                         LOGW("failed to add textbin\n");
5840
5841                         /* release signal */
5842                         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5843
5844                         /* release textbin with it's childs */
5845                         gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
5846                         MMPLAYER_FREEIF(player->pipeline->textbin);
5847                         player->pipeline->textbin = textbin = NULL;
5848                         goto ERROR;
5849                 }
5850
5851                 LOGD("link text input selector and textbin ghost pad");
5852
5853                 player->textsink_linked = 1;
5854                 player->external_text_idx = 0;
5855                 LOGI("player->textsink_linked set to 1\n");
5856         } else {
5857                 textbin = player->pipeline->textbin;
5858                 LOGD("text bin has been created. reuse it.");
5859                 player->external_text_idx = 1;
5860         }
5861
5862         if (!gst_element_link_pads(subparse, "src", textbin[MMPLAYER_T_BIN].gst, "text_sink")) {
5863                 LOGW("failed to link subparse and textbin\n");
5864                 goto ERROR;
5865         }
5866
5867         pad = gst_element_get_static_pad(textbin[MMPLAYER_T_FAKE_SINK].gst, "sink");
5868         if (!pad) {
5869                 LOGE("failed to get sink pad from textsink to probe data");
5870                 goto ERROR;
5871         }
5872
5873         gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
5874                                 __mmplayer_subtitle_adjust_position_probe, player, NULL);
5875
5876         gst_object_unref(pad);
5877         pad = NULL;
5878
5879         /* create dot. for debugging */
5880         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-with-subtitle");
5881         MMPLAYER_FLEAVE();
5882
5883         return MM_ERROR_NONE;
5884
5885 ERROR:
5886         /* release text pipeline resource */
5887         player->textsink_linked = 0;
5888
5889         /* release signal */
5890         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
5891
5892         if (player->pipeline->textbin) {
5893                 LOGE("remove textbin");
5894
5895                 /* release textbin with it's childs */
5896                 MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
5897                 MMPLAYER_FREEIF(player->pipeline->textbin);
5898                 player->pipeline->textbin = NULL;
5899
5900         }
5901
5902         /* release subtitle elem */
5903         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
5904         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
5905
5906         return MM_ERROR_PLAYER_INTERNAL;
5907 }
5908
5909 gboolean
5910 __mmplayer_update_subtitle(GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
5911 {
5912         mm_player_t* player = (mm_player_t*) data;
5913         MMMessageParamType msg = {0, };
5914         GstClockTime duration = 0;
5915         gpointer text = NULL;
5916         guint text_size = 0;
5917         gboolean ret = TRUE;
5918         GstMapInfo mapinfo = GST_MAP_INFO_INIT;
5919
5920         MMPLAYER_FENTER();
5921
5922         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5923         MMPLAYER_RETURN_VAL_IF_FAIL(buffer, FALSE);
5924
5925         if (player->is_subtitle_force_drop) {
5926                 LOGW("subtitle is dropped forcedly.");
5927                 return ret;
5928         }
5929
5930         gst_buffer_map(buffer, &mapinfo, GST_MAP_READ);
5931         text = mapinfo.data;
5932         text_size = mapinfo.size;
5933         duration = GST_BUFFER_DURATION(buffer);
5934
5935         if (player->set_mode.subtitle_off) {
5936                 LOGD("subtitle is OFF.\n");
5937                 return TRUE;
5938         }
5939
5940         if (!text || (text_size == 0)) {
5941                 LOGD("There is no subtitle to be displayed.\n");
5942                 return TRUE;
5943         }
5944
5945         msg.data = (void *) text;
5946         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
5947
5948         LOGD("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data);
5949
5950         MMPLAYER_POST_MSG(player, MM_MESSAGE_UPDATE_SUBTITLE, &msg);
5951         gst_buffer_unmap(buffer, &mapinfo);
5952
5953         MMPLAYER_FLEAVE();
5954
5955         return ret;
5956 }
5957
5958 static GstPadProbeReturn
5959 __mmplayer_subtitle_adjust_position_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data)
5960 {
5961         mm_player_t *player = (mm_player_t *) u_data;
5962         GstClockTime cur_timestamp = 0;
5963         gint64 adjusted_timestamp = 0;
5964         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
5965
5966         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
5967
5968         if (player->set_mode.subtitle_off) {
5969                 LOGD("subtitle is OFF.\n");
5970                 return TRUE;
5971         }
5972
5973         if (player->adjust_subtitle_pos == 0) {
5974                 LOGD("nothing to do");
5975                 return TRUE;
5976         }
5977
5978         cur_timestamp = GST_BUFFER_TIMESTAMP(buffer);
5979         adjusted_timestamp = (gint64) cur_timestamp +((gint64) player->adjust_subtitle_pos * G_GINT64_CONSTANT(1000000));
5980
5981         if (adjusted_timestamp < 0) {
5982                 LOGD("adjusted_timestamp under zero");
5983                 MMPLAYER_FLEAVE();
5984                 return FALSE;
5985         }
5986
5987         GST_BUFFER_TIMESTAMP(buffer) = (GstClockTime) adjusted_timestamp;
5988         LOGD("buffer timestamp changed %" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "",
5989                                 GST_TIME_ARGS(cur_timestamp),
5990                                 GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
5991
5992         return GST_PAD_PROBE_OK;
5993 }
5994 static int __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
5995 {
5996         MMPLAYER_FENTER();
5997
5998         /* check player and subtitlebin are created */
5999         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6000         MMPLAYER_RETURN_VAL_IF_FAIL(player->play_subtitle, MM_ERROR_NOT_SUPPORT_API);
6001
6002         if (position == 0) {
6003                 LOGD("nothing to do\n");
6004                 MMPLAYER_FLEAVE();
6005                 return MM_ERROR_NONE;
6006         }
6007
6008         switch (format) {
6009         case MM_PLAYER_POS_FORMAT_TIME:
6010                 {
6011                         /* check current postion */
6012                         player->adjust_subtitle_pos = position;
6013
6014                         LOGD("save adjust_subtitle_pos in player") ;
6015                 }
6016                 break;
6017
6018         default:
6019                 {
6020                         LOGW("invalid format.\n");
6021                         MMPLAYER_FLEAVE();
6022                         return MM_ERROR_INVALID_ARGUMENT;
6023                 }
6024         }
6025
6026         MMPLAYER_FLEAVE();
6027
6028         return MM_ERROR_NONE;
6029 }
6030 static int __gst_adjust_video_position(mm_player_t* player, int offset)
6031 {
6032         MMPLAYER_FENTER();
6033         LOGD("adjusting video_pos in player") ;
6034         int current_pos = 0;
6035         /* check player and videobin are created */
6036         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
6037         if (!player->pipeline->videobin ||
6038                         !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
6039                 LOGD("no video pipeline or sink is there");
6040                 return MM_ERROR_PLAYER_INVALID_STATE ;
6041         }
6042         if (offset == 0) {
6043                 LOGD("nothing to do\n");
6044                 MMPLAYER_FLEAVE();
6045                 return MM_ERROR_NONE;
6046         }
6047         if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, (unsigned long*)&current_pos) != MM_ERROR_NONE) {
6048                 LOGD("failed to get current position");
6049                 return MM_ERROR_PLAYER_INTERNAL;
6050         }
6051         if ((current_pos - offset) < GST_TIME_AS_MSECONDS(player->duration)) {
6052                 LOGD("enter video delay is valid");
6053         } else {
6054                 LOGD("enter video delay is crossing content boundary");
6055                 return MM_ERROR_INVALID_ARGUMENT ;
6056         }
6057         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "ts-offset", ((gint64) offset * G_GINT64_CONSTANT(1000000)), NULL);
6058         LOGD("video delay has been done");
6059         MMPLAYER_FLEAVE();
6060
6061         return MM_ERROR_NONE;
6062 }
6063
6064 static void
6065 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data)
6066 {
6067         GstElement *appsrc = element;
6068         MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
6069         GstBuffer *buffer = NULL;
6070         GstFlowReturn ret = GST_FLOW_OK;
6071         gint len = size;
6072
6073         MMPLAYER_RETURN_IF_FAIL(element);
6074         MMPLAYER_RETURN_IF_FAIL(buf);
6075
6076         buffer = gst_buffer_new();
6077
6078         if (buf->offset >= buf->len) {
6079                 LOGD("call eos appsrc\n");
6080                 g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
6081                 return;
6082         }
6083
6084         if (buf->len - buf->offset < size)
6085                 len = buf->len - buf->offset;
6086
6087         gst_buffer_insert_memory(buffer, -1, gst_memory_new_wrapped(0, (guint8 *)(buf->buf + buf->offset), len, 0, len, NULL, NULL));
6088         GST_BUFFER_OFFSET(buffer) = (guint64)buf->offset;
6089         GST_BUFFER_OFFSET_END(buffer) = (guint64)(buf->offset + len);
6090
6091         //LOGD("feed buffer %p, offset %u-%u length %u", buffer, buf->offset, (buf->offset+len), len);
6092         g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
6093
6094         buf->offset += len;
6095 }
6096
6097 static gboolean
6098 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data)
6099 {
6100         MMPlayerInputBuffer *buf = (MMPlayerInputBuffer *)user_data;
6101
6102         MMPLAYER_RETURN_VAL_IF_FAIL(buf, FALSE);
6103
6104         buf->offset  = (int)size;
6105
6106         return TRUE;
6107 }
6108
6109 static GstBusSyncReply
6110 __mmplayer_bus_sync_callback(GstBus * bus, GstMessage * message, gpointer data)
6111 {
6112         mm_player_t *player = (mm_player_t *)data;
6113         GstBusSyncReply reply = GST_BUS_DROP;
6114
6115         if (!(player->pipeline && player->pipeline->mainbin)) {
6116                 LOGE("player pipeline handle is null");
6117                 return GST_BUS_PASS;
6118         }
6119
6120         if (!__mmplayer_check_useful_message(player, message)) {
6121                 gst_message_unref(message);
6122                 return GST_BUS_DROP;
6123         }
6124
6125         switch (GST_MESSAGE_TYPE(message)) {
6126         case GST_MESSAGE_STATE_CHANGED:
6127                 /* post directly for fast launch */
6128                 if (player->sync_handler) {
6129                         __mmplayer_gst_callback(message, player);
6130                         reply = GST_BUS_DROP;
6131                 } else
6132                         reply = GST_BUS_PASS;
6133                 break;
6134         case GST_MESSAGE_TAG:
6135                 __mmplayer_gst_extract_tag_from_msg(player, message);
6136
6137                 #if 0 // debug
6138                 {
6139                         GstTagList *tags = NULL;
6140
6141                         gst_message_parse_tag(message, &tags);
6142                         if (tags) {
6143                                 LOGE("TAGS received from element \"%s\".\n",
6144                                 GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
6145
6146                                 gst_tag_list_foreach(tags, print_tag, NULL);
6147                                 gst_tag_list_free(tags);
6148                                 tags = NULL;
6149                         }
6150                         break;
6151                 }
6152                 #endif
6153                 break;
6154
6155         case GST_MESSAGE_DURATION_CHANGED:
6156                 __mmplayer_gst_handle_duration(player, message);
6157                 break;
6158         case GST_MESSAGE_ASYNC_DONE:
6159                 /* NOTE:Don't call gst_callback directly
6160                  * because previous frame can be showed even though this message is received for seek.
6161                  */
6162         default:
6163                 reply = GST_BUS_PASS;
6164                 break;
6165         }
6166
6167         if (reply == GST_BUS_DROP)
6168                 gst_message_unref(message);
6169
6170         return reply;
6171 }
6172
6173 static gboolean
6174 __mmplayer_gst_create_decoder(mm_player_t *player,
6175                                                                 MMPlayerTrackType track,
6176                                                                 GstPad* srcpad,
6177                                                                 enum MainElementID elemId,
6178                                                                 const gchar* name)
6179 {
6180         gboolean ret = TRUE;
6181         GstPad *sinkpad = NULL;
6182
6183         MMPLAYER_FENTER();
6184
6185         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
6186                                                 player->pipeline &&
6187                                                 player->pipeline->mainbin, FALSE);
6188         MMPLAYER_RETURN_VAL_IF_FAIL((track == MM_PLAYER_TRACK_TYPE_AUDIO || track == MM_PLAYER_TRACK_TYPE_VIDEO), FALSE);
6189         MMPLAYER_RETURN_VAL_IF_FAIL(srcpad, FALSE);
6190         MMPLAYER_RETURN_VAL_IF_FAIL((player->pipeline->mainbin[elemId].gst == NULL), FALSE);
6191
6192         GstElement *decodebin = NULL;
6193         GstCaps *dec_caps = NULL;
6194
6195         /* create decodebin */
6196         decodebin = gst_element_factory_make("decodebin", name);
6197
6198         if (!decodebin) {
6199                 LOGE("error : fail to create decodebin for %d decoder\n", track);
6200                 ret = FALSE;
6201                 goto ERROR;
6202         }
6203
6204         /* raw pad handling signal */
6205         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6206                                                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
6207
6208         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
6209         before looking for any elements that can handle that stream.*/
6210         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
6211                                                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
6212
6213         /* This signal is emitted when a element is added to the bin.*/
6214         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
6215                                                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
6216
6217         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
6218                 LOGE("failed to add new decodebin\n");
6219                 ret = FALSE;
6220                 goto ERROR;
6221         }
6222
6223         dec_caps = gst_pad_query_caps(srcpad, NULL);
6224         if (dec_caps) {
6225                 //LOGD("got pad %s:%s , dec_caps %" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME(srcpad), dec_caps);
6226                 g_object_set(G_OBJECT(decodebin), "sink-caps", dec_caps, NULL);
6227                 gst_caps_unref(dec_caps);
6228         }
6229
6230         player->pipeline->mainbin[elemId].id = elemId;
6231         player->pipeline->mainbin[elemId].gst = decodebin;
6232
6233         sinkpad = gst_element_get_static_pad(decodebin, "sink");
6234
6235         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
6236                 LOGW("failed to link [%s:%s] to decoder\n", GST_DEBUG_PAD_NAME(srcpad));
6237                 gst_object_unref(GST_OBJECT(decodebin));
6238         }
6239
6240         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin))
6241                 LOGE("failed to sync second level decodebin state with parent\n");
6242
6243         LOGD("Total num of %d tracks = %d \n", track, player->selector[track].total_track_num);
6244
6245 ERROR:
6246         if (sinkpad) {
6247                 gst_object_unref(GST_OBJECT(sinkpad));
6248                 sinkpad = NULL;
6249         }
6250         MMPLAYER_FLEAVE();
6251
6252         return ret;
6253 }
6254
6255 /**
6256  * This function is to create  audio or video pipeline for playing.
6257  *
6258  * @param       player          [in]    handle of player
6259  *
6260  * @return      This function returns zero on success.
6261  * @remark
6262  * @see
6263  */
6264 static int
6265 __mmplayer_gst_create_pipeline(mm_player_t* player)
6266 {
6267         GstBus  *bus = NULL;
6268         MMPlayerGstElement *mainbin = NULL;
6269         MMHandleType attrs = 0;
6270         GstElement* element = NULL;
6271         GstElement* elem_src_audio = NULL;
6272         GstElement* elem_src_subtitle = NULL;
6273         GstElement* es_video_queue = NULL;
6274         GstElement* es_audio_queue = NULL;
6275         GstElement* es_subtitle_queue = NULL;
6276         GList* element_bucket = NULL;
6277         gboolean need_state_holder = TRUE;
6278         gint i = 0;
6279 #ifdef SW_CODEC_ONLY
6280         int surface_type = 0;
6281 #endif
6282         MMPLAYER_FENTER();
6283
6284         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6285
6286         /* get profile attribute */
6287         attrs = MMPLAYER_GET_ATTRS(player);
6288         if (!attrs) {
6289                 LOGE("cannot get content attribute\n");
6290                 goto INIT_ERROR;
6291         }
6292
6293         /* create pipeline handles */
6294         if (player->pipeline) {
6295                 LOGW("pipeline should be released before create new one\n");
6296                 goto INIT_ERROR;
6297         }
6298
6299         player->video360_metadata.is_spherical = -1;
6300         player->is_openal_plugin_used = FALSE;
6301
6302         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0(sizeof(MMPlayerGstPipelineInfo));
6303         if (player->pipeline == NULL)
6304                 goto INIT_ERROR;
6305
6306         memset(player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo)); /* g_malloc0 did this job already */
6307
6308         /* create mainbin */
6309         mainbin = (MMPlayerGstElement*) g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
6310         if (mainbin == NULL)
6311                 goto INIT_ERROR;
6312
6313         memset(mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM); /* g_malloc0 did this job already */
6314
6315         /* create pipeline */
6316         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
6317         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
6318         if (!mainbin[MMPLAYER_M_PIPE].gst) {
6319                 LOGE("failed to create pipeline\n");
6320                 goto INIT_ERROR;
6321         }
6322         player->demux_pad_index = 0;
6323         player->subtitle_language_list = NULL;
6324
6325         player->is_subtitle_force_drop = FALSE;
6326         player->last_multiwin_status = FALSE;
6327
6328         _mmplayer_track_initialize(player);
6329         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
6330
6331         /* create source element */
6332         switch (player->profile.uri_type) {
6333         /* rtsp streamming */
6334         case MM_PLAYER_URI_TYPE_URL_RTSP:
6335                 {
6336                         gchar *user_agent;
6337
6338                         element = gst_element_factory_make("rtspsrc", "rtsp source");
6339
6340                         if (!element) {
6341                                 LOGE("failed to create streaming source element\n");
6342                                 break;
6343                         }
6344
6345                         /* make it zero */
6346                         user_agent = NULL;
6347
6348                         /* get attribute */
6349                         mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6350
6351                         SECURE_LOGD("user_agent : %s\n", user_agent);
6352
6353                         /* setting property to streaming source */
6354                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6355                         if (user_agent)
6356                                 g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6357
6358                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
6359                                 G_CALLBACK(__mmplayer_gst_rtp_dynamic_pad), player);
6360                         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(element), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
6361                                 G_CALLBACK(__mmplayer_gst_rtp_no_more_pads), player);
6362                 }
6363                 break;
6364
6365         /* http streaming*/
6366         case MM_PLAYER_URI_TYPE_URL_HTTP:
6367                 {
6368                         gchar *user_agent, *cookies, **cookie_list;
6369                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6370                         user_agent = cookies = NULL;
6371                         cookie_list = NULL;
6372                         gint mode = MM_PLAYER_PD_MODE_NONE;
6373
6374                         mm_attrs_get_int_by_name(attrs, "pd_mode", &mode);
6375
6376                         player->pd_mode = mode;
6377
6378                         LOGD("http playback, PD mode : %d\n", player->pd_mode);
6379
6380                         if (!MMPLAYER_IS_HTTP_PD(player)) {
6381                                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
6382                                 if (!element) {
6383                                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
6384                                         break;
6385                                 }
6386                                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
6387
6388                                 /* get attribute */
6389                                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
6390                                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
6391
6392                                 if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
6393                                         LOGD("get timeout from ini\n");
6394                                         http_timeout = player->ini.http_timeout;
6395                                 }
6396
6397                                 /* get attribute */
6398                                 SECURE_LOGD("location : %s\n", player->profile.uri);
6399                                 SECURE_LOGD("cookies : %s\n", cookies);
6400                                 SECURE_LOGD("user_agent :  %s\n",  user_agent);
6401                                 LOGD("timeout : %d\n",  http_timeout);
6402
6403                                 /* setting property to streaming source */
6404                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6405                                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6406                                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
6407
6408                                 /* parsing cookies */
6409                                 if ((cookie_list = util_get_cookie_list((const char*)cookies))) {
6410                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
6411                                         g_strfreev(cookie_list);
6412                                 }
6413                                 if (user_agent)
6414                                         g_object_set(G_OBJECT(element), "user-agent", user_agent, NULL);
6415
6416                                 if (MMPLAYER_URL_HAS_DASH_SUFFIX(player))
6417                                         LOGW("it's dash. and it's still experimental feature.");
6418                         } else {
6419                                 // progressive download
6420                                 gchar* location = NULL;
6421
6422                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI) {
6423                                         gchar *path = NULL;
6424
6425                                         mm_attrs_get_string_by_name(attrs, "pd_location", &path);
6426
6427                                         MMPLAYER_FREEIF(player->pd_file_save_path);
6428
6429                                         LOGD("PD Location : %s\n", path);
6430
6431                                         if (path) {
6432                                                 if (!util_get_storage_info(path, &player->storage_info[MMPLAYER_PATH_VOD])) {
6433                                                         LOGE("failed to get storage info");
6434                                                         break;
6435                                                 }
6436                                                 player->pd_file_save_path = g_strdup(path);
6437                                         } else {
6438                                                 LOGE("can't find pd location so, it should be set \n");
6439                                                 break;
6440                                         }
6441                                 }
6442
6443                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
6444                                 if (!element) {
6445                                         LOGE("failed to create PD push source element[%s].\n", "pdpushsrc");
6446                                         break;
6447                                 }
6448
6449                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
6450                                         g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
6451                                 else
6452                                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6453                                 g_object_get(element, "location", &location, NULL);
6454                                 LOGD("PD_LOCATION [%s].\n", location);
6455                                 if (location)
6456                                         g_free(location);
6457                         }
6458                 }
6459                 break;
6460
6461         /* file source */
6462         case MM_PLAYER_URI_TYPE_FILE:
6463                 {
6464                         LOGD("using filesrc for 'file://' handler.\n");
6465                         if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
6466                                 LOGE("failed to get storage info");
6467                                 break;
6468                         }
6469
6470                         element = gst_element_factory_make("filesrc", "source");
6471                         if (!element) {
6472                                 LOGE("failed to create filesrc\n");
6473                                 break;
6474                         }
6475
6476                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
6477                 }
6478                 break;
6479
6480         case MM_PLAYER_URI_TYPE_SS:
6481                 {
6482                         gint http_timeout = DEFAULT_HTTP_TIMEOUT;
6483                         element = gst_element_factory_make("souphttpsrc", "http streaming source");
6484                         if (!element) {
6485                                 LOGE("failed to create http streaming source element[%s]", player->ini.httpsrc_element);
6486                                 break;
6487                         }
6488
6489                         if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
6490                                 LOGD("get timeout from ini\n");
6491                                 http_timeout = player->ini.http_timeout;
6492                         }
6493
6494                         /* setting property to streaming source */
6495                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
6496                         g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
6497                 }
6498                 break;
6499         case MM_PLAYER_URI_TYPE_MS_BUFF:
6500                 {
6501                         LOGD("MS buff src is selected\n");
6502
6503                         if (player->v_stream_caps) {
6504                                 element = gst_element_factory_make("appsrc", "video_appsrc");
6505                                 if (!element) {
6506                                         LOGF("failed to create video app source element[appsrc].\n");
6507                                         break;
6508                                 }
6509
6510                                 if (player->a_stream_caps) {
6511                                         elem_src_audio = gst_element_factory_make("appsrc", "audio_appsrc");
6512                                         if (!elem_src_audio) {
6513                                                 LOGF("failed to create audio app source element[appsrc].\n");
6514                                                 break;
6515                                         }
6516                                 }
6517                         } else if (player->a_stream_caps) {
6518                                 /* no video, only audio pipeline*/
6519                                 element = gst_element_factory_make("appsrc", "audio_appsrc");
6520                                 if (!element) {
6521                                         LOGF("failed to create audio app source element[appsrc].\n");
6522                                         break;
6523                                 }
6524                         }
6525
6526                         if (player->s_stream_caps) {
6527                                 elem_src_subtitle = gst_element_factory_make("appsrc", "subtitle_appsrc");
6528                                 if (!elem_src_subtitle) {
6529                                         LOGF("failed to create subtitle app source element[appsrc].\n");
6530                                         break;
6531                                 }
6532                         }
6533
6534                         LOGD("setting app sources properties.\n");
6535                         LOGD("location : %s\n", player->profile.uri);
6536
6537                         if (player->v_stream_caps && element) {
6538                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6539                                                                                             "blocksize", (guint)1048576,        /* size of many video frames are larger than default blocksize as 4096 */
6540                                                                                                 "caps", player->v_stream_caps, NULL);
6541
6542                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6543                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6544                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO] > 0)
6545                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_VIDEO], NULL);
6546
6547                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6548                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6549                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6550                                                                                                                 G_CALLBACK(__gst_seek_video_data), player);
6551
6552                                 if (player->a_stream_caps && elem_src_audio) {
6553                                         g_object_set(G_OBJECT(elem_src_audio), "format", GST_FORMAT_TIME,
6554                                                                                                                         "caps", player->a_stream_caps, NULL);
6555
6556                                         if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6557                                                 g_object_set(G_OBJECT(elem_src_audio), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6558                                         if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6559                                                 g_object_set(G_OBJECT(elem_src_audio), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6560
6561                                         /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6562                                         gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_audio), GST_APP_STREAM_TYPE_SEEKABLE);
6563                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6564                                                                                                                 G_CALLBACK(__gst_seek_audio_data), player);
6565                                 }
6566                         } else if (player->a_stream_caps && element) {
6567                                 g_object_set(G_OBJECT(element), "format", GST_FORMAT_TIME,
6568                                                                                                 "caps", player->a_stream_caps, NULL);
6569
6570                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6571                                         g_object_set(G_OBJECT(element), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6572                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO] > 0)
6573                                         g_object_set(G_OBJECT(element), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_AUDIO], NULL);
6574
6575                                 /*Fix Seek External Demuxer:  set audio and video appsrc as seekable */
6576                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(element), GST_APP_STREAM_TYPE_SEEKABLE);
6577                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6578                                                                                                                         G_CALLBACK(__gst_seek_audio_data), player);
6579                         }
6580
6581                         if (player->s_stream_caps && elem_src_subtitle) {
6582                                 g_object_set(G_OBJECT(elem_src_subtitle), "format", GST_FORMAT_TIME,
6583                                                                                                                  "caps", player->s_stream_caps, NULL);
6584
6585                                 if (player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6586                                         g_object_set(G_OBJECT(elem_src_subtitle), "max-bytes", player->media_stream_buffer_max_size[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6587                                 if (player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT] > 0)
6588                                         g_object_set(G_OBJECT(elem_src_subtitle), "min-percent", player->media_stream_buffer_min_percent[MM_PLAYER_STREAM_TYPE_TEXT], NULL);
6589
6590                                 gst_app_src_set_stream_type((GstAppSrc*)G_OBJECT(elem_src_subtitle), GST_APP_STREAM_TYPE_SEEKABLE);
6591
6592                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6593                                                                                                                                 G_CALLBACK(__gst_seek_subtitle_data), player);
6594                         }
6595
6596                         if (player->v_stream_caps && element) {
6597                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6598                                                                                                                 G_CALLBACK(__gst_appsrc_feed_video_data), player);
6599                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6600                                                                                                                 G_CALLBACK(__gst_appsrc_enough_video_data), player);
6601
6602                                 if (player->a_stream_caps && elem_src_audio) {
6603                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6604                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6605                                         MMPLAYER_SIGNAL_CONNECT(player, elem_src_audio, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6606                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6607                                 }
6608                         } else if (player->a_stream_caps && element) {
6609                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6610                                                                                                                 G_CALLBACK(__gst_appsrc_feed_audio_data), player);
6611                                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "enough-data",
6612                                                                                                                 G_CALLBACK(__gst_appsrc_enough_audio_data), player);
6613                         }
6614
6615                         if (player->s_stream_caps && elem_src_subtitle)
6616                                 MMPLAYER_SIGNAL_CONNECT(player, elem_src_subtitle, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6617                                                                                                                 G_CALLBACK(__gst_appsrc_feed_subtitle_data), player);
6618
6619                         need_state_holder = FALSE;
6620
6621                         mm_attrs_set_int_by_name(attrs, "profile_prepare_async", TRUE);
6622                         if (mmf_attrs_commit(attrs)) /* return -1 if error */
6623                                 LOGE("failed to commit\n");
6624                 }
6625                 break;
6626         /* appsrc */
6627         case MM_PLAYER_URI_TYPE_MEM:
6628                 {
6629                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
6630
6631                         LOGD("mem src is selected\n");
6632
6633                         element = gst_element_factory_make("appsrc", "mem-source");
6634                         if (!element) {
6635                                 LOGE("failed to create appsrc element\n");
6636                                 break;
6637                         }
6638
6639                         g_object_set(element, "stream-type", stream_type, NULL);
6640                         g_object_set(element, "size", player->profile.input_mem.len, NULL);
6641                         g_object_set(element, "blocksize", (guint64)20480, NULL);
6642
6643                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "seek-data",
6644                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->profile.input_mem);
6645                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_OTHERS, "need-data",
6646                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->profile.input_mem);
6647                 }
6648                 break;
6649         case MM_PLAYER_URI_TYPE_URL:
6650                 break;
6651
6652         case MM_PLAYER_URI_TYPE_TEMP:
6653                 break;
6654
6655         case MM_PLAYER_URI_TYPE_NONE:
6656         default:
6657                 break;
6658         }
6659
6660         /* check source element is OK */
6661         if (!element) {
6662                 LOGE("no source element was created.\n");
6663                 goto INIT_ERROR;
6664         }
6665
6666         /* take source element */
6667         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
6668         mainbin[MMPLAYER_M_SRC].gst = element;
6669         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
6670
6671         if ((MMPLAYER_IS_STREAMING(player)) && (player->streamer == NULL)) {
6672                 player->streamer = __mm_player_streaming_create();
6673                 __mm_player_streaming_initialize(player->streamer);
6674         }
6675
6676         if (MMPLAYER_IS_HTTP_PD(player)) {
6677                 gint pre_buffering_time = player->streamer->buffering_req.prebuffer_time;
6678
6679                 LOGD("Picked queue2 element(pre buffer : %d ms)....\n", pre_buffering_time);
6680                 element = gst_element_factory_make("queue2", "queue2");
6681                 if (!element) {
6682                         LOGE("failed to create http streaming buffer element\n");
6683                         goto INIT_ERROR;
6684                 }
6685
6686                 /* take it */
6687                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
6688                 mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = element;
6689                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_MUXED_S_BUFFER]);
6690
6691                 pre_buffering_time = (pre_buffering_time > 0) ? (pre_buffering_time) : (player->ini.http_buffering_time);
6692
6693                 player->streamer->is_pd_mode = TRUE;
6694
6695                 __mm_player_streaming_set_queue2(player->streamer,
6696                                 element,
6697                                 TRUE,
6698                                 player->ini.http_max_size_bytes + PLAYER_PD_EXT_MAX_SIZE_BYTE,
6699                                 pre_buffering_time,
6700                                 1.0,
6701                                 player->ini.http_buffering_limit,
6702                                 MUXED_BUFFER_TYPE_MEM_QUEUE,
6703                                 NULL,
6704                                 0);
6705         }
6706         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6707                 if (player->v_stream_caps) {
6708                         es_video_queue = gst_element_factory_make("queue2", "video_queue");
6709                         if (!es_video_queue) {
6710                                 LOGE("create es_video_queue for es player failed\n");
6711                                 goto INIT_ERROR;
6712                         }
6713                         g_object_set(G_OBJECT(es_video_queue), "max-size-buffers", 2, NULL);
6714                         mainbin[MMPLAYER_M_V_BUFFER].id = MMPLAYER_M_V_BUFFER;
6715                         mainbin[MMPLAYER_M_V_BUFFER].gst = es_video_queue;
6716                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_V_BUFFER]);
6717
6718                         /* Adding audio appsrc to bucket */
6719                         if (player->a_stream_caps && elem_src_audio) {
6720                                 mainbin[MMPLAYER_M_2ND_SRC].id = MMPLAYER_M_2ND_SRC;
6721                                 mainbin[MMPLAYER_M_2ND_SRC].gst = elem_src_audio;
6722                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_2ND_SRC]);
6723
6724                                 es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6725                                 if (!es_audio_queue) {
6726                                         LOGE("create es_audio_queue for es player failed\n");
6727                                         goto INIT_ERROR;
6728                                 }
6729                                 g_object_set(G_OBJECT(es_audio_queue), "max-size-buffers", 2, NULL);
6730
6731                                 mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6732                                 mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6733                                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6734                         }
6735                 } else if (player->a_stream_caps) {
6736                         /* Only audio stream, no video */
6737                         es_audio_queue = gst_element_factory_make("queue2", "audio_queue");
6738                         if (!es_audio_queue) {
6739                                 LOGE("create es_audio_queue for es player failed\n");
6740                                 goto INIT_ERROR;
6741                         }
6742                         mainbin[MMPLAYER_M_A_BUFFER].id = MMPLAYER_M_A_BUFFER;
6743                         mainbin[MMPLAYER_M_A_BUFFER].gst = es_audio_queue;
6744                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_A_BUFFER]);
6745                 }
6746
6747                 if (player->s_stream_caps && elem_src_subtitle) {
6748                         mainbin[MMPLAYER_M_SUBSRC].id = MMPLAYER_M_SUBSRC;
6749                         mainbin[MMPLAYER_M_SUBSRC].gst = elem_src_subtitle;
6750                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SUBSRC]);
6751
6752                         es_subtitle_queue = gst_element_factory_make("queue2", "subtitle_queue");
6753                         if (!es_subtitle_queue) {
6754                                 LOGE("create es_subtitle_queue for es player failed\n");
6755                                 goto INIT_ERROR;
6756                         }
6757                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_V_BUFFER;
6758                         mainbin[MMPLAYER_M_S_BUFFER].gst = es_subtitle_queue;
6759                         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
6760                 }
6761         }
6762
6763         /* create autoplugging element if src element is not a rtsp src */
6764         if ((player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP) &&
6765                 (player->profile.uri_type != MM_PLAYER_URI_TYPE_MS_BUFF)) {
6766                 element = NULL;
6767                 enum MainElementID elemId = MMPLAYER_M_NUM;
6768
6769                 if (((MMPLAYER_IS_HTTP_PD(player)) ||
6770                         (!MMPLAYER_IS_HTTP_STREAMING(player)))) {
6771                         elemId = MMPLAYER_M_AUTOPLUG;
6772                         element = __mmplayer_create_decodebin(player);
6773                         if (element) {
6774                                 /* default size of mq in decodebin is 2M
6775                                  * but it can cause blocking issue during seeking depends on content. */
6776                                 g_object_set(G_OBJECT(element), "max-size-bytes", (5*1024*1024), NULL);
6777                         }
6778                         need_state_holder = FALSE;
6779                 } else {
6780                         elemId = MMPLAYER_M_TYPEFIND;
6781                         element = gst_element_factory_make("typefind", "typefinder");
6782                         MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
6783                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
6784                 }
6785
6786
6787                 /* check autoplug element is OK */
6788                 if (!element) {
6789                         LOGE("can not create element(%d)\n", elemId);
6790                         goto INIT_ERROR;
6791                 }
6792
6793                 mainbin[elemId].id = elemId;
6794                 mainbin[elemId].gst = element;
6795
6796                 element_bucket = g_list_append(element_bucket, &mainbin[elemId]);
6797         }
6798
6799         /* add elements to pipeline */
6800         if (!__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket)) {
6801                 LOGE("Failed to add elements to pipeline\n");
6802                 goto INIT_ERROR;
6803         }
6804
6805
6806         /* linking elements in the bucket by added order. */
6807         if (__mmplayer_gst_element_link_bucket(element_bucket) == -1) {
6808                 LOGE("Failed to link some elements\n");
6809                 goto INIT_ERROR;
6810         }
6811
6812
6813         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
6814         if (need_state_holder) {
6815                 /* create */
6816                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
6817                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make("fakesink", "state-holder");
6818
6819                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst) {
6820                         LOGE("fakesink element could not be created\n");
6821                         goto INIT_ERROR;
6822                 }
6823                 GST_OBJECT_FLAG_UNSET(mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_FLAG_SINK);
6824
6825                 /* take ownership of fakesink. we are reusing it */
6826                 gst_object_ref(mainbin[MMPLAYER_M_SRC_FAKESINK].gst);
6827
6828                 /* add */
6829                 if (FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
6830                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst)) {
6831                         LOGE("failed to add fakesink to bin\n");
6832                         goto INIT_ERROR;
6833                 }
6834         }
6835
6836         /* now we have completed mainbin. take it */
6837         player->pipeline->mainbin = mainbin;
6838
6839         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
6840                 GstPad *srcpad = NULL;
6841
6842                 if (mainbin[MMPLAYER_M_V_BUFFER].gst) {
6843                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_V_BUFFER].gst, "src");
6844                         if (srcpad) {
6845                                 __mmplayer_gst_create_decoder(player,
6846                                                                                                 MM_PLAYER_TRACK_TYPE_VIDEO,
6847                                                                                                 srcpad,
6848                                                                                                 MMPLAYER_M_AUTOPLUG_V_DEC,
6849                                                                                                 "video_decodebin");
6850
6851                                 gst_object_unref(GST_OBJECT(srcpad));
6852                                 srcpad = NULL;
6853                         }
6854                 }
6855
6856                 if ((player->a_stream_caps) && (mainbin[MMPLAYER_M_A_BUFFER].gst)) {
6857                         srcpad = gst_element_get_static_pad(mainbin[MMPLAYER_M_A_BUFFER].gst, "src");
6858                         if (srcpad) {
6859                                 __mmplayer_gst_create_decoder(player,
6860                                                                                                 MM_PLAYER_TRACK_TYPE_AUDIO,
6861                                                                                                 srcpad,
6862                                                                                                 MMPLAYER_M_AUTOPLUG_A_DEC,
6863                                                                                                 "audio_decodebin");
6864
6865                                 gst_object_unref(GST_OBJECT(srcpad));
6866                                 srcpad = NULL;
6867                         } // else error
6868                 } //  else error
6869
6870                 if (mainbin[MMPLAYER_M_S_BUFFER].gst)
6871                         __mmplayer_try_to_plug_decodebin(player, gst_element_get_static_pad(mainbin[MMPLAYER_M_S_BUFFER].gst, "src"), player->s_stream_caps);
6872         }
6873
6874         /* Note : check whether subtitle atrribute uri is set. If uri is set, then try to play subtitle file */
6875         if (__mmplayer_check_subtitle(player)) {
6876                 if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player))
6877                         LOGE("fail to create text pipeline");
6878         }
6879
6880         /* connect bus callback */
6881         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
6882         if (!bus) {
6883                 LOGE("cannot get bus from pipeline.\n");
6884                 goto INIT_ERROR;
6885         }
6886
6887         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_msg_push, player);
6888
6889         player->context.thread_default = g_main_context_get_thread_default();
6890
6891         if (player->context.thread_default == NULL) {
6892                 player->context.thread_default = g_main_context_default();
6893                 LOGD("thread-default context is the global default context");
6894         }
6895         LOGW("bus watcher thread context = %p, watcher : %d", player->context.thread_default, player->bus_watcher);
6896
6897         /* set sync handler to get tag synchronously */
6898         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player, NULL);
6899
6900         /* finished */
6901         gst_object_unref(GST_OBJECT(bus));
6902         g_list_free(element_bucket);
6903
6904         /* create gst bus_msb_cb thread */
6905         g_mutex_init(&player->bus_msg_thread_mutex);
6906         g_cond_init(&player->bus_msg_thread_cond);
6907         player->bus_msg_thread_exit = FALSE;
6908         player->bus_msg_timeout = PLAYER_BUS_MSG_DEFAULT_TIMEOUT;
6909         player->bus_msg_thread =
6910                 g_thread_try_new("gst_bus_msg_thread", __mmplayer_gst_bus_msg_thread, (gpointer)player, NULL);
6911         if (!player->bus_msg_thread) {
6912                 LOGE("failed to create gst BUS msg thread");
6913                 g_mutex_clear(&player->bus_msg_thread_mutex);
6914                 g_cond_clear(&player->bus_msg_thread_cond);
6915                 goto INIT_ERROR;
6916         }
6917
6918         MMPLAYER_FLEAVE();
6919
6920         return MM_ERROR_NONE;
6921
6922 INIT_ERROR:
6923         __mmplayer_gst_destroy_pipeline(player);
6924         g_list_free(element_bucket);
6925
6926         if (mainbin) {
6927                 /* release element which are not added to bin */
6928                 for (i = 1; i < MMPLAYER_M_NUM; i++) {
6929                         /* NOTE : skip pipeline */
6930                         if (mainbin[i].gst) {
6931                                 GstObject* parent = NULL;
6932                                 parent = gst_element_get_parent(mainbin[i].gst);
6933
6934                                 if (!parent) {
6935                                         gst_object_unref(GST_OBJECT(mainbin[i].gst));
6936                                         mainbin[i].gst = NULL;
6937                                 } else
6938                                         gst_object_unref(GST_OBJECT(parent));
6939                         }
6940                 }
6941
6942                 /* release pipeline with it's childs */
6943                 if (mainbin[MMPLAYER_M_PIPE].gst)
6944                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
6945
6946                 MMPLAYER_FREEIF(mainbin);
6947         }
6948
6949         MMPLAYER_FREEIF(player->pipeline);
6950         return MM_ERROR_PLAYER_INTERNAL;
6951 }
6952
6953 static void
6954 __mmplayer_reset_gapless_state(mm_player_t* player)
6955 {
6956         MMPLAYER_FENTER();
6957         MMPLAYER_RETURN_IF_FAIL(player
6958                 && player->pipeline
6959                 && player->pipeline->audiobin
6960                 && player->pipeline->audiobin[MMPLAYER_A_BIN].gst);
6961
6962         memset(&player->gapless, 0, sizeof(mm_player_gapless_t));
6963
6964         MMPLAYER_FLEAVE();
6965         return;
6966 }
6967
6968 static int
6969 __mmplayer_gst_destroy_pipeline(mm_player_t* player)
6970 {
6971         gint timeout = 0;
6972         int ret = MM_ERROR_NONE;
6973
6974         MMPLAYER_FENTER();
6975
6976         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_INVALID_HANDLE);
6977
6978         /* cleanup stuffs */
6979         MMPLAYER_FREEIF(player->type);
6980         player->have_dynamic_pad = FALSE;
6981         player->no_more_pad = FALSE;
6982         player->num_dynamic_pad = 0;
6983         player->demux_pad_index = 0;
6984         player->use_deinterleave = FALSE;
6985         player->max_audio_channels = 0;
6986         player->video_share_api_delta = 0;
6987         player->video_share_clock_delta = 0;
6988         player->video_hub_download_mode = 0;
6989
6990         MMPLAYER_SUBTITLE_INFO_LOCK(player);
6991         player->subtitle_language_list = NULL;
6992         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
6993
6994         __mmplayer_reset_gapless_state(player);
6995
6996         if (player->streamer) {
6997                 __mm_player_streaming_deinitialize(player->streamer);
6998                 __mm_player_streaming_destroy(player->streamer);
6999                 player->streamer = NULL;
7000         }
7001
7002         /* cleanup unlinked mime type */
7003         MMPLAYER_FREEIF(player->unlinked_audio_mime);
7004         MMPLAYER_FREEIF(player->unlinked_video_mime);
7005         MMPLAYER_FREEIF(player->unlinked_demuxer_mime);
7006
7007         /* cleanup running stuffs */
7008         __mmplayer_cancel_eos_timer(player);
7009
7010         /* cleanup gst stuffs */
7011         if (player->pipeline) {
7012                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
7013                 GstTagList* tag_list = player->pipeline->tag_list;
7014
7015                 /* first we need to disconnect all signal hander */
7016                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_ALL);
7017
7018                 if (player->bus_watcher)
7019                         __mmplayer_remove_g_source_from_context(player->context.thread_default, player->bus_watcher);
7020                 player->bus_watcher = 0;
7021
7022                 if (mainbin) {
7023                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
7024                         MMPlayerGstElement* videobin = player->pipeline->videobin;
7025                         MMPlayerGstElement* textbin = player->pipeline->textbin;
7026                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
7027                         gst_bus_set_sync_handler(bus, NULL, NULL, NULL);
7028                         gst_object_unref(bus);
7029
7030                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7031                         ret = __mmplayer_gst_set_state(player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout);
7032                         if (ret != MM_ERROR_NONE) {
7033                                 LOGE("fail to change state to NULL\n");
7034                                 return MM_ERROR_PLAYER_INTERNAL;
7035                         }
7036
7037                         LOGW("succeeded in chaning state to NULL\n");
7038
7039                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
7040
7041                         /* free fakesink */
7042                         if (mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
7043                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
7044
7045                         /* free avsysaudiosink
7046                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
7047                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
7048                         */
7049                         MMPLAYER_FREEIF(audiobin);
7050                         MMPLAYER_FREEIF(videobin);
7051                         MMPLAYER_FREEIF(textbin);
7052                         MMPLAYER_FREEIF(mainbin);
7053                 }
7054
7055                 if (tag_list)
7056                         gst_tag_list_free(tag_list);
7057
7058                 MMPLAYER_FREEIF(player->pipeline);
7059         }
7060         MMPLAYER_FREEIF(player->album_art);
7061
7062         if (player->v_stream_caps) {
7063                 gst_caps_unref(player->v_stream_caps);
7064                 player->v_stream_caps = NULL;
7065         }
7066         if (player->a_stream_caps) {
7067                 gst_caps_unref(player->a_stream_caps);
7068                 player->a_stream_caps = NULL;
7069         }
7070
7071         if (player->s_stream_caps) {
7072                 gst_caps_unref(player->s_stream_caps);
7073                 player->s_stream_caps = NULL;
7074         }
7075         _mmplayer_track_destroy(player);
7076
7077         if (player->sink_elements)
7078                 g_list_free(player->sink_elements);
7079         player->sink_elements = NULL;
7080
7081         if (player->bufmgr) {
7082                 tbm_bufmgr_deinit(player->bufmgr);
7083                 player->bufmgr = NULL;
7084         }
7085
7086         LOGW("finished destroy pipeline\n");
7087
7088         MMPLAYER_FLEAVE();
7089
7090         return ret;
7091 }
7092
7093 static int __gst_realize(mm_player_t* player)
7094 {
7095         gint timeout = 0;
7096         int ret = MM_ERROR_NONE;
7097
7098         MMPLAYER_FENTER();
7099
7100         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7101
7102         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7103
7104         ret = __mmplayer_gst_create_pipeline(player);
7105         if (ret) {
7106                 LOGE("failed to create pipeline\n");
7107                 return ret;
7108         }
7109
7110         /* set pipeline state to READY */
7111         /* NOTE : state change to READY must be performed sync. */
7112         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7113         ret = __mmplayer_gst_set_state(player,
7114                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
7115
7116         if (ret != MM_ERROR_NONE) {
7117                 /* return error if failed to set state */
7118                 LOGE("failed to set READY state");
7119                 return ret;
7120         }
7121
7122         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7123
7124         /* create dot before error-return. for debugging */
7125         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-realize");
7126
7127         MMPLAYER_FLEAVE();
7128
7129         return ret;
7130 }
7131
7132 static int __gst_unrealize(mm_player_t* player)
7133 {
7134         int ret = MM_ERROR_NONE;
7135
7136         MMPLAYER_FENTER();
7137
7138         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
7139
7140         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
7141         MMPLAYER_PRINT_STATE(player);
7142
7143         /* release miscellaneous information */
7144         __mmplayer_release_misc(player);
7145
7146         /* destroy pipeline */
7147         ret = __mmplayer_gst_destroy_pipeline(player);
7148         if (ret != MM_ERROR_NONE) {
7149                 LOGE("failed to destory pipeline\n");
7150                 return ret;
7151         }
7152
7153         /* release miscellaneous information.
7154            these info needs to be released after pipeline is destroyed. */
7155         __mmplayer_release_misc_post(player);
7156
7157         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
7158
7159         MMPLAYER_FLEAVE();
7160
7161         return ret;
7162 }
7163
7164 static int __gst_pending_seek(mm_player_t* player)
7165 {
7166         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7167         int ret = MM_ERROR_NONE;
7168
7169         MMPLAYER_FENTER();
7170
7171         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7172
7173         if (!player->pending_seek.is_pending) {
7174                 LOGD("pending seek is not reserved. nothing to do.\n");
7175                 return ret;
7176         }
7177
7178         /* check player state if player could pending seek or not. */
7179         current_state = MMPLAYER_CURRENT_STATE(player);
7180
7181         if (current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING) {
7182                 LOGW("try to pending seek in %s state, try next time. \n",
7183                         MMPLAYER_STATE_GET_NAME(current_state));
7184                 return ret;
7185         }
7186
7187         LOGD("trying to play from(%lu) pending position\n", player->pending_seek.pos);
7188
7189         ret = __gst_set_position(player, player->pending_seek.format, player->pending_seek.pos, FALSE);
7190
7191         if (MM_ERROR_NONE != ret)
7192                 LOGE("failed to seek pending postion. just keep staying current position.\n");
7193
7194         player->pending_seek.is_pending = FALSE;
7195
7196         MMPLAYER_FLEAVE();
7197
7198         return ret;
7199 }
7200
7201 static int __gst_start(mm_player_t* player)
7202 {
7203         gboolean sound_extraction = 0;
7204         int ret = MM_ERROR_NONE;
7205         gboolean async = FALSE;
7206
7207         MMPLAYER_FENTER();
7208
7209         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7210
7211         /* get sound_extraction property */
7212         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
7213
7214         /* NOTE : if SetPosition was called before Start. do it now */
7215         /* streaming doesn't support it. so it should be always sync */
7216         /* !!create one more api to check if there is pending seek rather than checking variables */
7217         if ((player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player)) {
7218                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
7219                 ret = __gst_pause(player, FALSE);
7220                 if (ret != MM_ERROR_NONE) {
7221                         LOGE("failed to set state to PAUSED for pending seek\n");
7222                         return ret;
7223                 }
7224
7225                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
7226
7227                 if (sound_extraction) {
7228                         LOGD("setting pcm extraction\n");
7229
7230                         ret = __mmplayer_set_pcm_extraction(player);
7231                         if (MM_ERROR_NONE != ret) {
7232                                 LOGW("failed to set pcm extraction\n");
7233                                 return ret;
7234                         }
7235                 } else {
7236                         if (MM_ERROR_NONE != __gst_pending_seek(player))
7237                                 LOGW("failed to seek pending postion. starting from the begin of content.\n");
7238                 }
7239         }
7240
7241         LOGD("current state before doing transition");
7242         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7243         MMPLAYER_PRINT_STATE(player);
7244
7245         /* set pipeline state to PLAYING  */
7246         if (player->es_player_push_mode)
7247                 async = TRUE;
7248         /* set pipeline state to PLAYING  */
7249         ret = __mmplayer_gst_set_state(player,
7250                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7251
7252         if (ret == MM_ERROR_NONE) {
7253                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7254         } else {
7255                 LOGE("failed to set state to PLAYING");
7256                 return ret;
7257         }
7258
7259         /* generating debug info before returning error */
7260         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-start");
7261
7262         MMPLAYER_FLEAVE();
7263
7264         return ret;
7265 }
7266
7267 static int __gst_stop(mm_player_t* player)
7268 {
7269         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
7270         MMHandleType attrs = 0;
7271         gboolean rewind = FALSE;
7272         gint timeout = 0;
7273         int ret = MM_ERROR_NONE;
7274         gboolean async = FALSE;
7275
7276         MMPLAYER_FENTER();
7277
7278         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7279         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7280
7281         LOGD("current state before doing transition");
7282         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
7283         MMPLAYER_PRINT_STATE(player);
7284
7285         attrs = MMPLAYER_GET_ATTRS(player);
7286         if (!attrs) {
7287                 LOGE("cannot get content attribute\n");
7288                 return MM_ERROR_PLAYER_INTERNAL;
7289         }
7290
7291         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
7292         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7293
7294         if ((!MMPLAYER_IS_STREAMING(player) && !MMPLAYER_IS_MS_BUFF_SRC(player)) ||
7295                 (player->streaming_type == STREAMING_SERVICE_VOD && player->videodec_linked))
7296                 rewind = TRUE;
7297
7298         if (player->es_player_push_mode)
7299                 async = TRUE;
7300         /* set gst state */
7301         ret = __mmplayer_gst_set_state(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, timeout);
7302
7303         /* return if set_state has failed */
7304         if (ret != MM_ERROR_NONE) {
7305                 LOGE("failed to set state.\n");
7306                 return ret;
7307         }
7308
7309         /* rewind */
7310         if (rewind) {
7311                 if (!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7312                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
7313                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
7314                         LOGW("failed to rewind\n");
7315                         ret = MM_ERROR_PLAYER_SEEK;
7316                 }
7317         }
7318
7319         /* initialize */
7320         player->sent_bos = FALSE;
7321
7322         if (player->es_player_push_mode) //for cloudgame
7323                 timeout = 0;
7324
7325         /* wait for seek to complete */
7326         change_ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
7327         if (change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL) {
7328                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_READY);
7329         } else {
7330                 LOGE("fail to stop player.\n");
7331                 ret = MM_ERROR_PLAYER_INTERNAL;
7332                 __mmplayer_dump_pipeline_state(player);
7333         }
7334
7335         /* generate dot file if enabled */
7336         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-stop");
7337
7338         MMPLAYER_FLEAVE();
7339
7340         return ret;
7341 }
7342
7343 int __gst_pause(mm_player_t* player, gboolean async)
7344 {
7345         int ret = MM_ERROR_NONE;
7346
7347         MMPLAYER_FENTER();
7348
7349         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7350         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
7351
7352         LOGD("current state before doing transition");
7353         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
7354         MMPLAYER_PRINT_STATE(player);
7355
7356         /* set pipeline status to PAUSED */
7357         ret = __mmplayer_gst_set_state(player,
7358                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
7359
7360         if (FALSE == async) {
7361                 if (ret != MM_ERROR_NONE) {
7362                         GstMessage *msg = NULL;
7363                         GTimer *timer = NULL;
7364                         gdouble MAX_TIMEOUT_SEC = 3;
7365
7366                         LOGE("failed to set state to PAUSED");
7367
7368                         if (player->msg_posted) {
7369                                 LOGE("error msg is already posted.");
7370                                 return ret;
7371                         }
7372
7373                         timer = g_timer_new();
7374                         g_timer_start(timer);
7375
7376                         GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
7377
7378                         do {
7379                                 msg = gst_bus_timed_pop(bus, 100 * GST_MSECOND);
7380                                 if (msg) {
7381                                         if (GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) {
7382                                                 GError *error = NULL;
7383
7384                                                 /* parse error code */
7385                                                 gst_message_parse_error(msg, &error, NULL);
7386
7387                                                 if (gst_structure_has_name(gst_message_get_structure(msg), "streaming_error")) {
7388                                                         /* Note : the streaming error from the streaming source is handled
7389                                                          *   using __mmplayer_handle_streaming_error.
7390                                                          */
7391                                                         __mmplayer_handle_streaming_error(player, msg);
7392
7393                                                 } else if (error) {
7394                                                         LOGE("paring error posted from bus, domain : %s, code : %d", g_quark_to_string(error->domain), error->code);
7395
7396                                                         if (error->domain == GST_STREAM_ERROR)
7397                                                                 ret = __gst_handle_stream_error(player, error, msg);
7398                                                         else if (error->domain == GST_RESOURCE_ERROR)
7399                                                                 ret = __gst_handle_resource_error(player, error->code, NULL);
7400                                                         else if (error->domain == GST_LIBRARY_ERROR)
7401                                                                 ret = __gst_handle_library_error(player, error->code);
7402                                                         else if (error->domain == GST_CORE_ERROR)
7403                                                                 ret = __gst_handle_core_error(player, error->code);
7404
7405                                                         g_error_free(error);
7406                                                 }
7407                                                 player->msg_posted = TRUE;
7408                                         }
7409                                         gst_message_unref(msg);
7410                                 }
7411                         } while (!player->msg_posted && (g_timer_elapsed(timer, NULL) < MAX_TIMEOUT_SEC));
7412                         /* clean */
7413                         gst_object_unref(bus);
7414                         g_timer_stop(timer);
7415                         g_timer_destroy(timer);
7416
7417                         return ret;
7418
7419                 } else if ((!MMPLAYER_IS_RTSP_STREAMING(player)) && (!player->video_stream_cb) &&
7420                                    (!player->pipeline->videobin) && (!player->pipeline->audiobin)) {
7421
7422                         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
7423
7424                 } else if (ret == MM_ERROR_NONE) {
7425
7426                         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PAUSED);
7427                 }
7428         }
7429
7430         /* generate dot file before returning error */
7431         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-pause");
7432
7433         MMPLAYER_FLEAVE();
7434
7435         return ret;
7436 }
7437
7438 int __gst_resume(mm_player_t* player, gboolean async)
7439 {
7440         int ret = MM_ERROR_NONE;
7441         gint timeout = 0;
7442
7443         MMPLAYER_FENTER();
7444
7445         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline,
7446                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7447
7448         LOGD("current state before doing transition");
7449         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
7450         MMPLAYER_PRINT_STATE(player);
7451
7452         /* generate dot file before returning error */
7453         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7454
7455         if (async)
7456                 LOGD("do async state transition to PLAYING.\n");
7457
7458         /* set pipeline state to PLAYING */
7459         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
7460
7461         ret = __mmplayer_gst_set_state(player,
7462                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout);
7463         if (ret != MM_ERROR_NONE) {
7464                 LOGE("failed to set state to PLAYING\n");
7465                 return ret;
7466         } else {
7467                 if (async == FALSE) {
7468                         // MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
7469                         LOGD("update state machine to %d\n", MM_PLAYER_STATE_PLAYING);
7470                         ret = __mmplayer_set_state(player, MM_PLAYER_STATE_PLAYING);
7471                 }
7472         }
7473
7474         /* generate dot file before returning error */
7475         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-resume");
7476
7477         MMPLAYER_FLEAVE();
7478
7479         return ret;
7480 }
7481
7482 static int
7483 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called)
7484 {
7485         unsigned long dur_msec = 0;
7486         gint64 dur_nsec = 0;
7487         gint64 pos_nsec = 0;
7488         gboolean ret = TRUE;
7489         gboolean accurated = FALSE;
7490         GstSeekFlags seek_flags = GST_SEEK_FLAG_FLUSH;
7491
7492         MMPLAYER_FENTER();
7493         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7494         MMPLAYER_RETURN_VAL_IF_FAIL(!MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP);
7495
7496         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
7497                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
7498                 goto PENDING;
7499
7500         if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7501                 /* check duration */
7502                 /* NOTE : duration cannot be zero except live streaming.
7503                  *              Since some element could have some timing problemn with quering duration, try again.
7504                  */
7505                 if (!player->duration) {
7506                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec)) {
7507                                 /* For RTSP Streaming , duration is not returned in READY state. So seek to the previous position does not work properly.
7508                                  * Added a patch to postpone the actual seek when state changes to PLAY. Sending a fake SEEK_COMPLETED event to finish the current request. */
7509                                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) && (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
7510                                         player->pending_seek.is_pending = TRUE;
7511                                         player->pending_seek.format = format;
7512                                         player->pending_seek.pos = position;
7513                                         player->doing_seek = FALSE;
7514                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
7515                                         return MM_ERROR_NONE;
7516                                 } else {
7517                                         goto SEEK_ERROR;
7518                                 }
7519                         }
7520                         player->duration = dur_nsec;
7521                 }
7522
7523                 if (player->duration) {
7524                         dur_msec = GST_TIME_AS_MSECONDS(player->duration);
7525                 } else {
7526                         LOGE("could not get the duration. fail to seek.\n");
7527                         goto SEEK_ERROR;
7528                 }
7529         }
7530         LOGD("playback rate: %f\n", player->playback_rate);
7531
7532         mm_attrs_get_int_by_name(player->attrs, "accurate_seek", &accurated);
7533         if (accurated)
7534                 seek_flags |= GST_SEEK_FLAG_ACCURATE;
7535         else
7536                 seek_flags |= GST_SEEK_FLAG_KEY_UNIT;
7537
7538         /* do seek */
7539         switch (format) {
7540         case MM_PLAYER_POS_FORMAT_TIME:
7541         {
7542                 if (!MMPLAYER_IS_MS_BUFF_SRC(player)) {
7543                         GstQuery *query = NULL;
7544                         gboolean seekable = FALSE;
7545
7546                         /* check position is valid or not */
7547                         if (position > dur_msec)
7548                                 goto INVALID_ARGS;
7549
7550                         query = gst_query_new_seeking(GST_FORMAT_TIME);
7551                         if (gst_element_query(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, query)) {
7552                                 gst_query_parse_seeking(query, NULL, &seekable, NULL, NULL);
7553                                 gst_query_unref(query);
7554
7555                                 if (!seekable) {
7556                                         LOGW("non-seekable content");
7557                                         player->doing_seek = FALSE;
7558                                         return MM_ERROR_PLAYER_NO_OP;
7559                                 }
7560                         } else {
7561                                 LOGW("failed to get seeking query");
7562                                 gst_query_unref(query); /* keep seeking operation */
7563                         }
7564
7565                         LOGD("seeking to(%lu) msec, duration is %d msec\n", position, dur_msec);
7566
7567                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
7568                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
7569                            This causes problem is position calculation during normal pause resume scenarios also.
7570                            Currently during seek , we are sending the current position to rtspsrc module for position saving for later use. */
7571                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
7572                                 (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
7573                                 if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_nsec))
7574                                         LOGW("getting current position failed in seek\n");
7575
7576                                 player->last_position = pos_nsec;
7577                                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
7578                         }
7579
7580                         if (player->doing_seek) {
7581                                 LOGD("not completed seek");
7582                                 return MM_ERROR_PLAYER_DOING_SEEK;
7583                         }
7584                 }
7585
7586                 if (!internal_called)
7587                         player->doing_seek = TRUE;
7588
7589                 pos_nsec = position * G_GINT64_CONSTANT(1000000);
7590
7591                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) && (!player->videodec_linked)) {
7592                         gint64 cur_time = 0;
7593
7594                         /* get current position */
7595                         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &cur_time);
7596
7597                         /* flush */
7598                         GstEvent *event = gst_event_new_seek(1.0,
7599                                                         GST_FORMAT_TIME,
7600                                                         (GstSeekFlags)GST_SEEK_FLAG_FLUSH,
7601                                                         GST_SEEK_TYPE_SET, cur_time,
7602                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7603                         if (event)
7604                                 __gst_send_event_to_sink(player, event);
7605
7606                         if (!MMPLAYER_IS_RTSP_STREAMING(player))
7607                                 __gst_pause(player, FALSE);
7608                 }
7609
7610                 /* rtsp streaming case, there is no sink after READY TO PAUSE state(no preroll state change).
7611                         that's why set position through property. */
7612                 if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
7613                         (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) &&
7614                         (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY) &&
7615                         (!player->videodec_linked) && (!player->audiodec_linked)) {
7616
7617                         g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "pending-start-position", pos_nsec, NULL);
7618                         LOGD("[%s] set position =%"GST_TIME_FORMAT,
7619                                         GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), GST_TIME_ARGS(pos_nsec));
7620                         player->doing_seek = FALSE;
7621                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
7622                 } else {
7623                         ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7624                                                         GST_FORMAT_TIME, seek_flags,
7625                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7626                 }
7627
7628                 if (!ret) {
7629                         LOGE("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
7630                         goto SEEK_ERROR;
7631                 }
7632         }
7633         break;
7634
7635         case MM_PLAYER_POS_FORMAT_PERCENT:
7636         {
7637                 LOGD("seeking to(%lu)%% \n", position);
7638
7639                 if (player->doing_seek) {
7640                         LOGD("not completed seek");
7641                         return MM_ERROR_PLAYER_DOING_SEEK;
7642                 }
7643
7644                 if (!internal_called)
7645                         player->doing_seek = TRUE;
7646
7647                 /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
7648                 pos_nsec = (gint64)((position * player->duration) / 100);
7649                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, player->playback_rate,
7650                                                 GST_FORMAT_TIME, seek_flags,
7651                                                 GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
7652                 if (!ret) {
7653                         LOGE("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%"G_GUINT64_FORMAT"]\n", dur_msec, position, pos_nsec);
7654                         goto SEEK_ERROR;
7655                 }
7656         }
7657         break;
7658
7659         default:
7660                 goto INVALID_ARGS;
7661         }
7662
7663         /* NOTE : store last seeking point to overcome some bad operation
7664           *     (returning zero when getting current position) of some elements
7665           */
7666         player->last_position = pos_nsec;
7667
7668         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
7669         if (player->playback_rate > 1.0)
7670                 _mmplayer_set_playspeed((MMHandleType)player, player->playback_rate, FALSE);
7671
7672         MMPLAYER_FLEAVE();
7673         return MM_ERROR_NONE;
7674
7675 PENDING:
7676         player->pending_seek.is_pending = TRUE;
7677         player->pending_seek.format = format;
7678         player->pending_seek.pos = position;
7679
7680         LOGW("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n",
7681                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
7682
7683         return MM_ERROR_NONE;
7684
7685 INVALID_ARGS:
7686         LOGE("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
7687         return MM_ERROR_INVALID_ARGUMENT;
7688
7689 SEEK_ERROR:
7690         player->doing_seek = FALSE;
7691         return MM_ERROR_PLAYER_SEEK;
7692 }
7693
7694 #define TRICKPLAY_OFFSET GST_MSECOND
7695
7696 static int
7697 __gst_get_position(mm_player_t* player, int format, unsigned long* position)
7698 {
7699         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7700         gint64 pos_msec = 0;
7701         gboolean ret = TRUE;
7702
7703         MMPLAYER_RETURN_VAL_IF_FAIL(player && position && player->pipeline && player->pipeline->mainbin,
7704                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7705
7706         current_state = MMPLAYER_CURRENT_STATE(player);
7707
7708         /* NOTE : query position except paused state to overcome some bad operation
7709          * please refer to below comments in details
7710          */
7711         if (current_state != MM_PLAYER_STATE_PAUSED)
7712                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
7713
7714         /* NOTE : get last point to overcome some bad operation of some elements
7715          *(returning zero when getting current position in paused state
7716          * and when failed to get postion during seeking
7717          */
7718         if ((current_state == MM_PLAYER_STATE_PAUSED) || (!ret)) {
7719                 LOGD("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_msec), ret, current_state);
7720
7721                 if (player->playback_rate < 0.0)
7722                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
7723                 else
7724                         pos_msec = player->last_position;
7725
7726                 if (!ret)
7727                         pos_msec = player->last_position;
7728                 else
7729                         player->last_position = pos_msec;
7730
7731                 LOGD("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
7732
7733         } else {
7734                 if (player->duration > 0 && pos_msec > player->duration)
7735                         pos_msec = player->duration;
7736
7737                 player->last_position = pos_msec;
7738         }
7739
7740         switch (format) {
7741         case MM_PLAYER_POS_FORMAT_TIME:
7742                 *position = GST_TIME_AS_MSECONDS(pos_msec);
7743                 break;
7744
7745         case MM_PLAYER_POS_FORMAT_PERCENT:
7746         {
7747                 if (player->duration <= 0) {
7748                         LOGD("duration is [%lld], so returning position 0\n", player->duration);
7749                         *position = 0;
7750                 } else {
7751                         LOGD("postion is [%lld] msec , duration is [%lld] msec", pos_msec, player->duration);
7752                         *position = pos_msec * 100 / player->duration;
7753                 }
7754                 break;
7755         }
7756         default:
7757                 return MM_ERROR_PLAYER_INTERNAL;
7758         }
7759
7760         return MM_ERROR_NONE;
7761 }
7762
7763
7764 static int __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
7765 {
7766 #define STREAMING_IS_FINISHED   0
7767 #define BUFFERING_MAX_PER       100
7768 #define DEFAULT_PER_VALUE       -1
7769 #define CHECK_PERCENT_VALUE(a, min, max)(((a) > (min)) ? (((a) < (max)) ? (a) : (max)) : (min))
7770
7771         MMPlayerGstElement *mainbin = NULL;
7772         gint start_per = DEFAULT_PER_VALUE, stop_per = DEFAULT_PER_VALUE;
7773         gint64 buffered_total = 0;
7774         unsigned long position = 0;
7775         gint buffered_sec = -1;
7776         GstBufferingMode mode = GST_BUFFERING_STREAM;
7777         gint64 content_size_time = player->duration;
7778         guint64 content_size_bytes = player->http_content_size;
7779
7780         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
7781                                                 player->pipeline &&
7782                                                 player->pipeline->mainbin,
7783                                                 MM_ERROR_PLAYER_NOT_INITIALIZED);
7784
7785         MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT);
7786
7787         *start_pos = 0;
7788         *stop_pos = 0;
7789
7790         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
7791                 /* and rtsp is not ready yet. */
7792                 LOGW("it's only used for http streaming case.\n");
7793                 return MM_ERROR_PLAYER_NO_OP;
7794         }
7795
7796         if (format != MM_PLAYER_POS_FORMAT_PERCENT) {
7797                 LOGW("Time format is not supported yet.\n");
7798                 return MM_ERROR_INVALID_ARGUMENT;
7799         }
7800
7801         if (content_size_time <= 0 || content_size_bytes <= 0) {
7802                 LOGW("there is no content size.");
7803                 return MM_ERROR_NONE;
7804         }
7805
7806         if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position) != MM_ERROR_NONE) {
7807                 LOGW("fail to get current position.");
7808                 return MM_ERROR_NONE;
7809         }
7810
7811         LOGD("pos %d ms, dur %d sec, len %"G_GUINT64_FORMAT" bytes",
7812                 position, (guint)(content_size_time/GST_SECOND), content_size_bytes);
7813
7814         mainbin = player->pipeline->mainbin;
7815         start_per = (gint)(floor(100 *(gdouble)(position*GST_MSECOND) / (gdouble)content_size_time));
7816
7817         if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
7818                 GstQuery *query = NULL;
7819                 gint byte_in_rate = 0, byte_out_rate = 0;
7820                 gint64 estimated_total = 0;
7821
7822                 query = gst_query_new_buffering(GST_FORMAT_BYTES);
7823                 if (!query || !gst_element_query(mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst, query)) {
7824                         LOGW("fail to get buffering query from queue2");
7825                         if (query)
7826                                 gst_query_unref(query);
7827                         return MM_ERROR_NONE;
7828                 }
7829
7830                 gst_query_parse_buffering_stats(query, &mode, &byte_in_rate, &byte_out_rate, NULL);
7831                 LOGD("mode %d, in_rate %d, out_rate %d", mode, byte_in_rate, byte_out_rate);
7832
7833                 if (mode == GST_BUFFERING_STREAM) {
7834                         /* using only queue in case of push mode(ts / mp3) */
7835                         if (gst_element_query_position(mainbin[MMPLAYER_M_SRC].gst,
7836                                 GST_FORMAT_BYTES, &buffered_total)) {
7837                                 LOGD("buffered_total %"G_GINT64_FORMAT, buffered_total);
7838                                 stop_per = 100 * buffered_total / content_size_bytes;
7839                         }
7840                 } else {
7841                         /* GST_BUFFERING_TIMESHIFT or GST_BUFFERING_DOWNLOAD */
7842                         guint idx = 0;
7843                         guint num_of_ranges = 0;
7844                         gint64 start_byte = 0, stop_byte = 0;
7845
7846                         gst_query_parse_buffering_range(query, NULL, NULL, NULL, &estimated_total);
7847                         if (estimated_total != STREAMING_IS_FINISHED) {
7848                                 /* buffered size info from queue2 */
7849                                 num_of_ranges = gst_query_get_n_buffering_ranges(query);
7850                                 for (idx = 0; idx < num_of_ranges; idx++) {
7851                                         gst_query_parse_nth_buffering_range(query, idx, &start_byte, &stop_byte);
7852                                         LOGD("range %d, %"G_GINT64_FORMAT" ~ %"G_GUINT64_FORMAT, idx, start_byte, stop_byte);
7853
7854                                         buffered_total += (stop_byte - start_byte);
7855                                 }
7856                         } else
7857                                 stop_per = BUFFERING_MAX_PER;
7858                 }
7859                 gst_query_unref(query);
7860         }
7861
7862         if (stop_per == DEFAULT_PER_VALUE) {
7863                 guint dur_sec = (guint)(content_size_time/GST_SECOND);
7864                 if (dur_sec > 0) {
7865                         guint avg_byterate = (guint)(content_size_bytes/dur_sec);
7866
7867                         /* buffered size info from multiqueue */
7868                         if (mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst) {
7869                                 guint curr_size_bytes = 0;
7870                                 g_object_get(G_OBJECT(mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst),
7871                                         "curr-size-bytes", &curr_size_bytes, NULL);
7872                                 LOGD("curr_size_bytes of multiqueue = %d", curr_size_bytes);
7873                                 buffered_total += curr_size_bytes;
7874                         }
7875
7876                         if (avg_byterate > 0)
7877                                 buffered_sec = (gint)(ceil((gdouble)buffered_total/(gdouble)avg_byterate));
7878                         else if (player->total_maximum_bitrate > 0)
7879                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_maximum_bitrate));
7880                         else if (player->total_bitrate > 0)
7881                                 buffered_sec = (gint)(ceil((gdouble)GET_BIT_FROM_BYTE(buffered_total)/(gdouble)player->total_bitrate));
7882
7883                         if (buffered_sec >= 0)
7884                                 stop_per = start_per +(gint)(ceil)(100*(gdouble)buffered_sec/(gdouble)dur_sec);
7885                 }
7886         }
7887
7888         *start_pos = CHECK_PERCENT_VALUE(start_per, 0, 100);
7889         *stop_pos = CHECK_PERCENT_VALUE(stop_per, *start_pos, 100);
7890
7891         LOGD("buffered info: %"G_GINT64_FORMAT" bytes, %d sec, per %lu~%lu\n",
7892                 buffered_total, buffered_sec, *start_pos, *stop_pos);
7893
7894         return MM_ERROR_NONE;
7895 }
7896
7897 static int
7898 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param)
7899 {
7900         MMPLAYER_FENTER();
7901
7902         if (!player) {
7903                 LOGW("set_message_callback is called with invalid player handle\n");
7904                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
7905         }
7906
7907         player->msg_cb = callback;
7908         player->msg_cb_param = user_param;
7909
7910         LOGD("msg_cb : %p     msg_cb_param : %p\n", callback, user_param);
7911
7912         MMPLAYER_FLEAVE();
7913
7914         return MM_ERROR_NONE;
7915 }
7916
7917 static int __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data)
7918 {
7919         int ret = MM_ERROR_PLAYER_INVALID_URI;
7920         char *path = NULL;
7921
7922         MMPLAYER_FENTER();
7923
7924         MMPLAYER_RETURN_VAL_IF_FAIL(uri , FALSE);
7925         MMPLAYER_RETURN_VAL_IF_FAIL(data , FALSE);
7926         MMPLAYER_RETURN_VAL_IF_FAIL((strlen(uri) <= MM_MAX_URL_LEN), FALSE);
7927
7928         memset(data, 0, sizeof(MMPlayerParseProfile));
7929
7930         if ((path = strstr(uri, "es_buff://"))) {
7931                 if (strlen(path)) {
7932                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7933                         data->uri_type = MM_PLAYER_URI_TYPE_MS_BUFF;
7934                         ret = MM_ERROR_NONE;
7935                 }
7936         } else if ((path = strstr(uri, "rtsp://")) || (path = strstr(uri, "rtsps://"))) {
7937                 if (strlen(path)) {
7938                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7939                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7940                         ret = MM_ERROR_NONE;
7941                 }
7942         } else if ((path = strstr(uri, "http://")) || (path = strstr(uri, "https://"))) {
7943                 if (strlen(path)) {
7944                         gchar *tmp = NULL;
7945                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7946                         tmp = g_ascii_strdown(uri, strlen(uri));
7947
7948                         if (tmp && (g_str_has_suffix(tmp, ".ism/manifest") || g_str_has_suffix(tmp, ".isml/manifest")))
7949                                 data->uri_type = MM_PLAYER_URI_TYPE_SS;
7950                         else
7951                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
7952
7953                         ret = MM_ERROR_NONE;
7954                         g_free(tmp);
7955                 }
7956         } else if ((path = strstr(uri, "rtspu://"))) {
7957                 if (strlen(path)) {
7958                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7959                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7960                         ret = MM_ERROR_NONE;
7961                 }
7962         } else if ((path = strstr(uri, "rtspr://"))) {
7963                 strncpy(data->uri, path, MM_MAX_URL_LEN-1);
7964                 char *separater = strstr(path, "*");
7965
7966                 if (separater) {
7967                         int urgent_len = 0;
7968                         char *urgent = separater + strlen("*");
7969
7970                         if ((urgent_len = strlen(urgent))) {
7971                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
7972                                 strncpy(data->urgent, urgent, MM_MAX_FILENAME_LEN-1);
7973                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
7974                                 ret = MM_ERROR_NONE;
7975                         }
7976                 }
7977         } else if ((path = strstr(uri, "mms://"))) {
7978                 if (strlen(path)) {
7979                         strncpy(data->uri, uri, MM_MAX_URL_LEN-1);
7980                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
7981                         ret = MM_ERROR_NONE;
7982                 }
7983         } else if ((path = strstr(uri, "mem://"))) {
7984                 if (strlen(path)) {
7985                         int mem_size = 0;
7986                         char *buffer = NULL;
7987                         char *seperator = strchr(path, ',');
7988                         char ext[100] = {0,}, size[100] = {0,};
7989
7990                         if (seperator) {
7991                                 if ((buffer = strstr(path, "ext="))) {
7992                                         buffer += strlen("ext=");
7993
7994                                         if (strlen(buffer)) {
7995                                                 strncpy(ext, buffer, 99);
7996
7997                                                 if ((seperator = strchr(ext, ','))
7998                                                         || (seperator = strchr(ext, ' '))
7999                                                         || (seperator = strchr(ext, '\0'))) {
8000                                                         seperator[0] = '\0';
8001                                                 }
8002                                         }
8003                                 }
8004
8005                                 if ((buffer = strstr(path, "size="))) {
8006                                         buffer += strlen("size=");
8007
8008                                         if (strlen(buffer) > 0) {
8009                                                 strncpy(size, buffer, 99);
8010
8011                                                 if ((seperator = strchr(size, ','))
8012                                                         || (seperator = strchr(size, ' '))
8013                                                         || (seperator = strchr(size, '\0'))) {
8014                                                         seperator[0] = '\0';
8015                                                 }
8016
8017                                                 mem_size = atoi(size);
8018                                         }
8019                                 }
8020                         }
8021
8022                         LOGD("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
8023                         if (mem_size && param) {
8024                                 if (data->input_mem.buf)
8025                                         free(data->input_mem.buf);
8026                                 data->input_mem.buf = malloc(mem_size);
8027
8028                                 if (data->input_mem.buf) {
8029                                         memcpy(data->input_mem.buf, param, mem_size);
8030                                         data->input_mem.len = mem_size;
8031                                         ret = MM_ERROR_NONE;
8032                                 } else {
8033                                         LOGE("failed to alloc mem %d", mem_size);
8034                                         ret = MM_ERROR_PLAYER_INTERNAL;
8035                                 }
8036
8037                                 data->input_mem.offset = 0;
8038                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
8039                         }
8040                 }
8041         } else {
8042                 gchar *location = NULL;
8043                 GError *err = NULL;
8044
8045                 if ((path = strstr(uri, "file://"))) {
8046
8047                         location = g_filename_from_uri(uri, NULL, &err);
8048
8049                         if (!location || (err != NULL)) {
8050                           LOGE("Invalid URI '%s' for filesrc: %s", path,
8051                                  (err != NULL) ? err->message : "unknown error");
8052
8053                           if (err) g_error_free(err);
8054                           if (location) g_free(location);
8055
8056                           data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8057                           goto exit;
8058                         }
8059
8060                         LOGD("path from uri: %s", location);
8061                 }
8062
8063                 path = (location != NULL) ? (location) : ((char*)uri);
8064                 int file_stat = MM_ERROR_NONE;
8065
8066                 file_stat = util_exist_file_path(path);
8067
8068                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
8069                 if (file_stat == MM_ERROR_NONE) {
8070                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", path);
8071
8072                         if (util_is_sdp_file(path)) {
8073                                 LOGD("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
8074                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
8075                         } else {
8076                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
8077                         }
8078                         ret = MM_ERROR_NONE;
8079                 } else if (file_stat == MM_ERROR_PLAYER_PERMISSION_DENIED) {
8080                         data->uri_type = MM_PLAYER_URI_TYPE_NO_PERMISSION;
8081                 } else {
8082                         LOGE("invalid uri, could not play..\n");
8083                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
8084                 }
8085
8086                 if (location) g_free(location);
8087         }
8088
8089 exit:
8090         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE)
8091                 ret = MM_ERROR_PLAYER_FILE_NOT_FOUND;
8092         else if (data->uri_type == MM_PLAYER_URI_TYPE_NO_PERMISSION)
8093                 ret = MM_ERROR_PLAYER_PERMISSION_DENIED;
8094
8095         /* dump parse result */
8096         SECURE_LOGW("incomming uri : %s\n", uri);
8097         LOGD("uri_type : %d, mem : %p, mem_size : %d, urgent : %s\n",
8098                 data->uri_type, data->input_mem.buf, data->input_mem.len, data->urgent);
8099
8100         MMPLAYER_FLEAVE();
8101
8102         return ret;
8103 }
8104
8105 gboolean
8106 __mmplayer_can_do_interrupt(mm_player_t *player)
8107 {
8108         if (!player || !player->pipeline || !player->attrs) {
8109                 LOGW("not initialized");
8110                 goto FAILED;
8111         }
8112
8113         if (player->set_mode.pcm_extraction) {
8114                 LOGW("leave right now, %d", player->set_mode.pcm_extraction);
8115                 goto FAILED;
8116         }
8117
8118         /* check if seeking */
8119         if (player->doing_seek) {
8120                 MMMessageParamType msg_param;
8121                 memset(&msg_param, 0, sizeof(MMMessageParamType));
8122                 msg_param.code = MM_ERROR_PLAYER_SEEK;
8123                 player->doing_seek = FALSE;
8124                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
8125                 goto FAILED;
8126         }
8127
8128         /* check other thread */
8129         if (!MMPLAYER_CMD_TRYLOCK(player)) {
8130                 LOGW("locked already, cmd state : %d", player->cmd);
8131
8132                 /* check application command */
8133                 if (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) {
8134                         LOGW("playing.. should wait cmd lock then, will be interrupted");
8135
8136                         /* lock will be released at mrp_resource_release_cb() */
8137                         MMPLAYER_CMD_LOCK(player);
8138                         goto INTERRUPT;
8139                 }
8140                 LOGW("nothing to do");
8141                 goto FAILED;
8142         } else {
8143                 LOGW("can interrupt immediately");
8144                 goto INTERRUPT;
8145         }
8146
8147 FAILED:    /* with CMD UNLOCKED */
8148         return FALSE;
8149
8150 INTERRUPT: /* with CMD LOCKED, released at mrp_resource_release_cb() */
8151         return TRUE;
8152 }
8153
8154 static int
8155 __resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h res,
8156                 void *user_data)
8157 {
8158         mm_player_t *player = NULL;
8159
8160         MMPLAYER_FENTER();
8161
8162         if (user_data == NULL) {
8163                 LOGE("- user_data is null\n");
8164                 return FALSE;
8165         }
8166         player = (mm_player_t *)user_data;
8167
8168         /* do something to release resource here.
8169          * player stop and interrupt forwarding */
8170         if (!__mmplayer_can_do_interrupt(player)) {
8171                 LOGW("no need to interrupt, so leave");
8172         } else {
8173                 MMMessageParamType msg = {0, };
8174                 unsigned long pos = 0;
8175
8176                 player->interrupted_by_resource = TRUE;
8177
8178                 /* get last play position */
8179                 if (_mmplayer_get_position((MMHandleType)player, MM_PLAYER_POS_FORMAT_TIME, &pos) != MM_ERROR_NONE) {
8180                         LOGW("failed to get play position.");
8181                 } else {
8182                         msg.union_type = MM_MSG_UNION_TIME;
8183                         msg.time.elapsed = (unsigned int)pos;
8184                         MMPLAYER_POST_MSG(player, MM_MESSAGE_PLAY_POSITION, &msg);
8185                 }
8186                 LOGD("video resource conflict so, resource will be freed by unrealizing");
8187                 if (_mmplayer_unrealize((MMHandleType)player))
8188                         LOGW("failed to unrealize");
8189
8190                 /* lock is called in __mmplayer_can_do_interrupt() */
8191                 MMPLAYER_CMD_UNLOCK(player);
8192         }
8193
8194         if (res == player->video_overlay_resource)
8195                 player->video_overlay_resource = FALSE;
8196         else
8197                 player->video_decoder_resource = FALSE;
8198
8199         MMPLAYER_FLEAVE();
8200
8201         return FALSE;
8202 }
8203
8204 int
8205 _mmplayer_create_player(MMHandleType handle)
8206 {
8207         int ret = MM_ERROR_PLAYER_INTERNAL;
8208         bool enabled = false;
8209
8210         mm_player_t* player = MM_PLAYER_CAST(handle);
8211
8212         MMPLAYER_FENTER();
8213
8214         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8215
8216         /* initialize player state */
8217         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
8218         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
8219         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
8220         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
8221
8222         /* check current state */
8223         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_CREATE);
8224
8225         /* construct attributes */
8226         player->attrs = _mmplayer_construct_attribute(handle);
8227
8228         if (!player->attrs) {
8229                 LOGE("Failed to construct attributes\n");
8230                 return ret;
8231         }
8232
8233         /* initialize gstreamer with configured parameter */
8234         if (!__mmplayer_init_gstreamer(player)) {
8235                 LOGE("Initializing gstreamer failed\n");
8236                 _mmplayer_deconstruct_attribute(handle);
8237                 return ret;
8238         }
8239
8240         /* create lock. note that g_tread_init() has already called in gst_init() */
8241         g_mutex_init(&player->fsink_lock);
8242
8243         /* create update tag lock */
8244         g_mutex_init(&player->update_tag_lock);
8245
8246         /* create next play mutex */
8247         g_mutex_init(&player->next_play_thread_mutex);
8248
8249         /* create next play cond */
8250         g_cond_init(&player->next_play_thread_cond);
8251
8252         /* create next play thread */
8253         player->next_play_thread =
8254                 g_thread_try_new("next_play_thread", __mmplayer_next_play_thread, (gpointer)player, NULL);
8255         if (!player->next_play_thread) {
8256                 LOGE("failed to create next play thread");
8257                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8258                 g_mutex_clear(&player->next_play_thread_mutex);
8259                 g_cond_clear(&player->next_play_thread_cond);
8260                 goto ERROR;
8261         }
8262
8263         player->bus_msg_q = g_queue_new();
8264         if (!player->bus_msg_q) {
8265                 LOGE("failed to create queue for bus_msg");
8266                 ret = MM_ERROR_PLAYER_RESOURCE_LIMIT;
8267                 goto ERROR;
8268         }
8269
8270         ret = _mmplayer_initialize_video_capture(player);
8271         if (ret != MM_ERROR_NONE) {
8272                 LOGE("failed to initialize video capture\n");
8273                 goto ERROR;
8274         }
8275
8276         /* initialize resource manager */
8277         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_create(
8278                         MM_RESOURCE_MANAGER_APP_CLASS_MEDIA, __resource_release_cb, player,
8279                         &player->resource_manager)) {
8280                 LOGE("failed to initialize resource manager\n");
8281                 goto ERROR;
8282         }
8283
8284         if (MMPLAYER_IS_HTTP_PD(player)) {
8285                 player->pd_downloader = NULL;
8286                 player->pd_file_save_path = NULL;
8287         }
8288
8289         /* create video bo lock and cond */
8290         g_mutex_init(&player->video_bo_mutex);
8291         g_cond_init(&player->video_bo_cond);
8292
8293         /* create media stream callback mutex */
8294         g_mutex_init(&player->media_stream_cb_lock);
8295
8296         /* create subtitle info lock and cond */
8297         g_mutex_init(&player->subtitle_info_mutex);
8298         g_cond_init(&player->subtitle_info_cond);
8299
8300         player->streaming_type = STREAMING_SERVICE_NONE;
8301
8302         /* give default value of audio effect setting */
8303         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
8304         player->sound.rg_enable = false;
8305         player->playback_rate = DEFAULT_PLAYBACK_RATE;
8306
8307         player->play_subtitle = FALSE;
8308         player->use_deinterleave = FALSE;
8309         player->max_audio_channels = 0;
8310         player->video_share_api_delta = 0;
8311         player->video_share_clock_delta = 0;
8312         player->has_closed_caption = FALSE;
8313         player->video_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8314         player->video_extra_num_buffers = DEFAULT_NUM_OF_V_OUT_BUFFER;
8315         player->pending_resume = FALSE;
8316         if (player->ini.dump_element_keyword[0][0] == '\0')
8317                 player->ini.set_dump_element_flag = FALSE;
8318         else
8319                 player->ini.set_dump_element_flag = TRUE;
8320
8321         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8322         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8323         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
8324
8325         /* Set video360 settings to their defaults for just-created player.
8326          * */
8327
8328         player->is_360_feature_enabled = FALSE;
8329         if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(FEATURE_NAME_SPHERICAL_VIDEO, &enabled)) {
8330                 LOGI("spherical feature info: %d", enabled);
8331                 if (enabled)
8332                         player->is_360_feature_enabled = TRUE;
8333         } else {
8334                 LOGE("failed to get spherical feature info");
8335         }
8336
8337         player->is_content_spherical = FALSE;
8338         player->is_video360_enabled = TRUE;
8339         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
8340         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
8341         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
8342         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
8343         player->video360_zoom = 1.0f;
8344         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
8345         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
8346
8347         /* set player state to null */
8348         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8349         MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_NULL);
8350
8351         return MM_ERROR_NONE;
8352
8353 ERROR:
8354         /* free lock */
8355         g_mutex_clear(&player->fsink_lock);
8356
8357         /* free update tag lock */
8358         g_mutex_clear(&player->update_tag_lock);
8359
8360         g_queue_free(player->bus_msg_q);
8361
8362         /* free next play thread */
8363         if (player->next_play_thread) {
8364                 MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
8365                 player->next_play_thread_exit = TRUE;
8366                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8367                 MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
8368
8369                 g_thread_join(player->next_play_thread);
8370                 player->next_play_thread = NULL;
8371
8372                 g_mutex_clear(&player->next_play_thread_mutex);
8373                 g_cond_clear(&player->next_play_thread_cond);
8374         }
8375
8376         /* release attributes */
8377         _mmplayer_deconstruct_attribute(handle);
8378
8379         MMPLAYER_FLEAVE();
8380
8381         return ret;
8382 }
8383
8384 static gboolean
8385 __mmplayer_init_gstreamer(mm_player_t* player)
8386 {
8387         static gboolean initialized = FALSE;
8388         static const int max_argc = 50;
8389         gint* argc = NULL;
8390         gchar** argv = NULL;
8391         gchar** argv2 = NULL;
8392         GError *err = NULL;
8393         int i = 0;
8394         int arg_count = 0;
8395
8396         if (initialized) {
8397                 LOGD("gstreamer already initialized.\n");
8398                 return TRUE;
8399         }
8400
8401         /* alloc */
8402         argc = malloc(sizeof(int));
8403         argv = malloc(sizeof(gchar*) * max_argc);
8404         argv2 = malloc(sizeof(gchar*) * max_argc);
8405
8406         if (!argc || !argv || !argv2)
8407                 goto ERROR;
8408
8409         memset(argv, 0, sizeof(gchar*) * max_argc);
8410         memset(argv2, 0, sizeof(gchar*) * max_argc);
8411
8412         /* add initial */
8413         *argc = 1;
8414         argv[0] = g_strdup("mmplayer");
8415
8416         /* add gst_param */
8417         for (i = 0; i < 5; i++) {
8418                 /* FIXIT : num of param is now fixed to 5. make it dynamic */
8419                 if (strlen(player->ini.gst_param[i]) > 0) {
8420                         argv[*argc] = g_strdup(player->ini.gst_param[i]);
8421                         (*argc)++;
8422                 }
8423         }
8424
8425         /* we would not do fork for scanning plugins */
8426         argv[*argc] = g_strdup("--gst-disable-registry-fork");
8427         (*argc)++;
8428
8429         /* check disable registry scan */
8430         if (player->ini.skip_rescan) {
8431                 argv[*argc] = g_strdup("--gst-disable-registry-update");
8432                 (*argc)++;
8433         }
8434
8435         /* check disable segtrap */
8436         if (player->ini.disable_segtrap) {
8437                 argv[*argc] = g_strdup("--gst-disable-segtrap");
8438                 (*argc)++;
8439         }
8440
8441         LOGD("initializing gstreamer with following parameter\n");
8442         LOGD("argc : %d\n", *argc);
8443         arg_count = *argc;
8444
8445         for (i = 0; i < arg_count; i++) {
8446                 argv2[i] = argv[i];
8447                 LOGD("argv[%d] : %s\n", i, argv2[i]);
8448         }
8449
8450         /* initializing gstreamer */
8451         if (!gst_init_check(argc, &argv, &err)) {
8452                 LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
8453                 if (err)
8454                         g_error_free(err);
8455
8456                 goto ERROR;
8457         }
8458         /* release */
8459         for (i = 0; i < arg_count; i++) {
8460                 //LOGD("release - argv[%d] : %s\n", i, argv2[i]);
8461                 MMPLAYER_FREEIF(argv2[i]);
8462         }
8463
8464         MMPLAYER_FREEIF(argv);
8465         MMPLAYER_FREEIF(argv2);
8466         MMPLAYER_FREEIF(argc);
8467
8468         /* done */
8469         initialized = TRUE;
8470
8471         return TRUE;
8472
8473 ERROR:
8474
8475         /* release */
8476         for (i = 0; i < arg_count; i++) {
8477                 LOGD("free[%d] : %s\n", i, argv2[i]);
8478                 MMPLAYER_FREEIF(argv2[i]);
8479         }
8480
8481         MMPLAYER_FREEIF(argv);
8482         MMPLAYER_FREEIF(argv2);
8483         MMPLAYER_FREEIF(argc);
8484
8485         return FALSE;
8486 }
8487
8488 int
8489 __mmplayer_destroy_streaming_ext(mm_player_t* player)
8490 {
8491         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8492
8493         if (player->pd_downloader || MMPLAYER_IS_HTTP_PD(player)) {
8494                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
8495                 MMPLAYER_FREEIF(player->pd_file_save_path);
8496         }
8497
8498         return MM_ERROR_NONE;
8499 }
8500
8501 static void
8502 __mmplayer_check_async_state_transition(mm_player_t* player)
8503 {
8504         GstState element_state = GST_STATE_VOID_PENDING;
8505         GstState element_pending_state = GST_STATE_VOID_PENDING;
8506         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
8507         GstElement * element = NULL;
8508         gboolean async = FALSE;
8509
8510         /* check player handle */
8511         MMPLAYER_RETURN_IF_FAIL(player &&
8512                                                 player->pipeline &&
8513                                                 player->pipeline->mainbin &&
8514                                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
8515
8516         if (player->attrs)
8517                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
8518
8519         if (!MMPLAYER_IS_MS_BUFF_SRC(player) && (async == FALSE)) {
8520                 LOGD("don't need to check the pipeline state");
8521                 return;
8522         }
8523
8524         MMPLAYER_PRINT_STATE(player);
8525
8526         /* wait for state transition */
8527         element = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
8528         ret = gst_element_get_state(element, &element_state, &element_pending_state, 1*GST_SECOND);
8529
8530         if (ret == GST_STATE_CHANGE_FAILURE) {
8531                 LOGE(" [%s] state : %s   pending : %s \n",
8532                         GST_ELEMENT_NAME(element),
8533                         gst_element_state_get_name(element_state),
8534                         gst_element_state_get_name(element_pending_state));
8535
8536                 /* dump state of all element */
8537                 __mmplayer_dump_pipeline_state(player);
8538
8539                 return;
8540         }
8541
8542         LOGD("[%s] element state has changed\n", GST_ELEMENT_NAME(element));
8543         return;
8544 }
8545
8546 int
8547 _mmplayer_destroy(MMHandleType handle)
8548 {
8549         mm_player_t* player = MM_PLAYER_CAST(handle);
8550
8551         MMPLAYER_FENTER();
8552
8553         /* check player handle */
8554         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8555
8556         /* destroy can called at anytime */
8557         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_DESTROY);
8558
8559         /* check async state transition */
8560         __mmplayer_check_async_state_transition(player);
8561
8562         __mmplayer_destroy_streaming_ext(player);
8563
8564         /* release next play thread */
8565         if (player->next_play_thread) {
8566                 MMPLAYER_NEXT_PLAY_THREAD_LOCK(player);
8567                 player->next_play_thread_exit = TRUE;
8568                 MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
8569                 MMPLAYER_NEXT_PLAY_THREAD_UNLOCK(player);
8570
8571                 LOGD("waitting for next play thread exit\n");
8572                 g_thread_join(player->next_play_thread);
8573                 g_mutex_clear(&player->next_play_thread_mutex);
8574                 g_cond_clear(&player->next_play_thread_cond);
8575                 LOGD("next play thread released\n");
8576         }
8577
8578         _mmplayer_release_video_capture(player);
8579
8580         /* de-initialize resource manager */
8581         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_destroy(
8582                         player->resource_manager))
8583                 LOGE("failed to deinitialize resource manager\n");
8584
8585         /* release pipeline */
8586         if (MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline(player)) {
8587                 LOGE("failed to destory pipeline\n");
8588                 return MM_ERROR_PLAYER_INTERNAL;
8589         }
8590
8591         g_queue_free(player->bus_msg_q);
8592
8593         /* release subtitle info lock and cond */
8594         g_mutex_clear(&player->subtitle_info_mutex);
8595         g_cond_clear(&player->subtitle_info_cond);
8596
8597         __mmplayer_release_dump_list(player->dump_list);
8598
8599         /* release miscellaneous information */
8600         __mmplayer_release_misc(player);
8601
8602         /* release miscellaneous information.
8603            these info needs to be released after pipeline is destroyed. */
8604         __mmplayer_release_misc_post(player);
8605
8606         /* release attributes */
8607         _mmplayer_deconstruct_attribute(handle);
8608
8609         /* release lock */
8610         g_mutex_clear(&player->fsink_lock);
8611
8612         /* release lock */
8613         g_mutex_clear(&player->update_tag_lock);
8614
8615         /* release video bo lock and cond */
8616         g_mutex_clear(&player->video_bo_mutex);
8617         g_cond_clear(&player->video_bo_cond);
8618
8619         /* release media stream callback lock */
8620         g_mutex_clear(&player->media_stream_cb_lock);
8621
8622         MMPLAYER_FLEAVE();
8623
8624         return MM_ERROR_NONE;
8625 }
8626
8627 int
8628 __mmplayer_realize_streaming_ext(mm_player_t* player)
8629 {
8630         int ret = MM_ERROR_NONE;
8631
8632         MMPLAYER_FENTER();
8633         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8634
8635         if (MMPLAYER_IS_HTTP_PD(player)) {
8636                 gboolean bret = FALSE;
8637
8638                 player->pd_downloader = _mmplayer_create_pd_downloader();
8639                 if (!player->pd_downloader) {
8640                         LOGE("Unable to create PD Downloader...");
8641                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
8642                 }
8643
8644                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
8645
8646                 if (FALSE == bret) {
8647                         LOGE("Unable to create PD Downloader...");
8648                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
8649                 }
8650         }
8651
8652         MMPLAYER_FLEAVE();
8653         return ret;
8654 }
8655
8656 int
8657 _mmplayer_realize(MMHandleType hplayer)
8658 {
8659         mm_player_t* player = (mm_player_t*)hplayer;
8660         char *uri = NULL;
8661         void *param = NULL;
8662         MMHandleType attrs = 0;
8663         int ret = MM_ERROR_NONE;
8664
8665         MMPLAYER_FENTER();
8666
8667         /* check player handle */
8668         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED)
8669
8670         /* check current state */
8671         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_REALIZE);
8672
8673         attrs = MMPLAYER_GET_ATTRS(player);
8674         if (!attrs) {
8675                 LOGE("fail to get attributes.\n");
8676                 return MM_ERROR_PLAYER_INTERNAL;
8677         }
8678         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
8679         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
8680
8681         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_NONE) {
8682                 ret = __mmfplayer_parse_profile((const char*)uri, param, &player->profile);
8683
8684                 if (ret != MM_ERROR_NONE) {
8685                         LOGE("failed to parse profile\n");
8686                         return ret;
8687                 }
8688         }
8689
8690         if (uri && (strstr(uri, "es_buff://"))) {
8691                 if (strstr(uri, "es_buff://push_mode"))
8692                         player->es_player_push_mode = TRUE;
8693                 else
8694                         player->es_player_push_mode = FALSE;
8695         }
8696
8697         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS) {
8698                 LOGW("mms protocol is not supported format.\n");
8699                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
8700         }
8701
8702         if (MMPLAYER_IS_STREAMING(player))
8703                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.live_state_change_timeout;
8704         else
8705                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = player->ini.localplayback_state_change_timeout;
8706
8707         player->smooth_streaming = FALSE;
8708         player->videodec_linked  = 0;
8709         player->videosink_linked = 0;
8710         player->audiodec_linked  = 0;
8711         player->audiosink_linked = 0;
8712         player->textsink_linked = 0;
8713         player->is_external_subtitle_present = FALSE;
8714         player->is_external_subtitle_added_now = FALSE;
8715         /* set the subtitle ON default */
8716         player->is_subtitle_off = FALSE;
8717
8718         /* realize pipeline */
8719         ret = __gst_realize(player);
8720         if (ret != MM_ERROR_NONE)
8721                 LOGE("fail to realize the player.\n");
8722         else
8723                 ret = __mmplayer_realize_streaming_ext(player);
8724
8725         player->bus_msg_timeout = PLAYER_BUS_MSG_PREPARE_TIMEOUT;
8726         MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
8727
8728         MMPLAYER_FLEAVE();
8729
8730         return ret;
8731 }
8732
8733 int
8734 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
8735 {
8736         MMPLAYER_FENTER();
8737         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8738
8739         /* destroy can called at anytime */
8740         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
8741                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
8742
8743         MMPLAYER_FLEAVE();
8744         return MM_ERROR_NONE;
8745 }
8746
8747 int
8748 _mmplayer_unrealize(MMHandleType hplayer)
8749 {
8750         mm_player_t* player = (mm_player_t*)hplayer;
8751         int ret = MM_ERROR_NONE;
8752
8753         MMPLAYER_FENTER();
8754
8755         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8756
8757         MMPLAYER_CMD_UNLOCK(player);
8758         /* destroy the gst bus msg thread which is created during realize.
8759            this funct have to be called before getting cmd lock. */
8760         _mmplayer_bus_msg_thread_destroy(player);
8761         MMPLAYER_CMD_LOCK(player);
8762
8763         /* check current state */
8764         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_UNREALIZE);
8765
8766         /* check async state transition */
8767         __mmplayer_check_async_state_transition(player);
8768
8769         __mmplayer_unrealize_streaming_ext(player);
8770
8771         /* unrealize pipeline */
8772         ret = __gst_unrealize(player);
8773
8774         /* set asm stop if success */
8775         if (MM_ERROR_NONE == ret) {
8776                 if (!player->interrupted_by_resource) {
8777                         if (player->video_decoder_resource != NULL) {
8778                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
8779                                                 player->video_decoder_resource);
8780                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8781                                         LOGE("failed to mark decoder resource for release, ret(0x%x)\n", ret);
8782                                 else
8783                                         player->video_decoder_resource = NULL;
8784                         }
8785
8786                         if (player->video_overlay_resource != NULL) {
8787                                 ret = mm_resource_manager_mark_for_release(player->resource_manager,
8788                                                 player->video_overlay_resource);
8789                                 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8790                                         LOGE("failed to mark overlay resource for release, ret(0x%x)\n", ret);
8791                                 else
8792                                         player->video_overlay_resource = NULL;
8793                         }
8794
8795                         ret = mm_resource_manager_commit(player->resource_manager);
8796                         if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
8797                                 LOGE("failed to commit resource releases, ret(0x%x)\n", ret);
8798                 }
8799         } else
8800                 LOGE("failed and don't change asm state to stop");
8801
8802         MMPLAYER_FLEAVE();
8803
8804         return ret;
8805 }
8806
8807 int
8808 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param)
8809 {
8810         mm_player_t* player = (mm_player_t*)hplayer;
8811
8812         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8813
8814         return __gst_set_message_callback(player, callback, user_param);
8815 }
8816
8817 int
8818 _mmplayer_get_state(MMHandleType hplayer, int* state)
8819 {
8820         mm_player_t *player = (mm_player_t*)hplayer;
8821
8822         MMPLAYER_RETURN_VAL_IF_FAIL(state, MM_ERROR_INVALID_ARGUMENT);
8823
8824         *state = MMPLAYER_CURRENT_STATE(player);
8825
8826         return MM_ERROR_NONE;
8827 }
8828
8829
8830 int
8831 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume)
8832 {
8833         mm_player_t* player = (mm_player_t*) hplayer;
8834         GstElement* vol_element = NULL;
8835         int i = 0;
8836
8837         MMPLAYER_FENTER();
8838
8839         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8840
8841         LOGD("volume [L]=%f:[R]=%f\n",
8842                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
8843
8844         /* invalid factor range or not */
8845         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++) {
8846                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
8847                         LOGE("Invalid factor!(valid factor:0~1.0)\n");
8848                         return MM_ERROR_INVALID_ARGUMENT;
8849                 }
8850         }
8851
8852         /* not support to set other value into each channel */
8853         if ((volume.level[MM_VOLUME_CHANNEL_LEFT] != volume.level[MM_VOLUME_CHANNEL_RIGHT]))
8854                 return MM_ERROR_INVALID_ARGUMENT;
8855
8856         /* Save volume to handle. Currently the first array element will be saved. */
8857         player->sound.volume = volume.level[MM_VOLUME_CHANNEL_LEFT];
8858
8859         /* check pipeline handle */
8860         if (!player->pipeline || !player->pipeline->audiobin) {
8861                 LOGD("audiobin is not created yet\n");
8862                 LOGD("but, current stored volume will be set when it's created.\n");
8863
8864                 /* NOTE : stored volume will be used in create_audiobin
8865                  * returning MM_ERROR_NONE here makes application to able to
8866                  * set volume at anytime.
8867                  */
8868                 return MM_ERROR_NONE;
8869         }
8870
8871         /* setting volume to volume element */
8872         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
8873
8874         if (vol_element) {
8875                 LOGD("volume is set [%f]\n", player->sound.volume);
8876                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
8877         }
8878
8879         MMPLAYER_FLEAVE();
8880
8881         return MM_ERROR_NONE;
8882 }
8883
8884
8885 int
8886 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
8887 {
8888         mm_player_t* player = (mm_player_t*) hplayer;
8889         int i = 0;
8890
8891         MMPLAYER_FENTER();
8892
8893         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8894         MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
8895
8896         /* returning stored volume */
8897         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
8898                 volume->level[i] = player->sound.volume;
8899
8900         MMPLAYER_FLEAVE();
8901
8902         return MM_ERROR_NONE;
8903 }
8904
8905 int
8906 _mmplayer_set_mute(MMHandleType hplayer, int mute)
8907 {
8908         mm_player_t* player = (mm_player_t*) hplayer;
8909         GstElement* vol_element = NULL;
8910
8911         MMPLAYER_FENTER();
8912
8913         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8914
8915         /* mute value shoud 0 or 1 */
8916         if (mute != 0 && mute != 1) {
8917                 LOGE("bad mute value\n");
8918
8919                 /* FIXIT : definitly, we need _BAD_PARAM error code */
8920                 return MM_ERROR_INVALID_ARGUMENT;
8921         }
8922
8923         player->sound.mute = mute;
8924
8925         /* just hold mute value if pipeline is not ready */
8926         if (!player->pipeline || !player->pipeline->audiobin) {
8927                 LOGD("pipeline is not ready. holding mute value\n");
8928                 return MM_ERROR_NONE;
8929         }
8930
8931         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
8932
8933         /* NOTE : volume will only created when the bt is enabled */
8934         if (vol_element) {
8935                 LOGD("mute : %d\n", mute);
8936                 g_object_set(vol_element, "mute", mute, NULL);
8937         } else
8938                 LOGD("volume elemnet is not created. using volume in audiosink\n");
8939
8940         MMPLAYER_FLEAVE();
8941
8942         return MM_ERROR_NONE;
8943 }
8944
8945 int
8946 _mmplayer_get_mute(MMHandleType hplayer, int* pmute)
8947 {
8948         mm_player_t* player = (mm_player_t*) hplayer;
8949
8950         MMPLAYER_FENTER();
8951
8952         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8953         MMPLAYER_RETURN_VAL_IF_FAIL(pmute, MM_ERROR_INVALID_ARGUMENT);
8954
8955         /* just hold mute value if pipeline is not ready */
8956         if (!player->pipeline || !player->pipeline->audiobin) {
8957                 LOGD("pipeline is not ready. returning stored value\n");
8958                 *pmute = player->sound.mute;
8959                 return MM_ERROR_NONE;
8960         }
8961
8962         *pmute = player->sound.mute;
8963
8964         MMPLAYER_FLEAVE();
8965
8966         return MM_ERROR_NONE;
8967 }
8968
8969 int
8970 _mmplayer_set_videostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
8971 {
8972         mm_player_t* player = (mm_player_t*) hplayer;
8973
8974         MMPLAYER_FENTER();
8975
8976         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8977
8978         player->video_stream_changed_cb = callback;
8979         player->video_stream_changed_cb_user_param = user_param;
8980         LOGD("Handle value is %p : %p\n", player, player->video_stream_changed_cb);
8981
8982         MMPLAYER_FLEAVE();
8983
8984         return MM_ERROR_NONE;
8985 }
8986
8987 int
8988 _mmplayer_set_audiostream_changed_cb(MMHandleType hplayer, mm_player_stream_changed_callback callback, void *user_param)
8989 {
8990         mm_player_t* player = (mm_player_t*) hplayer;
8991
8992         MMPLAYER_FENTER();
8993
8994         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
8995
8996         player->audio_stream_changed_cb = callback;
8997         player->audio_stream_changed_cb_user_param = user_param;
8998         LOGD("Handle value is %p : %p\n", player, player->audio_stream_changed_cb);
8999
9000         MMPLAYER_FLEAVE();
9001
9002         return MM_ERROR_NONE;
9003 }
9004
9005 int
9006 _mmplayer_set_audiostream_cb_ex(MMHandleType hplayer, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param)
9007 {
9008         mm_player_t* player = (mm_player_t*) hplayer;
9009
9010         MMPLAYER_FENTER();
9011
9012         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9013
9014         player->audio_stream_render_cb_ex = callback;
9015         player->audio_stream_cb_user_param = user_param;
9016         player->audio_stream_sink_sync = sync;
9017         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);
9018
9019         MMPLAYER_FLEAVE();
9020
9021         return MM_ERROR_NONE;
9022 }
9023
9024 int
9025 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param)
9026 {
9027         mm_player_t* player = (mm_player_t*) hplayer;
9028
9029         MMPLAYER_FENTER();
9030
9031         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9032
9033         if (callback && !player->bufmgr)
9034                 player->bufmgr = tbm_bufmgr_init(-1);
9035
9036         player->set_mode.media_packet_video_stream = (callback) ? TRUE : FALSE;
9037         player->video_stream_cb = callback;
9038         player->video_stream_cb_user_param = user_param;
9039
9040         LOGD("Stream cb Handle value is %p : %p, enable:%d\n", player, player->video_stream_cb, player->set_mode.media_packet_video_stream);
9041
9042         MMPLAYER_FLEAVE();
9043
9044         return MM_ERROR_NONE;
9045 }
9046
9047 int
9048 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param)
9049 {
9050         mm_player_t* player = (mm_player_t*) hplayer;
9051
9052         MMPLAYER_FENTER();
9053
9054         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9055
9056         player->audio_stream_cb = callback;
9057         player->audio_stream_cb_user_param = user_param;
9058         LOGD("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
9059
9060         MMPLAYER_FLEAVE();
9061
9062         return MM_ERROR_NONE;
9063 }
9064
9065 static int
9066 __mmplayer_start_streaming_ext(mm_player_t *player)
9067 {
9068         gint ret = MM_ERROR_NONE;
9069
9070         MMPLAYER_FENTER();
9071         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9072
9073         if (MMPLAYER_IS_HTTP_PD(player)) {
9074                 if (!player->pd_downloader) {
9075                         ret = __mmplayer_realize_streaming_ext(player);
9076
9077                         if (ret != MM_ERROR_NONE) {
9078                                 LOGE("failed to realize streaming ext\n");
9079                                 return ret;
9080                         }
9081                 }
9082
9083                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI) {
9084                         ret = _mmplayer_start_pd_downloader((MMHandleType)player);
9085                         if (!ret) {
9086                                 LOGE("ERROR while starting PD...\n");
9087                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
9088                         }
9089                         ret = MM_ERROR_NONE;
9090                 }
9091         }
9092
9093         MMPLAYER_FLEAVE();
9094         return ret;
9095 }
9096
9097 int
9098 _mmplayer_start(MMHandleType hplayer)
9099 {
9100         mm_player_t* player = (mm_player_t*) hplayer;
9101         gint ret = MM_ERROR_NONE;
9102
9103         MMPLAYER_FENTER();
9104
9105         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9106
9107         /* check current state */
9108         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_START);
9109
9110         /* NOTE : we should check and create pipeline again if not created as we destroy
9111          * whole pipeline when stopping in streamming playback
9112          */
9113         if (!player->pipeline) {
9114                 ret = __gst_realize(player);
9115                 if (MM_ERROR_NONE != ret) {
9116                         LOGE("failed to realize before starting. only in streamming\n");
9117                         /* unlock */
9118                         return ret;
9119                 }
9120         }
9121
9122         ret = __mmplayer_start_streaming_ext(player);
9123         if (ret != MM_ERROR_NONE) {
9124                 LOGE("failed to start streaming ext 0x%X", ret);
9125                 return ret;
9126         }
9127
9128         /* start pipeline */
9129         ret = __gst_start(player);
9130         if (ret != MM_ERROR_NONE)
9131                 LOGE("failed to start player.\n");
9132
9133         MMPLAYER_FLEAVE();
9134
9135         return ret;
9136 }
9137
9138 /* NOTE: post "not supported codec message" to application
9139  * when one codec is not found during AUTOPLUGGING in MSL.
9140  * So, it's separated with error of __mmplayer_gst_callback().
9141  * And, if any codec is not found, don't send message here.
9142  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
9143  */
9144 int
9145 __mmplayer_handle_missed_plugin(mm_player_t* player)
9146 {
9147         MMMessageParamType msg_param;
9148         memset(&msg_param, 0, sizeof(MMMessageParamType));
9149         gboolean post_msg_direct = FALSE;
9150
9151         MMPLAYER_FENTER();
9152
9153         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9154
9155         LOGD("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
9156                         player->not_supported_codec, player->can_support_codec);
9157
9158         if (player->not_found_demuxer) {
9159                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9160                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
9161
9162                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9163                 MMPLAYER_FREEIF(msg_param.data);
9164
9165                 return MM_ERROR_NONE;
9166         }
9167
9168         if (player->not_supported_codec) {
9169                 if (player->can_support_codec) {
9170                         // There is one codec to play
9171                         post_msg_direct = TRUE;
9172                 } else {
9173                         if (player->pipeline->audiobin) // Some content has only PCM data in container.
9174                                 post_msg_direct = TRUE;
9175                 }
9176
9177                 if (post_msg_direct) {
9178                         MMMessageParamType msg_param;
9179                         memset(&msg_param, 0, sizeof(MMMessageParamType));
9180
9181                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9182                                 LOGW("not found AUDIO codec, posting error code to application.\n");
9183
9184                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9185                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9186                         } else if (player->not_supported_codec ==  MISSING_PLUGIN_VIDEO) {
9187                                 LOGW("not found VIDEO codec, posting error code to application.\n");
9188
9189                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9190                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
9191                         }
9192
9193                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9194
9195                         MMPLAYER_FREEIF(msg_param.data);
9196
9197                         return MM_ERROR_NONE;
9198                 } else {
9199                         // no any supported codec case
9200                         LOGW("not found any codec, posting error code to application.\n");
9201
9202                         if (player->not_supported_codec ==  MISSING_PLUGIN_AUDIO) {
9203                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9204                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
9205                         } else {
9206                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9207                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
9208                         }
9209
9210                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9211
9212                         MMPLAYER_FREEIF(msg_param.data);
9213                 }
9214         }
9215
9216         MMPLAYER_FLEAVE();
9217
9218         return MM_ERROR_NONE;
9219 }
9220
9221 static void __mmplayer_check_pipeline(mm_player_t* player)
9222 {
9223         GstState element_state = GST_STATE_VOID_PENDING;
9224         GstState element_pending_state = GST_STATE_VOID_PENDING;
9225         gint timeout = 0;
9226         int ret = MM_ERROR_NONE;
9227
9228         if (player->gapless.reconfigure) {
9229                 LOGW("pipeline is under construction.\n");
9230
9231                 MMPLAYER_PLAYBACK_LOCK(player);
9232                 MMPLAYER_PLAYBACK_UNLOCK(player);
9233
9234                 timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
9235
9236                 /* wait for state transition */
9237                 ret = gst_element_get_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &element_state, &element_pending_state, timeout * GST_SECOND);
9238
9239                 if (ret == GST_STATE_CHANGE_FAILURE)
9240                         LOGE("failed to change pipeline state within %d sec\n", timeout);
9241         }
9242 }
9243
9244 /* NOTE : it should be able to call 'stop' anytime*/
9245 int
9246 _mmplayer_stop(MMHandleType hplayer)
9247 {
9248         mm_player_t* player = (mm_player_t*)hplayer;
9249         int ret = MM_ERROR_NONE;
9250
9251         MMPLAYER_FENTER();
9252
9253         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9254
9255         /* check current state */
9256         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_STOP);
9257
9258         /* check pipline building state */
9259         __mmplayer_check_pipeline(player);
9260         __mmplayer_reset_gapless_state(player);
9261
9262         /* NOTE : application should not wait for EOS after calling STOP */
9263         __mmplayer_cancel_eos_timer(player);
9264
9265         __mmplayer_unrealize_streaming_ext(player);
9266
9267         /* reset */
9268         player->doing_seek = FALSE;
9269
9270         /* stop pipeline */
9271         ret = __gst_stop(player);
9272
9273         if (ret != MM_ERROR_NONE)
9274                 LOGE("failed to stop player.\n");
9275
9276         MMPLAYER_FLEAVE();
9277
9278         return ret;
9279 }
9280
9281 int
9282 _mmplayer_pause(MMHandleType hplayer)
9283 {
9284         mm_player_t* player = (mm_player_t*)hplayer;
9285         gint64 pos_msec = 0;
9286         gboolean async = FALSE;
9287         gint ret = MM_ERROR_NONE;
9288
9289         MMPLAYER_FENTER();
9290
9291         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9292
9293         /* check current state */
9294         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_PAUSE);
9295
9296         /* check pipline building state */
9297         __mmplayer_check_pipeline(player);
9298
9299         switch (MMPLAYER_CURRENT_STATE(player)) {
9300         case MM_PLAYER_STATE_READY:
9301                 {
9302                         /* check prepare async or not.
9303                          * In the case of streaming playback, it's recommned to avoid blocking wait.
9304                          */
9305                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9306                         LOGD("prepare working mode : %s", (async ? "async" : "sync"));
9307
9308                         /* Changing back sync of rtspsrc to async */
9309                         if (MMPLAYER_IS_RTSP_STREAMING(player)) {
9310                                 LOGD("async prepare working mode for rtsp");
9311                                 async = TRUE;
9312                         }
9313                 }
9314                 break;
9315
9316         case MM_PLAYER_STATE_PLAYING:
9317                 {
9318                         /* NOTE : store current point to overcome some bad operation
9319                         *(returning zero when getting current position in paused state) of some
9320                         * elements
9321                         */
9322                         if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec))
9323                                 LOGW("getting current position failed in paused\n");
9324
9325                         player->last_position = pos_msec;
9326
9327                         /* For rtspsrc stack , npt-start value coming from server is used for finding the current position.
9328                            But when a rtsp clip (especially from Youtube Desktop View) is paused and kept for sometime,npt-start is still increasing.
9329                            This causes problem is position calculation during normal pause resume scenarios also.
9330                            Currently during pause , we are sending the current position to rtspsrc module for position saving. */
9331                         if ((MMPLAYER_IS_RTSP_STREAMING(player)) &&
9332                                 (__mmplayer_get_stream_service_type(player) == STREAMING_SERVICE_VOD)) {
9333                                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "resume-position", player->last_position, NULL);
9334                         }
9335                 }
9336                 break;
9337         }
9338
9339         if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
9340                 LOGD("doing async pause in case of ms buff src");
9341                 async = TRUE;
9342         }
9343
9344         /* pause pipeline */
9345         ret = __gst_pause(player, async);
9346
9347         if (ret != MM_ERROR_NONE)
9348                 LOGE("failed to pause player. ret : 0x%x\n", ret);
9349
9350         if (MMPLAYER_PREV_STATE(player) == MM_PLAYER_STATE_READY && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED) {
9351                 if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "display_rotation"))
9352                         LOGE("failed to update display_rotation");
9353         }
9354
9355         MMPLAYER_FLEAVE();
9356
9357         return ret;
9358 }
9359
9360 int
9361 _mmplayer_resume(MMHandleType hplayer)
9362 {
9363         mm_player_t* player = (mm_player_t*)hplayer;
9364         int ret = MM_ERROR_NONE;
9365         gboolean async = FALSE;
9366
9367         MMPLAYER_FENTER();
9368
9369         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9370
9371         /* Changing back sync mode rtspsrc to async */
9372         if ((MMPLAYER_IS_RTSP_STREAMING(player))) {
9373                 LOGD("async resume for rtsp case");
9374                 async = TRUE;
9375         }
9376
9377         /* check current state */
9378         MMPLAYER_CHECK_STATE(player, MMPLAYER_COMMAND_RESUME);
9379
9380         ret = __gst_resume(player, async);
9381
9382         if (ret != MM_ERROR_NONE)
9383                 LOGE("failed to resume player.\n");
9384
9385         MMPLAYER_FLEAVE();
9386
9387         return ret;
9388 }
9389
9390 static int
9391 __mmplayer_set_pcm_extraction(mm_player_t* player)
9392 {
9393         gint64 start_nsec = 0;
9394         gint64 end_nsec = 0;
9395         gint64 dur_nsec = 0;
9396         gint64 dur_msec = 0;
9397         int required_start = 0;
9398         int required_end = 0;
9399         int ret = 0;
9400
9401         MMPLAYER_FENTER();
9402
9403         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
9404
9405         mm_attrs_multiple_get(player->attrs,
9406                 NULL,
9407                 "pcm_extraction_start_msec", &required_start,
9408                 "pcm_extraction_end_msec", &required_end,
9409                 NULL);
9410
9411         LOGD("pcm extraction required position is from [%d] to [%d](msec)\n", required_start, required_end);
9412
9413         if (required_start == 0 && required_end == 0) {
9414                 LOGD("extracting entire stream");
9415                 return MM_ERROR_NONE;
9416         } else if (required_start < 0 || required_start > required_end || required_end < 0) {
9417                 LOGD("invalid range for pcm extraction");
9418                 return MM_ERROR_INVALID_ARGUMENT;
9419         }
9420
9421         /* get duration */
9422         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &dur_nsec);
9423         if (!ret) {
9424                 LOGE("failed to get duration");
9425                 return MM_ERROR_PLAYER_INTERNAL;
9426         }
9427         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
9428
9429         if (dur_msec < required_end) {
9430                 // FIXME
9431                 LOGD("invalid end pos for pcm extraction");
9432                 return MM_ERROR_INVALID_ARGUMENT;
9433         }
9434
9435         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
9436         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
9437
9438         if ((!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9439                                         1.0,
9440                                         GST_FORMAT_TIME,
9441                                         (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9442                                         GST_SEEK_TYPE_SET, start_nsec,
9443                                         GST_SEEK_TYPE_SET, end_nsec))) {
9444                 LOGE("failed to seek for pcm extraction\n");
9445
9446                 return MM_ERROR_PLAYER_SEEK;
9447         }
9448
9449         LOGD("succeeded to set up segment extraction from [%llu] to [%llu](nsec)\n", start_nsec, end_nsec);
9450
9451         MMPLAYER_FLEAVE();
9452
9453         return MM_ERROR_NONE;
9454 }
9455
9456 int
9457 _mmplayer_set_playspeed(MMHandleType hplayer, float rate, bool streaming)
9458 {
9459         mm_player_t* player = (mm_player_t*)hplayer;
9460         gint64 pos_msec = 0;
9461         int ret = MM_ERROR_NONE;
9462         int mute = FALSE;
9463         signed long long start = 0, stop = 0;
9464         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
9465         MMPLAYER_FENTER();
9466
9467         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
9468         MMPLAYER_RETURN_VAL_IF_FAIL(streaming || !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API);
9469
9470         /* The sound of video is not supported under 0.0 and over 2.0. */
9471         if (rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN) {
9472                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
9473                         mute = TRUE;
9474         }
9475         _mmplayer_set_mute(hplayer, mute);
9476
9477         if (player->playback_rate == rate)
9478                 return MM_ERROR_NONE;
9479
9480         /* If the position is reached at start potion during fast backward, EOS is posted.
9481          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
9482          * */
9483         player->playback_rate = rate;
9484
9485         current_state = MMPLAYER_CURRENT_STATE(player);
9486
9487         if (current_state != MM_PLAYER_STATE_PAUSED)
9488                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &pos_msec);
9489
9490         LOGD("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS(pos_msec), ret, current_state);
9491
9492         if ((current_state == MM_PLAYER_STATE_PAUSED)
9493                 || (!ret) /*|| (player->last_position != 0 && pos_msec == 0)*/) {
9494                 LOGW("returning last point : %lld\n", player->last_position);
9495                 pos_msec = player->last_position;
9496         }
9497
9498         if (rate >= 0) {
9499                 start = pos_msec;
9500                 stop = GST_CLOCK_TIME_NONE;
9501         } else {
9502                 start = GST_CLOCK_TIME_NONE;
9503                 stop = pos_msec;
9504         }
9505
9506         if (!__gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
9507                                 player->playback_rate,
9508                                 GST_FORMAT_TIME,
9509                                 (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE),
9510                                 GST_SEEK_TYPE_SET, start,
9511                                 GST_SEEK_TYPE_SET, stop)) {
9512                 LOGE("failed to set speed playback\n");
9513                 return MM_ERROR_PLAYER_SEEK;
9514         }
9515
9516         LOGD("succeeded to set speed playback as %0.1f\n", rate);
9517
9518         MMPLAYER_FLEAVE();
9519
9520         return MM_ERROR_NONE;;
9521 }
9522
9523 int
9524 _mmplayer_set_position(MMHandleType hplayer, int format, int position)
9525 {
9526         mm_player_t* player = (mm_player_t*)hplayer;
9527         int ret = MM_ERROR_NONE;
9528
9529         MMPLAYER_FENTER();
9530
9531         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9532
9533         /* check pipline building state */
9534         __mmplayer_check_pipeline(player);
9535
9536         ret = __gst_set_position(player, format, (unsigned long)position, FALSE);
9537
9538         MMPLAYER_FLEAVE();
9539
9540         return ret;
9541 }
9542
9543 int
9544 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position)
9545 {
9546         mm_player_t* player = (mm_player_t*)hplayer;
9547         int ret = MM_ERROR_NONE;
9548
9549         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9550
9551         ret = __gst_get_position(player, format, position);
9552
9553         return ret;
9554 }
9555
9556 int
9557 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos)
9558 {
9559         mm_player_t* player = (mm_player_t*)hplayer;
9560         int ret = MM_ERROR_NONE;
9561
9562         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9563
9564         ret = __gst_get_buffer_position(player, format, start_pos, stop_pos);
9565
9566         return ret;
9567 }
9568
9569 int
9570 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position)
9571 {
9572         mm_player_t* player = (mm_player_t*)hplayer;
9573         int ret = MM_ERROR_NONE;
9574
9575         MMPLAYER_FENTER();
9576
9577         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9578
9579         ret = __gst_adjust_subtitle_position(player, format, position);
9580
9581         MMPLAYER_FLEAVE();
9582
9583         return ret;
9584 }
9585 int
9586 _mmplayer_adjust_video_postion(MMHandleType hplayer, int offset)
9587 {
9588         mm_player_t* player = (mm_player_t*)hplayer;
9589         int ret = MM_ERROR_NONE;
9590
9591         MMPLAYER_FENTER();
9592
9593         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9594
9595         ret = __gst_adjust_video_position(player, offset);
9596
9597         MMPLAYER_FLEAVE();
9598
9599         return ret;
9600 }
9601
9602 static gboolean
9603 __mmplayer_is_midi_type(gchar* str_caps)
9604 {
9605         if ((g_strrstr(str_caps, "audio/midi")) ||
9606                 (g_strrstr(str_caps, "application/x-gst_ff-mmf")) ||
9607                 (g_strrstr(str_caps, "application/x-smaf")) ||
9608                 (g_strrstr(str_caps, "audio/x-imelody")) ||
9609                 (g_strrstr(str_caps, "audio/mobile-xmf")) ||
9610                 (g_strrstr(str_caps, "audio/xmf")) ||
9611                 (g_strrstr(str_caps, "audio/mxmf"))) {
9612                 LOGD("midi\n");
9613                 return TRUE;
9614         }
9615
9616         return FALSE;
9617 }
9618
9619 static gboolean
9620 __mmplayer_is_only_mp3_type(gchar *str_caps)
9621 {
9622         if (g_strrstr(str_caps, "application/x-id3") ||
9623                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion= (int)1")))
9624                 return TRUE;
9625         return FALSE;
9626 }
9627
9628 static void
9629 __mmplayer_set_audio_attrs(mm_player_t* player, GstCaps* caps)
9630 {
9631         GstStructure* caps_structure = NULL;
9632         gint samplerate = 0;
9633         gint channels = 0;
9634
9635         MMPLAYER_FENTER();
9636         MMPLAYER_RETURN_IF_FAIL(player && caps);
9637
9638         caps_structure = gst_caps_get_structure(caps, 0);
9639
9640         /* set stream information */
9641         gst_structure_get_int(caps_structure, "rate", &samplerate);
9642         mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
9643
9644         gst_structure_get_int(caps_structure, "channels", &channels);
9645         mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
9646
9647         LOGD("audio samplerate : %d     channels : %d\n", samplerate, channels);
9648 }
9649
9650 static void
9651 __mmplayer_update_content_type_info(mm_player_t* player)
9652 {
9653         MMPLAYER_FENTER();
9654         MMPLAYER_RETURN_IF_FAIL(player && player->type);
9655
9656         if (__mmplayer_is_midi_type(player->type)) {
9657                 player->bypass_audio_effect = TRUE;
9658         } else if (g_strrstr(player->type, "application/x-hls")) {
9659                 /* If it can't know exact type when it parses uri because of redirection case,
9660                  * it will be fixed by typefinder or when doing autoplugging.
9661                  */
9662                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
9663                 if (player->streamer) {
9664                         player->streamer->is_adaptive_streaming = TRUE;
9665                         player->streamer->buffering_req.mode = MM_PLAYER_BUFFERING_MODE_FIXED;
9666                         player->streamer->buffering_req.rebuffer_time = 5 * 1000;
9667                 }
9668         } else if (g_strrstr(player->type, "application/dash+xml")) {
9669                 player->profile.uri_type = MM_PLAYER_URI_TYPE_DASH;
9670         }
9671
9672         MMPLAYER_FLEAVE();
9673 }
9674
9675 static void
9676 __mmplayer_typefind_have_type(GstElement *tf, guint probability,
9677 GstCaps *caps, gpointer data)
9678 {
9679         mm_player_t* player = (mm_player_t*)data;
9680         GstPad* pad = NULL;
9681
9682         MMPLAYER_FENTER();
9683
9684         MMPLAYER_RETURN_IF_FAIL(player && tf && caps);
9685
9686         /* store type string */
9687         MMPLAYER_FREEIF(player->type);
9688         player->type = gst_caps_to_string(caps);
9689         if (player->type) {
9690                 LOGD("[handle: %p] media type %s found, probability %d%% / %d\n",
9691                                 player, player->type, probability, gst_caps_get_size(caps));
9692         }
9693
9694         if ((!MMPLAYER_IS_RTSP_STREAMING(player)) &&
9695                 (g_strrstr(player->type, "audio/x-raw-int"))) {
9696                 LOGE("not support media format\n");
9697
9698                 if (player->msg_posted == FALSE) {
9699                         MMMessageParamType msg_param;
9700                         memset(&msg_param, 0, sizeof(MMMessageParamType));
9701
9702                         msg_param.code = MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9703                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
9704
9705                         /* don't post more if one was sent already */
9706                         player->msg_posted = TRUE;
9707                 }
9708                 return;
9709         }
9710
9711         __mmplayer_update_content_type_info(player);
9712
9713         pad = gst_element_get_static_pad(tf, "src");
9714         if (!pad) {
9715                 LOGE("fail to get typefind src pad.\n");
9716                 return;
9717         }
9718
9719         if (!__mmplayer_try_to_plug_decodebin(player, pad, caps)) {
9720                 gboolean async = FALSE;
9721                 LOGE("failed to autoplug %s\n", player->type);
9722
9723                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
9724
9725                 if (async && player->msg_posted == FALSE)
9726                         __mmplayer_handle_missed_plugin(player);
9727
9728                 goto DONE;
9729         }
9730
9731 DONE:
9732         gst_object_unref(GST_OBJECT(pad));
9733
9734         MMPLAYER_FLEAVE();
9735
9736         return;
9737 }
9738
9739 static GstElement *
9740 __mmplayer_create_decodebin(mm_player_t* player)
9741 {
9742         GstElement *decodebin = NULL;
9743
9744         MMPLAYER_FENTER();
9745
9746         /* create decodebin */
9747         decodebin = gst_element_factory_make("decodebin", NULL);
9748
9749         if (!decodebin) {
9750                 LOGE("fail to create decodebin\n");
9751                 goto ERROR;
9752         }
9753
9754         /* raw pad handling signal */
9755         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-added",
9756                                                 G_CALLBACK(__mmplayer_gst_decode_pad_added), player);
9757
9758         /* no-more-pad pad handling signal */
9759         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "no-more-pads",
9760                                                 G_CALLBACK(__mmplayer_gst_decode_no_more_pads), player);
9761
9762         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "pad-removed",
9763                                                 G_CALLBACK(__mmplayer_gst_decode_pad_removed), player);
9764
9765         /* This signal is emitted when a pad for which there is no further possible
9766            decoding is added to the decodebin.*/
9767         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "unknown-type",
9768                                                 G_CALLBACK(__mmplayer_gst_decode_unknown_type), player);
9769
9770         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
9771            before looking for any elements that can handle that stream.*/
9772         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-continue",
9773                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_continue), player);
9774
9775         /* This signal is emitted whenever decodebin finds a new stream. It is emitted
9776            before looking for any elements that can handle that stream.*/
9777         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "autoplug-select",
9778                                                 G_CALLBACK(__mmplayer_gst_decode_autoplug_select), player);
9779
9780         /* This signal is emitted once decodebin has finished decoding all the data.*/
9781         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "drained",
9782                                                 G_CALLBACK(__mmplayer_gst_decode_drained), player);
9783
9784         /* This signal is emitted when a element is added to the bin.*/
9785         MMPLAYER_SIGNAL_CONNECT(player, G_OBJECT(decodebin), MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "element-added",
9786                                                 G_CALLBACK(__mmplayer_gst_element_added), player);
9787
9788 ERROR:
9789         return decodebin;
9790 }
9791
9792 static gboolean
9793 __mmplayer_try_to_plug_decodebin(mm_player_t* player, GstPad *srcpad, const GstCaps *caps)
9794 {
9795         MMPlayerGstElement* mainbin = NULL;
9796         GstElement* decodebin = NULL;
9797         GstElement* queue2 = NULL;
9798         GstPad* sinkpad = NULL;
9799         GstPad* qsrcpad = NULL;
9800         gint64 dur_bytes = 0L;
9801
9802         guint max_buffer_size_bytes = 0;
9803         gint init_buffering_time = player->streamer->buffering_req.prebuffer_time;
9804
9805         MMPLAYER_FENTER();
9806         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin, FALSE);
9807
9808         mainbin = player->pipeline->mainbin;
9809
9810         if ((!MMPLAYER_IS_HTTP_PD(player)) &&
9811                 (MMPLAYER_IS_HTTP_STREAMING(player))) {
9812                 LOGD("creating http streaming buffering queue(queue2)\n");
9813
9814                 if (mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst) {
9815                         LOGE("MMPLAYER_M_MUXED_S_BUFFER is not null\n");
9816                 } else {
9817                         queue2 = gst_element_factory_make("queue2", "queue2");
9818                         if (!queue2) {
9819                                 LOGE("failed to create buffering queue element\n");
9820                                 goto ERROR;
9821                         }
9822
9823                         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2)) {
9824                                 LOGE("failed to add buffering queue\n");
9825                                 goto ERROR;
9826                         }
9827
9828                         sinkpad = gst_element_get_static_pad(queue2, "sink");
9829                         qsrcpad = gst_element_get_static_pad(queue2, "src");
9830
9831                         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
9832                                 LOGE("failed to link buffering queue\n");
9833                                 goto ERROR;
9834                         }
9835
9836                         if (!gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, GST_FORMAT_BYTES, &dur_bytes))
9837                                 LOGE("fail to get duration.\n");
9838
9839                         LOGD("dur_bytes = %lld\n", dur_bytes);
9840
9841                         muxed_buffer_type_e type = MUXED_BUFFER_TYPE_MEM_QUEUE;
9842
9843                         if (dur_bytes > 0) {
9844                                 if (MMPLAYER_USE_FILE_FOR_BUFFERING(player)) {
9845                                         type = MUXED_BUFFER_TYPE_FILE;
9846                                 } else {
9847                                         type = MUXED_BUFFER_TYPE_MEM_RING_BUFFER;
9848                                         player->streamer->ring_buffer_size = player->ini.http_ring_buffer_size;
9849                                 }
9850                         } else {
9851                                 dur_bytes = 0;
9852                         }
9853
9854                         /* NOTE : we cannot get any duration info from ts container in case of streaming */
9855                         // if (!g_strrstr(GST_ELEMENT_NAME(sinkelement), "mpegtsdemux"))
9856                         if (!g_strrstr(player->type, "video/mpegts")) {
9857                                 max_buffer_size_bytes = (type == MUXED_BUFFER_TYPE_FILE) ? (player->ini.http_max_size_bytes) : (5*1024*1024);
9858                                 LOGD("max_buffer_size_bytes = %d\n", max_buffer_size_bytes);
9859
9860                                 // FIXME : pass ini setting directly. is this ok?
9861                                 __mm_player_streaming_set_queue2(player->streamer,
9862                                                                                                 queue2,
9863                                                                                                 FALSE,
9864                                                                                                 max_buffer_size_bytes,
9865                                                                                                 player->ini.http_buffering_time,
9866                                                                                                 1.0,                                                            // no meaning
9867                                                                                                 player->ini.http_buffering_limit,       // no meaning
9868                                                                                                 type,
9869                                                                                                 player->http_file_buffering_path,
9870                                                                                                 (guint64)dur_bytes);
9871                         }
9872
9873                         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(queue2)) {
9874                                 LOGE("failed to sync queue2 state with parent\n");
9875                                 goto ERROR;
9876                         }
9877
9878                         srcpad = qsrcpad;
9879
9880                         gst_object_unref(GST_OBJECT(sinkpad));
9881
9882                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].id = MMPLAYER_M_MUXED_S_BUFFER;
9883                         mainbin[MMPLAYER_M_MUXED_S_BUFFER].gst = queue2;
9884                 }
9885         }
9886
9887         /* create decodebin */
9888         decodebin = __mmplayer_create_decodebin(player);
9889
9890         if (!decodebin) {
9891                 LOGE("can not create autoplug element\n");
9892                 goto ERROR;
9893         }
9894
9895         if (!gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin)) {
9896                 LOGE("failed to add decodebin\n");
9897                 goto ERROR;
9898         }
9899
9900         /* to force caps on the decodebin element and avoid reparsing stuff by
9901         * typefind. It also avoids a deadlock in the way typefind activates pads in
9902         * the state change */
9903         g_object_set(decodebin, "sink-caps", caps, NULL);
9904
9905         sinkpad = gst_element_get_static_pad(decodebin, "sink");
9906
9907         if (GST_PAD_LINK_OK != gst_pad_link(srcpad, sinkpad)) {
9908                 LOGE("failed to link decodebin\n");
9909                 goto ERROR;
9910         }
9911
9912         gst_object_unref(GST_OBJECT(sinkpad));
9913
9914         mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
9915         mainbin[MMPLAYER_M_AUTOPLUG].gst = decodebin;
9916
9917         /* set decodebin property about buffer in streaming playback. *
9918          * in case of HLS/DASH, it does not need to have big buffer        *
9919          * because it is kind of adaptive streaming.                  */
9920         if (!MMPLAYER_IS_HTTP_PD(player) && MMPLAYER_IS_HTTP_STREAMING(player)) {
9921                 guint max_size_bytes = MAX_DECODEBIN_BUFFER_BYTES;
9922                 guint64 max_size_time = MAX_DECODEBIN_BUFFER_TIME;
9923                 init_buffering_time = (init_buffering_time != 0) ? (init_buffering_time) : (player->ini.http_buffering_time);
9924
9925                 if (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)
9926                         || MMPLAYER_IS_DASH_STREAMING(player)) {
9927                         max_size_bytes = MAX_DECODEBIN_ADAPTIVE_BUFFER_BYTES;
9928                         max_size_time = MAX_DECODEBIN_ADAPTIVE_BUFFER_TIME;
9929                 }
9930
9931                 g_object_set(G_OBJECT(decodebin), "use-buffering", TRUE,
9932                                                                                         "high-percent", (gint)player->ini.http_buffering_limit,
9933                                                                                         "low-percent", 1,   // 1%
9934                                                                                         "max-size-bytes", max_size_bytes,
9935                                                                                         "max-size-time", (guint64)(max_size_time * GST_SECOND),
9936                                                                                         "max-size-buffers", 0, NULL);  // disable or automatic
9937         }
9938
9939         if (GST_STATE_CHANGE_FAILURE == gst_element_sync_state_with_parent(decodebin)) {
9940                 LOGE("failed to sync decodebin state with parent\n");
9941                 goto ERROR;
9942         }
9943
9944         MMPLAYER_FLEAVE();
9945
9946         return TRUE;
9947
9948 ERROR:
9949
9950         if (sinkpad)
9951                 gst_object_unref(GST_OBJECT(sinkpad));
9952
9953         if (queue2) {
9954                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
9955                  * You need to explicitly set elements to the NULL state before
9956                  * dropping the final reference, to allow them to clean up.
9957                  */
9958                 gst_element_set_state(queue2, GST_STATE_NULL);
9959
9960                 /* And, it still has a parent "player".
9961                  * You need to let the parent manage the object instead of unreffing the object directly.
9962                  */
9963                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue2);
9964                 gst_object_unref(queue2);
9965                 queue2 = NULL;
9966         }
9967
9968         if (decodebin) {
9969                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
9970                  * You need to explicitly set elements to the NULL state before
9971                  * dropping the final reference, to allow them to clean up.
9972                  */
9973                 gst_element_set_state(decodebin, GST_STATE_NULL);
9974
9975                 /* And, it still has a parent "player".
9976                  * You need to let the parent manage the object instead of unreffing the object directly.
9977                  */
9978
9979                 gst_bin_remove(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), decodebin);
9980                 gst_object_unref(decodebin);
9981                 decodebin = NULL;
9982         }
9983
9984         return FALSE;
9985 }
9986
9987 static int
9988 __mmplayer_check_not_supported_codec(mm_player_t* player, const gchar* factory_class, const gchar* mime)
9989 {
9990         MMPLAYER_FENTER();
9991
9992         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
9993         MMPLAYER_RETURN_VAL_IF_FAIL(mime, MM_ERROR_INVALID_ARGUMENT);
9994
9995         LOGD("class : %s, mime : %s \n", factory_class, mime);
9996
9997         /* add missing plugin */
9998         /* NOTE : msl should check missing plugin for image mime type.
9999          * Some motion jpeg clips can have playable audio track.
10000          * So, msl have to play audio after displaying popup written video format not supported.
10001          */
10002         if (!(player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst)) {
10003                 if (!(player->can_support_codec | player->videodec_linked | player->audiodec_linked)) {
10004                         LOGD("not found demuxer\n");
10005                         player->not_found_demuxer = TRUE;
10006                         player->unlinked_demuxer_mime = g_strdup_printf("%s", mime);
10007
10008                         goto DONE;
10009                 }
10010         }
10011
10012         if (!g_strrstr(factory_class, "Demuxer")) {
10013                 if ((g_str_has_prefix(mime, "video")) || (g_str_has_prefix(mime, "image"))) {
10014                         LOGD("can support codec=0x%X, vdec_linked=%d, adec_linked=%d\n",
10015                                 player->can_support_codec, player->videodec_linked, player->audiodec_linked);
10016
10017                         /* check that clip have multi tracks or not */
10018                         if ((player->can_support_codec & FOUND_PLUGIN_VIDEO) && (player->videodec_linked)) {
10019                                 LOGD("video plugin is already linked\n");
10020                         } else {
10021                                 LOGW("add VIDEO to missing plugin\n");
10022                                 player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
10023                                 player->unlinked_video_mime = g_strdup_printf("%s", mime);
10024                         }
10025                 } else if (g_str_has_prefix(mime, "audio")) {
10026                         if ((player->can_support_codec & FOUND_PLUGIN_AUDIO) && (player->audiodec_linked)) {
10027                                 LOGD("audio plugin is already linked\n");
10028                         } else {
10029                                 LOGW("add AUDIO to missing plugin\n");
10030                                 player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
10031                                 player->unlinked_audio_mime = g_strdup_printf("%s", mime);
10032                         }
10033                 }
10034         }
10035
10036 DONE:
10037         MMPLAYER_FLEAVE();
10038
10039         return MM_ERROR_NONE;
10040 }
10041
10042
10043 static void
10044 __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data)
10045 {
10046         mm_player_t* player = (mm_player_t*)data;
10047
10048         MMPLAYER_FENTER();
10049
10050         MMPLAYER_RETURN_IF_FAIL(player);
10051
10052         /* remove fakesink. */
10053         if (!__mmplayer_gst_remove_fakesink(player,
10054                                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK])) {
10055                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
10056                  * signaling mechanism(pad-added, no-more-pad, new-decoded-pad) from various
10057                  * source element are not same. To overcome this situation, this function will called
10058                  * several places and several times. Therefore, this is not an error case.
10059                  */
10060                 return;
10061         }
10062
10063         LOGD("[handle: %p] pipeline has completely constructed", player);
10064
10065         if ((player->ini.async_start) &&
10066                 (player->msg_posted == FALSE) &&
10067                 (player->cmd >= MMPLAYER_COMMAND_START))
10068                 __mmplayer_handle_missed_plugin(player);
10069
10070         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-complete");
10071 }
10072
10073 static gboolean
10074 __mmplayer_verify_next_play_path(mm_player_t *player)
10075 {
10076         MMHandleType attrs = 0;
10077         MMPlayerParseProfile profile;
10078         gint uri_idx = 0, check_cnt = 0;
10079         char *uri = NULL;
10080         gint mode = MM_PLAYER_PD_MODE_NONE;
10081         gint video = 0;
10082         gint count = 0;
10083         gint gapless = 0;
10084         guint num_of_list = 0;
10085         static int profile_tv = -1;
10086
10087         MMPLAYER_FENTER();
10088
10089         LOGD("checking for gapless play");
10090
10091         if (player->pipeline->textbin) {
10092                 LOGE("subtitle path is enabled. gapless play is not supported.\n");
10093                 goto ERROR;
10094         }
10095
10096         attrs = MMPLAYER_GET_ATTRS(player);
10097         if (!attrs) {
10098                 LOGE("fail to get attributes.\n");
10099                 goto ERROR;
10100         }
10101
10102         mm_attrs_get_int_by_name(attrs, "content_video_found", &video);
10103
10104         if (__builtin_expect(profile_tv == -1, 0)) {
10105                 char *profileName;
10106                 system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
10107                 switch (*profileName) {
10108                 case 't':
10109                 case 'T':
10110                         profile_tv = 1;
10111                         break;
10112                 default:
10113                         profile_tv = 0;
10114                 }
10115                 free(profileName);
10116         }
10117         /* gapless playback is not supported in case of video at TV profile. */
10118         if (profile_tv && video) {
10119                 LOGW("not support video gapless playback");
10120                 goto ERROR;
10121         }
10122
10123         if (mm_attrs_get_int_by_name(attrs, "pd_mode", &mode) == MM_ERROR_NONE) {
10124                 if (mode == TRUE) {
10125                         LOGW("pd mode\n");
10126                         goto ERROR;
10127                 }
10128         }
10129
10130         if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
10131                 LOGE("can not get play count\n");
10132
10133         if (mm_attrs_get_int_by_name(attrs, "gapless_mode", &gapless) != MM_ERROR_NONE)
10134                 LOGE("can not get gapless mode\n");
10135
10136         if (video && !gapless) {
10137                 LOGW("not enabled video gapless playback");
10138                 goto ERROR;
10139         }
10140
10141         if ((count == -1 || count > 1)) /* enable gapless when looping or repeat */
10142                 gapless = 1;
10143
10144         if (!gapless) {
10145                 LOGW("gapless is disabled\n");  /* FIXME: playlist(without gapless) is not implemented. */
10146                 goto ERROR;
10147         }
10148
10149         num_of_list = g_list_length(player->uri_info.uri_list);
10150
10151         LOGD("repeat count = %d, num_of_list = %d\n", count, num_of_list);
10152
10153         if (num_of_list == 0) {
10154                 if (mm_attrs_get_string_by_name(player->attrs, "profile_uri", &uri) != MM_ERROR_NONE) {
10155                         LOGE("can not get profile_uri\n");
10156                         goto ERROR;
10157                 }
10158
10159                 if (!uri) {
10160                         LOGE("uri list is empty.\n");
10161                         goto ERROR;
10162                 }
10163
10164                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10165                 LOGD("add original path : %s ", uri);
10166
10167                 num_of_list = 1;
10168                 uri = NULL;
10169         }
10170
10171         uri_idx = player->uri_info.uri_idx;
10172
10173         while (TRUE) {
10174                 check_cnt++;
10175
10176                 if (check_cnt > num_of_list) {
10177                         LOGE("there is no valid uri.");
10178                         goto ERROR;
10179                 }
10180
10181                 LOGD("uri idx : %d / %d\n", uri_idx, num_of_list);
10182
10183                 if (uri_idx < num_of_list-1) {
10184                         uri_idx++;
10185                 } else {
10186                         if ((count <= 1) && (count != -1)) {
10187                                 LOGD("no repeat.");
10188                                 goto ERROR;
10189                         } else if (count > 1) {
10190                                 /* decrease play count */
10191                                 /* we succeeded to rewind. update play count and then wait for next EOS */
10192                                 count--;
10193
10194                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
10195
10196                                 /* commit attribute */
10197                                 if (mmf_attrs_commit(attrs))
10198                                         LOGE("failed to commit attribute\n");
10199                         }
10200
10201                         /* count < 0 : repeat continually */
10202                         uri_idx = 0;
10203                 }
10204
10205                 uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
10206                 LOGD("uri idx : %d, uri = %s\n", uri_idx, uri);
10207
10208                 if (uri == NULL) {
10209                         LOGW("next uri does not exist\n");
10210                         continue;
10211                 }
10212
10213                 if (__mmfplayer_parse_profile((const char*)uri, NULL, &profile) != MM_ERROR_NONE) {
10214                         LOGE("failed to parse profile\n");
10215                         continue;
10216                 }
10217
10218                 if ((profile.uri_type != MM_PLAYER_URI_TYPE_FILE) &&
10219                         (profile.uri_type != MM_PLAYER_URI_TYPE_URL_HTTP)) {
10220                         LOGW("uri type is not supported(%d).", profile.uri_type);
10221                         continue;
10222                 }
10223
10224                 break;
10225         }
10226
10227         player->uri_info.uri_idx = uri_idx;
10228         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
10229
10230         if (mmf_attrs_commit(player->attrs)) {
10231                 LOGE("failed to commit.\n");
10232                 goto ERROR;
10233         }
10234
10235         LOGD("next uri %s(%d)\n", uri, uri_idx);
10236
10237         return TRUE;
10238
10239 ERROR:
10240
10241         LOGE("unable to play next path. EOS will be posted soon.\n");
10242         return FALSE;
10243 }
10244
10245 static void
10246 __mmplayer_initialize_next_play(mm_player_t *player)
10247 {
10248         int i;
10249
10250         MMPLAYER_FENTER();
10251
10252         player->smooth_streaming = FALSE;
10253         player->videodec_linked = 0;
10254         player->audiodec_linked = 0;
10255         player->videosink_linked = 0;
10256         player->audiosink_linked = 0;
10257         player->textsink_linked = 0;
10258         player->is_external_subtitle_present = FALSE;
10259         player->is_external_subtitle_added_now = FALSE;
10260         player->not_supported_codec = MISSING_PLUGIN_NONE;
10261         player->can_support_codec = FOUND_PLUGIN_NONE;
10262         player->pending_seek.is_pending = FALSE;
10263         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
10264         player->pending_seek.pos = 0;
10265         player->msg_posted = FALSE;
10266         player->has_many_types = FALSE;
10267         player->no_more_pad = FALSE;
10268         player->not_found_demuxer = 0;
10269         player->doing_seek = FALSE;
10270         player->max_audio_channels = 0;
10271         player->is_subtitle_force_drop = FALSE;
10272         player->play_subtitle = FALSE;
10273         player->adjust_subtitle_pos = 0;
10274
10275         player->total_bitrate = 0;
10276         player->total_maximum_bitrate = 0;
10277
10278         _mmplayer_track_initialize(player);
10279         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
10280
10281         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
10282                 player->bitrate[i] = 0;
10283                 player->maximum_bitrate[i] = 0;
10284         }
10285
10286         if (player->v_stream_caps) {
10287                 gst_caps_unref(player->v_stream_caps);
10288                 player->v_stream_caps = NULL;
10289         }
10290
10291         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
10292
10293         /* clean found parsers */
10294         if (player->parsers) {
10295                 GList *parsers = player->parsers;
10296                 for (; parsers; parsers = g_list_next(parsers)) {
10297                         gchar *name = parsers->data;
10298                         MMPLAYER_FREEIF(name);
10299                 }
10300                 g_list_free(player->parsers);
10301                 player->parsers = NULL;
10302         }
10303
10304         /* clean found audio decoders */
10305         if (player->audio_decoders) {
10306                 GList *a_dec = player->audio_decoders;
10307                 for (; a_dec; a_dec = g_list_next(a_dec)) {
10308                         gchar *name = a_dec->data;
10309                         MMPLAYER_FREEIF(name);
10310                 }
10311                 g_list_free(player->audio_decoders);
10312                 player->audio_decoders = NULL;
10313         }
10314
10315         MMPLAYER_FLEAVE();
10316 }
10317
10318 static void
10319 __mmplayer_activate_next_source(mm_player_t *player, GstState target)
10320 {
10321         MMPlayerGstElement *mainbin = NULL;
10322         MMMessageParamType msg_param = {0,};
10323         GstElement *element = NULL;
10324         MMHandleType attrs = 0;
10325         char *uri = NULL;
10326         enum MainElementID elemId = MMPLAYER_M_NUM;
10327
10328         MMPLAYER_FENTER();
10329
10330         if ((player == NULL) ||
10331                 (player->pipeline == NULL) ||
10332                 (player->pipeline->mainbin == NULL)) {
10333                 LOGE("player is null.\n");
10334                 goto ERROR;
10335         }
10336
10337         mainbin = player->pipeline->mainbin;
10338         msg_param.code = MM_ERROR_PLAYER_INTERNAL;
10339
10340         attrs = MMPLAYER_GET_ATTRS(player);
10341         if (!attrs) {
10342                 LOGE("fail to get attributes.\n");
10343                 goto ERROR;
10344         }
10345
10346         /* Initialize Player values */
10347         __mmplayer_initialize_next_play(player);
10348
10349         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
10350
10351         if (__mmfplayer_parse_profile((const char*)uri, NULL, &player->profile) != MM_ERROR_NONE) {
10352                 LOGE("failed to parse profile\n");
10353                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
10354                 goto ERROR;
10355         }
10356
10357         if ((MMPLAYER_URL_HAS_DASH_SUFFIX(player)) ||
10358                 (MMPLAYER_URL_HAS_HLS_SUFFIX(player))) {
10359                 LOGE("it's dash or hls. not support.");
10360                 msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
10361                 goto ERROR;
10362         }
10363
10364         /* setup source */
10365         switch (player->profile.uri_type) {
10366         /* file source */
10367         case MM_PLAYER_URI_TYPE_FILE:
10368         {
10369                 LOGD("using filesrc for 'file://' handler.\n");
10370                 if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) {
10371                         LOGE("failed to get storage info");
10372                         break;
10373                 }
10374
10375                 element = gst_element_factory_make("filesrc", "source");
10376
10377                 if (!element) {
10378                         LOGE("failed to create filesrc\n");
10379                         break;
10380                 }
10381
10382                 g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
10383                 break;
10384         }
10385         case MM_PLAYER_URI_TYPE_URL_HTTP:
10386         {
10387                 gchar *user_agent, *cookies, **cookie_list;
10388                 gint http_timeout = DEFAULT_HTTP_TIMEOUT;
10389                 user_agent = cookies = NULL;
10390                 cookie_list = NULL;
10391
10392                 element = gst_element_factory_make(player->ini.httpsrc_element, "http_streaming_source");
10393                 if (!element) {
10394                         LOGE("failed to create http streaming source element[%s].\n", player->ini.httpsrc_element);
10395                         break;
10396                 }
10397                 LOGD("using http streamming source [%s].\n", player->ini.httpsrc_element);
10398
10399                 /* get attribute */
10400                 mm_attrs_get_string_by_name(attrs, "streaming_cookie", &cookies);
10401                 mm_attrs_get_string_by_name(attrs, "streaming_user_agent", &user_agent);
10402
10403                 if (player->ini.http_timeout != DEFAULT_HTTP_TIMEOUT) {
10404                         LOGD("get timeout from ini\n");
10405                         http_timeout = player->ini.http_timeout;
10406                 }
10407
10408                 /* get attribute */
10409                 SECURE_LOGD("location : %s\n", player->profile.uri);
10410                 SECURE_LOGD("cookies : %s\n", cookies);
10411                 SECURE_LOGD("user_agent :  %s\n", user_agent);
10412                 LOGD("timeout : %d\n", http_timeout);
10413
10414                 /* setting property to streaming source */
10415                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
10416                 g_object_set(G_OBJECT(element), "timeout", http_timeout, NULL);
10417                 g_object_set(G_OBJECT(element), "blocksize", (unsigned long)(64*1024), NULL);
10418
10419                 /* parsing cookies */
10420                 if ((cookie_list = util_get_cookie_list((const char*)cookies)))
10421                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
10422                 if (user_agent)
10423                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
10424                 break;
10425         }
10426         default:
10427                 LOGE("not support uri type %d\n", player->profile.uri_type);
10428                 break;
10429         }
10430
10431         if (!element) {
10432                 LOGE("no source element was created.\n");
10433                 goto ERROR;
10434         }
10435
10436         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
10437                 LOGE("failed to add source element to pipeline\n");
10438                 gst_object_unref(GST_OBJECT(element));
10439                 element = NULL;
10440                 goto ERROR;
10441         }
10442
10443         /* take source element */
10444         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
10445         mainbin[MMPLAYER_M_SRC].gst = element;
10446
10447         element = NULL;
10448
10449         if (MMPLAYER_IS_HTTP_STREAMING(player)) {
10450                 if (player->streamer == NULL) {
10451                         player->streamer = __mm_player_streaming_create();
10452                         __mm_player_streaming_initialize(player->streamer);
10453                 }
10454
10455                 elemId = MMPLAYER_M_TYPEFIND;
10456                 element = gst_element_factory_make("typefind", "typefinder");
10457                 MMPLAYER_SIGNAL_CONNECT(player, element, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG, "have-type",
10458                         G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player);
10459         } else {
10460                 elemId = MMPLAYER_M_AUTOPLUG;
10461                 element = __mmplayer_create_decodebin(player);
10462         }
10463
10464         /* check autoplug element is OK */
10465         if (!element) {
10466                 LOGE("can not create element(%d)\n", elemId);
10467                 goto ERROR;
10468         }
10469
10470         if (gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element) == FALSE) {
10471                 LOGE("failed to add sinkbin to pipeline\n");
10472                 gst_object_unref(GST_OBJECT(element));
10473                 element = NULL;
10474                 goto ERROR;
10475         }
10476
10477         mainbin[elemId].id = elemId;
10478         mainbin[elemId].gst = element;
10479
10480         if (gst_element_link(mainbin[MMPLAYER_M_SRC].gst, mainbin[elemId].gst) == FALSE) {
10481                 LOGE("Failed to link src - autoplug(or typefind)\n");
10482                 goto ERROR;
10483         }
10484
10485         if (gst_element_set_state(mainbin[MMPLAYER_M_SRC].gst, target) == GST_STATE_CHANGE_FAILURE) {
10486                 LOGE("Failed to change state of src element\n");
10487                 goto ERROR;
10488         }
10489
10490         if (!MMPLAYER_IS_HTTP_STREAMING(player)) {
10491                 if (gst_element_set_state(mainbin[MMPLAYER_M_AUTOPLUG].gst, target) == GST_STATE_CHANGE_FAILURE) {
10492                         LOGE("Failed to change state of decodebin\n");
10493                         goto ERROR;
10494                 }
10495         } else {
10496                 if (gst_element_set_state(mainbin[MMPLAYER_M_TYPEFIND].gst, target) == GST_STATE_CHANGE_FAILURE) {
10497                         LOGE("Failed to change state of src element\n");
10498                         goto ERROR;
10499                 }
10500         }
10501
10502         player->gapless.stream_changed = TRUE;
10503         player->gapless.running = TRUE;
10504         MMPLAYER_FLEAVE();
10505         return;
10506
10507 ERROR:
10508         if (player) {
10509                 MMPLAYER_PLAYBACK_UNLOCK(player);
10510
10511                 if (!player->msg_posted) {
10512                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
10513                         player->msg_posted = TRUE;
10514                 }
10515         }
10516         return;
10517 }
10518
10519 static gboolean
10520 __mmplayer_deactivate_selector(mm_player_t *player, MMPlayerTrackType type)
10521 {
10522         mm_player_selector_t *selector = &player->selector[type];
10523         MMPlayerGstElement *sinkbin = NULL;
10524         enum MainElementID selectorId = MMPLAYER_M_NUM;
10525         enum MainElementID sinkId = MMPLAYER_M_NUM;
10526         GstPad *srcpad = NULL;
10527         GstPad *sinkpad = NULL;
10528         gboolean send_notice = FALSE;
10529
10530         MMPLAYER_FENTER();
10531         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
10532
10533         LOGD("type %d", type);
10534
10535         switch (type) {
10536         case MM_PLAYER_TRACK_TYPE_AUDIO:
10537                 selectorId = MMPLAYER_M_A_INPUT_SELECTOR;
10538                 sinkId = MMPLAYER_A_BIN;
10539                 sinkbin = player->pipeline->audiobin;
10540                 break;
10541         case MM_PLAYER_TRACK_TYPE_VIDEO:
10542                 selectorId = MMPLAYER_M_V_INPUT_SELECTOR;
10543                 sinkId = MMPLAYER_V_BIN;
10544                 sinkbin = player->pipeline->videobin;
10545                 send_notice = TRUE;
10546                 break;
10547         case MM_PLAYER_TRACK_TYPE_TEXT:
10548                 selectorId = MMPLAYER_M_T_INPUT_SELECTOR;
10549                 sinkId = MMPLAYER_T_BIN;
10550                 sinkbin = player->pipeline->textbin;
10551                 break;
10552         default:
10553                 LOGE("requested type is not supportable");
10554                 return FALSE;
10555                 break;
10556         }
10557
10558         if (player->pipeline->mainbin[selectorId].gst) {
10559                 gint n;
10560
10561                 srcpad = gst_element_get_static_pad(player->pipeline->mainbin[selectorId].gst, "src");
10562
10563                 if (selector->event_probe_id != 0)
10564                         gst_pad_remove_probe(srcpad, selector->event_probe_id);
10565                 selector->event_probe_id = 0;
10566
10567                 if ((sinkbin) && (sinkbin[sinkId].gst)) {
10568                         sinkpad = gst_element_get_static_pad(sinkbin[sinkId].gst, "sink");
10569
10570                         if (srcpad && sinkpad) {
10571                                 /* after getting drained signal there is no data flows, so no need to do pad_block */
10572                                 LOGD("unlink %s:%s, %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));
10573                                 gst_pad_unlink(srcpad, sinkpad);
10574
10575                                 /* send custom event to sink pad to handle it at video sink */
10576                                 if (send_notice) {
10577                                         LOGD("send custom event to sinkpad");
10578                                         GstStructure *s = gst_structure_new_empty("application/flush-buffer");
10579                                         GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_DOWNSTREAM, s);
10580                                         gst_pad_send_event(sinkpad, event);
10581                                 }
10582                         }
10583
10584                         gst_object_unref(sinkpad);
10585                         sinkpad = NULL;
10586                 }
10587                 gst_object_unref(srcpad);
10588                 srcpad = NULL;
10589
10590                 LOGD("selector release");
10591
10592                 /* release and unref requests pad from the selector */
10593                 for (n = 0; n < selector->channels->len; n++) {
10594                         GstPad *sinkpad = g_ptr_array_index(selector->channels, n);
10595                         gst_element_release_request_pad((player->pipeline->mainbin[selectorId].gst), sinkpad);
10596                 }
10597                 g_ptr_array_set_size(selector->channels, 0);
10598
10599                 gst_element_set_state(player->pipeline->mainbin[selectorId].gst, GST_STATE_NULL);
10600                 gst_bin_remove(GST_BIN_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), player->pipeline->mainbin[selectorId].gst);
10601
10602                 player->pipeline->mainbin[selectorId].gst = NULL;
10603                 selector = NULL;
10604         }
10605
10606         return TRUE;
10607 }
10608
10609 static void
10610 __mmplayer_deactivate_old_path(mm_player_t *player)
10611 {
10612         MMPLAYER_FENTER();
10613         MMPLAYER_RETURN_IF_FAIL(player);
10614
10615         if ((!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_AUDIO)) ||
10616                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_VIDEO)) ||
10617                 (!__mmplayer_deactivate_selector(player, MM_PLAYER_TRACK_TYPE_TEXT))) {
10618                 LOGE("deactivate selector error");
10619                 goto ERROR;
10620         }
10621
10622         _mmplayer_track_destroy(player);
10623         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
10624
10625         if (player->streamer) {
10626                 __mm_player_streaming_deinitialize(player->streamer);
10627                 __mm_player_streaming_destroy(player->streamer);
10628                 player->streamer = NULL;
10629         }
10630
10631         MMPLAYER_PLAYBACK_LOCK(player);
10632         MMPLAYER_NEXT_PLAY_THREAD_SIGNAL(player);
10633
10634         MMPLAYER_FLEAVE();
10635         return;
10636
10637 ERROR:
10638
10639         if (!player->msg_posted) {
10640                 MMMessageParamType msg = {0,};
10641
10642                 /*post error*/
10643                 msg.code = MM_ERROR_PLAYER_INTERNAL;
10644                 LOGE("next_uri_play> deactivate error");
10645
10646                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg);
10647                 player->msg_posted = TRUE;
10648         }
10649         return;
10650 }
10651
10652 int _mmplayer_set_file_buffering_path(MMHandleType hplayer, const char* file_path)
10653 {
10654         int result = MM_ERROR_NONE;
10655         mm_player_t* player = (mm_player_t*) hplayer;
10656         MMPLAYER_FENTER();
10657
10658         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10659
10660         if (file_path) {
10661                 player->http_file_buffering_path = (gchar*)file_path;
10662                 LOGD("temp file path: %s\n", player->http_file_buffering_path);
10663         }
10664         MMPLAYER_FLEAVE();
10665         return result;
10666 }
10667
10668 int _mmplayer_set_uri(MMHandleType hplayer, const char* uri)
10669 {
10670         int result = MM_ERROR_NONE;
10671         mm_player_t* player = (mm_player_t*) hplayer;
10672         MMPLAYER_FENTER();
10673
10674         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10675
10676         mm_attrs_set_string_by_name(player->attrs, "profile_uri", uri);
10677         if (mmf_attrs_commit(player->attrs)) {
10678                 LOGE("failed to commit the original uri.\n");
10679                 result = MM_ERROR_PLAYER_INTERNAL;
10680         } else {
10681                 if (_mmplayer_set_next_uri(hplayer, uri, TRUE) != MM_ERROR_NONE)
10682                         LOGE("failed to add the original uri in the uri list.\n");
10683         }
10684
10685         MMPLAYER_FLEAVE();
10686         return result;
10687 }
10688
10689 int _mmplayer_set_next_uri(MMHandleType hplayer, const char* uri, bool is_first_path)
10690 {
10691         mm_player_t* player = (mm_player_t*) hplayer;
10692         guint num_of_list = 0;
10693
10694         MMPLAYER_FENTER();
10695
10696         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10697         MMPLAYER_RETURN_VAL_IF_FAIL(uri, MM_ERROR_INVALID_ARGUMENT);
10698
10699         if (player->pipeline && player->pipeline->textbin) {
10700                 LOGE("subtitle path is enabled.\n");
10701                 return MM_ERROR_PLAYER_INVALID_STATE;
10702         }
10703
10704         num_of_list = g_list_length(player->uri_info.uri_list);
10705
10706         if (is_first_path == TRUE) {
10707                 if (num_of_list == 0) {
10708                         player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10709                         LOGD("add original path : %s", uri);
10710                 } else {
10711                         player->uri_info.uri_list = g_list_delete_link(player->uri_info.uri_list, g_list_nth(player->uri_info.uri_list, 0));
10712                         player->uri_info.uri_list = g_list_insert(player->uri_info.uri_list, g_strdup(uri), 0);
10713
10714                         LOGD("change original path : %s", uri);
10715                 }
10716         } else {
10717                 MMHandleType attrs = 0;
10718                 attrs = MMPLAYER_GET_ATTRS(player);
10719
10720                 if (num_of_list == 0) {
10721                         char *original_uri = NULL;
10722
10723                         if (attrs) {
10724                                 mm_attrs_get_string_by_name(attrs, "profile_uri", &original_uri);
10725
10726                                 if (!original_uri) {
10727                                         LOGE("there is no original uri.");
10728                                         return MM_ERROR_PLAYER_INVALID_STATE;
10729                                 }
10730
10731                                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(original_uri));
10732                                 player->uri_info.uri_idx = 0;
10733
10734                                 LOGD("add original path at first : %s(%d)", original_uri);
10735                         }
10736                 }
10737
10738                 player->uri_info.uri_list = g_list_append(player->uri_info.uri_list, g_strdup(uri));
10739                 LOGD("add new path : %s(total num of list = %d)", uri, g_list_length(player->uri_info.uri_list));
10740         }
10741
10742         MMPLAYER_FLEAVE();
10743         return MM_ERROR_NONE;
10744 }
10745
10746 int _mmplayer_get_next_uri(MMHandleType hplayer, char** uri)
10747 {
10748         mm_player_t* player = (mm_player_t*) hplayer;
10749         char *next_uri = NULL;
10750         guint num_of_list = 0;
10751
10752         MMPLAYER_FENTER();
10753         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
10754
10755         num_of_list = g_list_length(player->uri_info.uri_list);
10756
10757         if (num_of_list > 0) {
10758                 gint uri_idx = player->uri_info.uri_idx;
10759
10760                 if (uri_idx < num_of_list-1)
10761                         uri_idx++;
10762                 else
10763                         uri_idx = 0;
10764
10765                 next_uri = g_list_nth_data(player->uri_info.uri_list, uri_idx);
10766                 LOGE("next uri idx : %d, uri = %s\n", uri_idx, next_uri);
10767
10768                 *uri = g_strdup(next_uri);
10769         }
10770
10771         MMPLAYER_FLEAVE();
10772         return MM_ERROR_NONE;
10773 }
10774
10775 static void
10776 __mmplayer_gst_decode_unknown_type(GstElement *elem,  GstPad* pad,
10777 GstCaps *caps, gpointer data)
10778 {
10779         mm_player_t* player = (mm_player_t*)data;
10780         const gchar* klass = NULL;
10781         const gchar* mime = NULL;
10782         gchar* caps_str = NULL;
10783
10784         klass = gst_element_factory_get_metadata(gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
10785         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10786         caps_str = gst_caps_to_string(caps);
10787
10788         LOGW("unknown type of caps : %s from %s",
10789                                         caps_str, GST_ELEMENT_NAME(elem));
10790
10791         MMPLAYER_FREEIF(caps_str);
10792
10793         /* There is no available codec. */
10794         __mmplayer_check_not_supported_codec(player, klass, mime);
10795 }
10796
10797 static gboolean
10798 __mmplayer_gst_decode_autoplug_continue(GstElement *bin,  GstPad* pad,
10799 GstCaps * caps,  gpointer data)
10800 {
10801         mm_player_t* player = (mm_player_t*)data;
10802         const char* mime = NULL;
10803         gboolean ret = TRUE;
10804
10805         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
10806         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
10807
10808         if (g_str_has_prefix(mime, "audio")) {
10809                 GstStructure* caps_structure = NULL;
10810                 gint samplerate = 0;
10811                 gint channels = 0;
10812                 gchar *caps_str = NULL;
10813
10814                 caps_structure = gst_caps_get_structure(caps, 0);
10815                 gst_structure_get_int(caps_structure, "rate", &samplerate);
10816                 gst_structure_get_int(caps_structure, "channels", &channels);
10817
10818                 if ((channels > 0 && samplerate == 0)) {
10819                         LOGD("exclude audio...");
10820                         ret = FALSE;
10821                 }
10822
10823                 caps_str = gst_caps_to_string(caps);
10824                 /* set it directly because not sent by TAG */
10825                 if (g_strrstr(caps_str, "mobile-xmf"))
10826                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", "mobile-xmf");
10827                 MMPLAYER_FREEIF(caps_str);
10828         } else if (g_str_has_prefix(mime, "video") && !player->ini.video_playback_supported) {
10829                 MMMessageParamType msg_param;
10830                 memset(&msg_param, 0, sizeof(MMMessageParamType));
10831                 msg_param.code = MM_ERROR_NOT_SUPPORT_API;
10832                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
10833                 LOGD("video file is not supported on this device");
10834                 ret = FALSE;
10835         } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
10836                 LOGD("already video linked");
10837                 ret = FALSE;
10838         } else {
10839                 LOGD("found new stream");
10840         }
10841
10842         return ret;
10843 }
10844
10845 static int
10846 __mmplayer_check_codec_info(mm_player_t* player, const char* klass, GstCaps* caps, char* factory_name)
10847 {
10848         int ret = MM_ERROR_NONE;
10849         int idx = 0;
10850         int codec_type = MM_PLAYER_CODEC_TYPE_DEFAULT;
10851
10852         if ((g_strrstr(klass, "Codec/Decoder/Audio"))) {
10853                 GstStructure* str = NULL;
10854                 gint channels = 0;
10855                 mm_attrs_get_int_by_name(player->attrs, "audio_codec_type", &codec_type);
10856
10857                 LOGD("audio codec type: %d", codec_type);
10858                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
10859                         /* sw codec will be skipped */
10860                         for (idx = 0; player->ini.audiocodec_element_sw[idx][0] != '\0'; idx++) {
10861                                 if (strstr(factory_name, player->ini.audiocodec_element_sw[idx])) {
10862                                         LOGW("skipping sw acodec:[%s] by codec type", factory_name);
10863                                         ret = MM_ERROR_PLAYER_INTERNAL;
10864                                         goto DONE;
10865                                 }
10866                         }
10867                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
10868                         /* hw codec will be skipped */
10869                         if (strcmp(player->ini.audiocodec_element_hw, "") &&
10870                             g_strrstr(factory_name, player->ini.audiocodec_element_hw)) {
10871                                 LOGW("skipping hw acodec:[%s] by codec type", factory_name);
10872                                 ret = MM_ERROR_PLAYER_INTERNAL;
10873                                 goto DONE;
10874                         }
10875                 }
10876
10877                 str = gst_caps_get_structure(caps, 0);
10878                 if (str) {
10879                         gst_structure_get_int(str, "channels", &channels);
10880
10881                         LOGD("check audio ch : %d %d\n", player->max_audio_channels, channels);
10882                         if (player->max_audio_channels < channels)
10883                                 player->max_audio_channels = channels;
10884                 }
10885                 /* set stream information */
10886                 if (!player->audiodec_linked)
10887                         __mmplayer_set_audio_attrs(player, caps);
10888
10889                 /* update codec info */
10890                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
10891                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
10892                 player->audiodec_linked = 1;
10893
10894         } else if (g_strrstr(klass, "Codec/Decoder/Video")) {
10895
10896                 mm_attrs_get_int_by_name(player->attrs, "video_codec_type", &codec_type);
10897
10898                 LOGD("video codec type: %d", codec_type);
10899                 if (codec_type == MM_PLAYER_CODEC_TYPE_HW) {
10900                         /* sw codec is skipped */
10901                         for (idx = 0; player->ini.videocodec_element_sw[idx][0] != '\0'; idx++) {
10902                                 if (strstr(factory_name, player->ini.videocodec_element_sw[idx])) {
10903                                         LOGW("skipping sw vcodec:[%s] by codec type", factory_name);
10904                                         ret = MM_ERROR_PLAYER_INTERNAL;
10905                                         goto DONE;
10906                                 }
10907                         }
10908                 } else if (codec_type == MM_PLAYER_CODEC_TYPE_SW) {
10909                         /* hw codec is skipped */
10910                         if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
10911                                 LOGW("skipping hw vcodec:[%s] by codec type", factory_name);
10912                                 ret = MM_ERROR_PLAYER_INTERNAL;
10913                                 goto DONE;
10914                         }
10915                 }
10916
10917                 if ((strlen(player->ini.videocodec_element_hw) > 0) &&
10918                         (g_strrstr(factory_name, player->ini.videocodec_element_hw))) {
10919
10920                         /* mark video decoder for acquire */
10921                         if (player->video_decoder_resource == NULL) {
10922                                 if (mm_resource_manager_mark_for_acquire(player->resource_manager,
10923                                                 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
10924                                                 MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
10925                                                 &player->video_decoder_resource)
10926                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
10927                                         LOGE("could not mark video_decoder resource for acquire");
10928                                         ret = MM_ERROR_PLAYER_INTERNAL;
10929                                         goto DONE;
10930                                 }
10931                         } else {
10932                                 LOGW("video decoder resource is already acquired, skip it.");
10933                                 ret = MM_ERROR_PLAYER_INTERNAL;
10934                                 goto DONE;
10935                         }
10936
10937                         player->interrupted_by_resource = FALSE;
10938                         /* acquire resources for video playing */
10939                         if (mm_resource_manager_commit(player->resource_manager)
10940                                         != MM_RESOURCE_MANAGER_ERROR_NONE) {
10941                                 LOGE("could not acquire resources for video decoding\n");
10942                                 ret = MM_ERROR_PLAYER_INTERNAL;
10943                                 goto DONE;
10944                         }
10945                 }
10946
10947                 /* update codec info */
10948                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
10949                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
10950                 player->videodec_linked = 1;
10951         }
10952
10953 DONE:
10954         return ret;
10955 }
10956
10957 static gint
10958 __mmplayer_gst_decode_autoplug_select(GstElement *bin,  GstPad* pad,
10959 GstCaps* caps, GstElementFactory* factory, gpointer data)
10960 {
10961         /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed
10962          We are defining our own and will be removed when it actually exposed */
10963         typedef enum {
10964                 GST_AUTOPLUG_SELECT_TRY,
10965                 GST_AUTOPLUG_SELECT_EXPOSE,
10966                 GST_AUTOPLUG_SELECT_SKIP
10967         } GstAutoplugSelectResult;
10968
10969         GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
10970         mm_player_t* player = (mm_player_t*)data;
10971
10972         gchar* factory_name = NULL;
10973         gchar* caps_str = NULL;
10974         const gchar* klass = NULL;
10975         gint idx = 0;
10976
10977         factory_name = GST_OBJECT_NAME(factory);
10978         klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
10979         caps_str = gst_caps_to_string(caps);
10980
10981         LOGD("[handle: %p] found new element [%s] to link", player, factory_name);
10982
10983         /* store type string */
10984         if (player->type == NULL) {
10985                 player->type = gst_caps_to_string(caps);
10986                 __mmplayer_update_content_type_info(player);
10987         }
10988
10989         /* filtering exclude keyword */
10990         for (idx = 0; player->ini.exclude_element_keyword[idx][0] != '\0'; idx++) {
10991                 if (strstr(factory_name, player->ini.exclude_element_keyword[idx])) {
10992                         LOGW("skipping [%s] by exculde keyword [%s]\n",
10993                                         factory_name, player->ini.exclude_element_keyword[idx]);
10994
10995                         result = GST_AUTOPLUG_SELECT_SKIP;
10996                         goto DONE;
10997                 }
10998         }
10999
11000         /* exclude webm format */
11001         /* NOTE : MSL have to post MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT
11002          * because webm format is not supportable.
11003          * If webm is disabled in "autoplug-continue", there is no state change
11004          * failure or error because the decodebin will expose the pad directly.
11005          * It make MSL invoke _prepare_async_callback.
11006          * So, we need to disable webm format in "autoplug-select" */
11007         if (caps_str && strstr(caps_str, "webm")) {
11008                 LOGW("webm is not supported");
11009                 result = GST_AUTOPLUG_SELECT_SKIP;
11010                 goto DONE;
11011         }
11012
11013         /* check factory class for filtering */
11014         /* NOTE : msl don't need to use image plugins.
11015          * So, those plugins should be skipped for error handling.
11016          */
11017         if (g_strrstr(klass, "Codec/Decoder/Image")) {
11018                 LOGD("skipping [%s] by not required\n", factory_name);
11019                 result = GST_AUTOPLUG_SELECT_SKIP;
11020                 goto DONE;
11021         }
11022
11023         if ((MMPLAYER_IS_MS_BUFF_SRC(player)) &&
11024                 (g_strrstr(klass, "Codec/Demuxer") || (g_strrstr(klass, "Codec/Parser")))) {
11025                 // TO CHECK : subtitle if needed, add subparse exception.
11026                 LOGD("skipping parser/demuxer [%s] in es player by not required\n", factory_name);
11027                 result = GST_AUTOPLUG_SELECT_SKIP;
11028                 goto DONE;
11029         }
11030
11031         if (g_strrstr(factory_name, "mpegpsdemux")) {
11032                 LOGD("skipping PS container - not support\n");
11033                 result = GST_AUTOPLUG_SELECT_SKIP;
11034                 goto DONE;
11035         }
11036
11037         if (g_strrstr(factory_name, "mssdemux"))
11038                 player->smooth_streaming = TRUE;
11039
11040         if ((g_strrstr(klass, "Codec/Parser/Converter/Video")) ||
11041                 (g_strrstr(klass, "Codec/Decoder/Video"))) {
11042                 gint stype = 0;
11043                 gint width = 0;
11044                 GstStructure *str = NULL;
11045                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &stype);
11046
11047                 /* don't make video because of not required */
11048                 if ((stype == MM_DISPLAY_SURFACE_NULL) &&
11049                         (player->set_mode.media_packet_video_stream == FALSE)) {
11050                         LOGD("no video because it's not required. -> return expose");
11051                         result = GST_AUTOPLUG_SELECT_EXPOSE;
11052                         goto DONE;
11053                 }
11054
11055                 /* get w/h for omx state-tune */
11056                 /* FIXME: deprecated? */
11057                 str = gst_caps_get_structure(caps, 0);
11058                 gst_structure_get_int(str, "width", &width);
11059
11060                 if (width != 0) {
11061                         if (player->v_stream_caps) {
11062                                 gst_caps_unref(player->v_stream_caps);
11063                                 player->v_stream_caps = NULL;
11064                         }
11065
11066                         player->v_stream_caps = gst_caps_copy(caps);
11067                         LOGD("take caps for video state tune");
11068                         MMPLAYER_LOG_GST_CAPS_TYPE(player->v_stream_caps);
11069                 }
11070         }
11071
11072         if (g_strrstr(klass, "Codec/Decoder")) {
11073                 if (__mmplayer_check_codec_info(player, klass, caps, factory_name) != MM_ERROR_NONE) {
11074                         LOGD("skipping %s codec", factory_name);
11075                         result = GST_AUTOPLUG_SELECT_SKIP;
11076                         goto DONE;
11077                 }
11078         }
11079
11080 DONE:
11081         MMPLAYER_FREEIF(caps_str);
11082
11083         return result;
11084 }
11085
11086 static void
11087 __mmplayer_gst_decode_pad_removed(GstElement *elem,  GstPad* new_pad,
11088 gpointer data)
11089 {
11090         //mm_player_t* player = (mm_player_t*)data;
11091         GstCaps* caps = NULL;
11092
11093         LOGD("[Decodebin2] pad-removed signal\n");
11094
11095         caps = gst_pad_query_caps(new_pad, NULL);
11096         if (caps) {
11097                 gchar* caps_str = NULL;
11098                 caps_str = gst_caps_to_string(caps);
11099
11100                 LOGD("pad removed caps : %s from %s", caps_str, GST_ELEMENT_NAME(elem));
11101
11102                 MMPLAYER_FREEIF(caps_str);
11103                 gst_caps_unref(caps);
11104         }
11105 }
11106
11107 static void
11108 __mmplayer_gst_decode_drained(GstElement *bin, gpointer data)
11109 {
11110         mm_player_t* player = (mm_player_t*)data;
11111         GstIterator *iter = NULL;
11112         GValue item = { 0, };
11113         GstPad *pad = NULL;
11114         gboolean done = FALSE;
11115         gboolean is_all_drained = TRUE;
11116
11117         MMPLAYER_FENTER();
11118         MMPLAYER_RETURN_IF_FAIL(player);
11119
11120         LOGD("__mmplayer_gst_decode_drained");
11121
11122         if (player->use_deinterleave == TRUE) {
11123                 LOGD("group playing mode.");
11124                 return;
11125         }
11126
11127         if (!MMPLAYER_CMD_TRYLOCK(player)) {
11128                 LOGW("Fail to get cmd lock");
11129                 return;
11130         }
11131
11132         if (!player->gapless.reconfigure && /* If it is already checked, skip verify. */
11133                 !__mmplayer_verify_next_play_path(player)) {
11134                 LOGD("decoding is finished.");
11135                 __mmplayer_reset_gapless_state(player);
11136                 MMPLAYER_CMD_UNLOCK(player);
11137                 return;
11138         }
11139
11140         player->gapless.reconfigure = TRUE;
11141
11142         /* check decodebin src pads whether they received EOS or not */
11143         iter = gst_element_iterate_src_pads(player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
11144
11145         while (!done) {
11146                 switch (gst_iterator_next(iter, &item)) {
11147                 case GST_ITERATOR_OK:
11148                         pad = g_value_get_object(&item);
11149                         if (pad && !GST_PAD_IS_EOS(pad)) {
11150                                 LOGW("[%s:%s] not received EOS yet.", GST_DEBUG_PAD_NAME(pad));
11151                                 is_all_drained = FALSE;
11152                                 break;
11153                         }
11154                         g_value_reset(&item);
11155                         break;
11156                 case GST_ITERATOR_RESYNC:
11157                         gst_iterator_resync(iter);
11158                         break;
11159                 case GST_ITERATOR_ERROR:
11160                 case GST_ITERATOR_DONE:
11161                         done = TRUE;
11162                         break;
11163                 }
11164         }
11165         g_value_unset(&item);
11166         gst_iterator_free(iter);
11167
11168         if (!is_all_drained) {
11169                 LOGD("Wait util the all pads get EOS.");
11170                 MMPLAYER_CMD_UNLOCK(player);
11171                 MMPLAYER_FLEAVE();
11172                 return;
11173         }
11174
11175         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_AUDIO] = FALSE;
11176         player->gapless.update_segment[MM_PLAYER_TRACK_TYPE_VIDEO] = FALSE;
11177
11178         /* deactivate pipeline except sinkbins to set up the new pipeline of next uri*/
11179         MMPLAYER_POST_MSG(player, MM_MESSAGE_GAPLESS_CONSTRUCTION, NULL); /* post message for gapless */
11180         __mmplayer_deactivate_old_path(player);
11181         MMPLAYER_CMD_UNLOCK(player);
11182
11183         MMPLAYER_FLEAVE();
11184 }
11185
11186 static void
11187 __mmplayer_gst_element_added(GstElement *bin, GstElement *element, gpointer data)
11188 {
11189         mm_player_t* player = (mm_player_t*)data;
11190         const gchar* klass = NULL;
11191         gchar* factory_name = NULL;
11192
11193         klass = gst_element_factory_get_metadata(gst_element_get_factory(element), GST_ELEMENT_METADATA_KLASS);
11194         factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
11195
11196         LOGD("new elem klass: %s, factory_name: %s, new elem name : %s\n", klass, factory_name, GST_ELEMENT_NAME(element));
11197
11198         if (__mmplayer_add_dump_buffer_probe(player, element))
11199                 LOGD("add buffer probe");
11200
11201         //<-
11202         if (g_strrstr(klass, "Codec/Decoder/Audio")) {
11203                 gchar* selected = NULL;
11204                 selected = g_strdup(GST_ELEMENT_NAME(element));
11205                 player->audio_decoders = g_list_append(player->audio_decoders, selected);
11206         }
11207         //-> temp code
11208
11209         if (g_strrstr(klass, "Parser")) {
11210                 gchar* selected = NULL;
11211
11212                 selected = g_strdup(factory_name);
11213                 player->parsers = g_list_append(player->parsers, selected);
11214         }
11215
11216         if (g_strrstr(klass, "Demuxer/Adaptive")) {
11217                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].id = MMPLAYER_M_ADAPTIVE_DEMUX;
11218                 player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst = element;
11219
11220                 LOGD("set max variant limit: %d, %d %d", player->adaptive_info.limit.bandwidth,
11221                                                 player->adaptive_info.limit.width, player->adaptive_info.limit.height);
11222
11223                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
11224                                                 "max-bandwidth", player->adaptive_info.limit.bandwidth,
11225                                                 "max-video-width", player->adaptive_info.limit.width,
11226                                                 "max-video-height", player->adaptive_info.limit.height, NULL);
11227
11228         } else if (g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse")) {
11229                 /* FIXIT : first value will be overwritten if there's more
11230                  * than 1 demuxer/parser
11231                  */
11232
11233                 //LOGD("plugged element is demuxer. take it\n");
11234                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
11235                 player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst = element;
11236
11237                 /*Added for multi audio support */ // Q. del?
11238                 if (g_strrstr(klass, "Demux")) {
11239                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].id = MMPLAYER_M_DEMUX_EX;
11240                         player->pipeline->mainbin[MMPLAYER_M_DEMUX_EX].gst = element;
11241                 }
11242         }
11243
11244         if (g_strrstr(factory_name, "asfdemux") || g_strrstr(factory_name, "qtdemux") || g_strrstr(factory_name, "avidemux")) {
11245                 int surface_type = 0;
11246
11247                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &surface_type);
11248         }
11249
11250         // to support trust-zone only
11251         if (g_strrstr(factory_name, "asfdemux")) {
11252                 LOGD("set file-location %s\n", player->profile.uri);
11253                 g_object_set(G_OBJECT(element), "file-location", player->profile.uri, NULL);
11254
11255                 if (player->video_hub_download_mode == TRUE)
11256                         g_object_set(G_OBJECT(element), "downloading-mode", player->video_hub_download_mode, NULL);
11257         } else if (g_strrstr(factory_name, "legacyh264parse")) {
11258                 LOGD("[%s] output-format to legacyh264parse\n", "mssdemux");
11259                 g_object_set(G_OBJECT(element), "output-format", 1, NULL); /* NALU/Byte Stream format */
11260         } else if (g_strrstr(factory_name, "mpegaudioparse")) {
11261                 if ((MMPLAYER_IS_HTTP_STREAMING(player)) &&
11262                         (__mmplayer_is_only_mp3_type(player->type))) {
11263                         LOGD("[mpegaudioparse] set streaming pull mode.");
11264                         g_object_set(G_OBJECT(element), "http-pull-mp3dec", TRUE, NULL);
11265                 }
11266         } else if (g_strrstr(factory_name, player->ini.videocodec_element_hw)) {
11267                 player->pipeline->mainbin[MMPLAYER_M_DEC1].gst = element;
11268         }
11269
11270         if ((player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst) &&
11271                 (g_strrstr(GST_ELEMENT_NAME(element), "multiqueue"))) {
11272                 LOGD("plugged element is multiqueue. take it\n");
11273
11274                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].id = MMPLAYER_M_DEMUXED_S_BUFFER;
11275                 player->pipeline->mainbin[MMPLAYER_M_DEMUXED_S_BUFFER].gst = element;
11276
11277                 if (!MMPLAYER_IS_HTTP_PD(player) &&
11278                         ((MMPLAYER_IS_HTTP_STREAMING(player)) ||
11279                         (MMPLAYER_IS_HTTP_LIVE_STREAMING(player)))) {
11280                         /* in case of multiqueue, max bytes size is defined with fixed value in mm_player_streaming.h*/
11281                         __mm_player_streaming_set_multiqueue(player->streamer,
11282                                 element,
11283                                 TRUE,
11284                                 player->ini.http_buffering_time,
11285                                 1.0,
11286                                 player->ini.http_buffering_limit);
11287
11288                         __mm_player_streaming_sync_property(player->streamer, player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst);
11289                 }
11290         }
11291
11292         return;
11293 }
11294
11295 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
11296 {
11297         MMPLAYER_FENTER();
11298         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11299
11300         if (MMPLAYER_IS_STREAMING(player))
11301                 return FALSE;
11302
11303         /* This callback can be set to music player only. */
11304         if ((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO) {
11305                 LOGW("audio callback is not supported for video");
11306                 return FALSE;
11307         }
11308
11309         if (player->audio_stream_cb) {
11310                 GstPad *pad = NULL;
11311
11312                 pad = gst_element_get_static_pad(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
11313
11314                 if (!pad) {
11315                         LOGE("failed to get sink pad from audiosink to probe data\n");
11316                         return FALSE;
11317                 }
11318                 player->audio_cb_probe_id = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
11319                         __mmplayer_audio_stream_probe, player, NULL);
11320
11321                 gst_object_unref(pad);
11322
11323                 pad = NULL;
11324         } else {
11325                 LOGE("There is no audio callback to configure.\n");
11326                 return FALSE;
11327         }
11328
11329         MMPLAYER_FLEAVE();
11330
11331         return TRUE;
11332 }
11333
11334 static void
11335 __mmplayer_release_misc(mm_player_t* player)
11336 {
11337         int i;
11338         bool cur_mode = player->set_mode.rich_audio;
11339         MMPLAYER_FENTER();
11340
11341         MMPLAYER_RETURN_IF_FAIL(player);
11342
11343         player->video_stream_cb = NULL;
11344         player->video_stream_cb_user_param = NULL;
11345         player->video_stream_prerolled = FALSE;
11346
11347         player->audio_stream_cb = NULL;
11348         player->audio_stream_render_cb_ex = NULL;
11349         player->audio_stream_cb_user_param = NULL;
11350         player->audio_stream_sink_sync = false;
11351
11352         player->video_stream_changed_cb = NULL;
11353         player->video_stream_changed_cb_user_param = NULL;
11354
11355         player->audio_stream_changed_cb = NULL;
11356         player->audio_stream_changed_cb_user_param = NULL;
11357
11358         player->sent_bos = FALSE;
11359         player->playback_rate = DEFAULT_PLAYBACK_RATE;
11360
11361         player->doing_seek = FALSE;
11362
11363         player->total_bitrate = 0;
11364         player->total_maximum_bitrate = 0;
11365
11366         player->not_found_demuxer = 0;
11367
11368         player->last_position = 0;
11369         player->duration = 0;
11370         player->http_content_size = 0;
11371         player->not_supported_codec = MISSING_PLUGIN_NONE;
11372         player->can_support_codec = FOUND_PLUGIN_NONE;
11373         player->pending_seek.is_pending = FALSE;
11374         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
11375         player->pending_seek.pos = 0;
11376         player->msg_posted = FALSE;
11377         player->has_many_types = FALSE;
11378         player->max_audio_channels = 0;
11379         player->video_share_api_delta = 0;
11380         player->video_share_clock_delta = 0;
11381         player->is_subtitle_force_drop = FALSE;
11382         player->play_subtitle = FALSE;
11383         player->adjust_subtitle_pos = 0;
11384         player->last_multiwin_status = FALSE;
11385         player->has_closed_caption = FALSE;
11386         player->set_mode.media_packet_video_stream = FALSE;
11387         player->profile.uri_type = MM_PLAYER_URI_TYPE_NONE;
11388         memset(&player->set_mode, 0, sizeof(MMPlayerSetMode));
11389         /* recover mode */
11390         player->set_mode.rich_audio = cur_mode;
11391
11392         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) {
11393                 player->bitrate[i] = 0;
11394                 player->maximum_bitrate[i] = 0;
11395         }
11396
11397         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
11398
11399         /* remove media stream cb(appsrc cb) */
11400         for (i = 0; i < MM_PLAYER_STREAM_TYPE_MAX; i++) {
11401                 player->media_stream_buffer_status_cb[i] = NULL;
11402                 player->media_stream_seek_data_cb[i] = NULL;
11403                 player->buffer_cb_user_param[i] = NULL;
11404                 player->seek_cb_user_param[i] = NULL;
11405         }
11406         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
11407
11408         /* free memory related to audio effect */
11409         MMPLAYER_FREEIF(player->audio_effect_info.custom_ext_level_for_plugin);
11410
11411         if (player->adaptive_info.var_list) {
11412                 g_list_free_full(player->adaptive_info.var_list, g_free);
11413                 player->adaptive_info.var_list = NULL;
11414         }
11415
11416         player->adaptive_info.limit.bandwidth = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11417         player->adaptive_info.limit.width = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11418         player->adaptive_info.limit.height = ADAPTIVE_VARIANT_DEFAULT_VALUE;
11419
11420         /* Reset video360 settings to their defaults in case if the pipeline is to be
11421          * re-created.
11422          * */
11423         player->video360_metadata.is_spherical = -1;
11424         player->is_openal_plugin_used = FALSE;
11425
11426         player->is_content_spherical = FALSE;
11427         player->is_video360_enabled = TRUE;
11428         player->video360_metadata.projection_type = VIDEO360_PROJECTION_TYPE_EQUIRECTANGULAR;
11429         player->video360_metadata.stereo_mode = VIDEO360_MODE_MONOSCOPIC;
11430         player->video360_yaw_radians = PLAYER_SPHERICAL_DEFAULT_YAW;
11431         player->video360_pitch_radians = PLAYER_SPHERICAL_DEFAULT_PITCH;
11432         player->video360_zoom = 1.0f;
11433         player->video360_horizontal_fov = PLAYER_SPHERICAL_DEFAULT_H_FOV;
11434         player->video360_vertical_fov = PLAYER_SPHERICAL_DEFAULT_V_FOV;
11435
11436         player->sound.rg_enable = false;
11437
11438         MMPLAYER_FLEAVE();
11439 }
11440
11441 static void
11442 __mmplayer_release_misc_post(mm_player_t* player)
11443 {
11444         char *original_uri = NULL;
11445         MMPLAYER_FENTER();
11446
11447         /* player->pipeline is already released before. */
11448
11449         MMPLAYER_RETURN_IF_FAIL(player);
11450
11451         mm_attrs_set_int_by_name(player->attrs, "content_video_found", 0);
11452
11453         /* clean found parsers */
11454         if (player->parsers) {
11455                 GList *parsers = player->parsers;
11456                 for (; parsers; parsers = g_list_next(parsers)) {
11457                         gchar *name = parsers->data;
11458                         MMPLAYER_FREEIF(name);
11459                 }
11460                 g_list_free(player->parsers);
11461                 player->parsers = NULL;
11462         }
11463
11464         /* clean found audio decoders */
11465         if (player->audio_decoders) {
11466                 GList *a_dec = player->audio_decoders;
11467                 for (; a_dec; a_dec = g_list_next(a_dec)) {
11468                         gchar *name = a_dec->data;
11469                         MMPLAYER_FREEIF(name);
11470                 }
11471                 g_list_free(player->audio_decoders);
11472                 player->audio_decoders = NULL;
11473         }
11474
11475         /* clean the uri list except original uri */
11476         if (player->uri_info.uri_list) {
11477                 original_uri = g_list_nth_data(player->uri_info.uri_list, 0);
11478
11479                 if (player->attrs) {
11480                         mm_attrs_set_string_by_name(player->attrs, "profile_uri", original_uri);
11481                         LOGD("restore original uri = %s\n", original_uri);
11482
11483                         if (mmf_attrs_commit(player->attrs))
11484                                 LOGE("failed to commit the original uri.\n");
11485                 }
11486
11487                 GList *uri_list = player->uri_info.uri_list;
11488                 for (; uri_list; uri_list = g_list_next(uri_list)) {
11489                         gchar *uri = uri_list->data;
11490                         MMPLAYER_FREEIF(uri);
11491                 }
11492                 g_list_free(player->uri_info.uri_list);
11493                 player->uri_info.uri_list = NULL;
11494         }
11495
11496         /* clear the audio stream buffer list */
11497         __mmplayer_audio_stream_clear_buffer(player, FALSE);
11498
11499         /* clear the video stream bo list */
11500         __mmplayer_video_stream_destroy_bo_list(player);
11501         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX);
11502
11503         if (player->profile.input_mem.buf) {
11504                 free(player->profile.input_mem.buf);
11505                 player->profile.input_mem.buf = NULL;
11506         }
11507         player->profile.input_mem.len = 0;
11508         player->profile.input_mem.offset = 0;
11509
11510         player->uri_info.uri_idx = 0;
11511         MMPLAYER_FLEAVE();
11512 }
11513
11514 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
11515 {
11516         GstElement *element = NULL;
11517         GstPad *sinkpad;
11518
11519         LOGD("creating %s to plug\n", name);
11520
11521         element = gst_element_factory_make(name, NULL);
11522         if (!element) {
11523                 LOGE("failed to create queue\n");
11524                 return NULL;
11525         }
11526
11527         if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY)) {
11528                 LOGE("failed to set state READY to %s\n", name);
11529                 gst_object_unref(element);
11530                 return NULL;
11531         }
11532
11533         if (!gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element)) {
11534                 LOGE("failed to add %s\n", name);
11535                 gst_object_unref(element);
11536                 return NULL;
11537         }
11538
11539         sinkpad = gst_element_get_static_pad(element, "sink");
11540
11541         if (GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad)) {
11542                 LOGE("failed to link %s\n", name);
11543                 gst_object_unref(sinkpad);
11544                 gst_object_unref(element);
11545                 return NULL;
11546         }
11547
11548         LOGD("linked %s to pipeline successfully\n", name);
11549
11550         gst_object_unref(sinkpad);
11551
11552         return element;
11553 }
11554
11555 gboolean
11556 __mmplayer_check_subtitle(mm_player_t* player)
11557 {
11558         MMHandleType attrs = 0;
11559         char *subtitle_uri = NULL;
11560
11561         MMPLAYER_FENTER();
11562
11563         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11564
11565         /* get subtitle attribute */
11566         attrs = MMPLAYER_GET_ATTRS(player);
11567         if (!attrs)
11568                 return FALSE;
11569
11570         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
11571         if (!subtitle_uri || !strlen(subtitle_uri))
11572                 return FALSE;
11573
11574         LOGD("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
11575         player->is_external_subtitle_present = TRUE;
11576
11577         MMPLAYER_FLEAVE();
11578
11579         return TRUE;
11580 }
11581
11582 static gboolean
11583 __mmplayer_can_extract_pcm(mm_player_t* player)
11584 {
11585         MMHandleType attrs = 0;
11586         gboolean sound_extraction = FALSE;
11587
11588         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11589
11590         attrs = MMPLAYER_GET_ATTRS(player);
11591         if (!attrs) {
11592                 LOGE("fail to get attributes.");
11593                 return FALSE;
11594         }
11595
11596         /* get sound_extraction property */
11597         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
11598
11599         if (!sound_extraction) {
11600                 LOGD("checking pcm extraction mode : %d ", sound_extraction);
11601                 return FALSE;
11602         }
11603
11604         return TRUE;
11605 }
11606
11607 static gboolean
11608 __mmplayer_handle_streaming_error(mm_player_t* player, GstMessage * message)
11609 {
11610         LOGD("\n");
11611         MMMessageParamType msg_param;
11612         gchar *msg_src_element = NULL;
11613         GstStructure *s = NULL;
11614         guint error_id = 0;
11615         gchar *error_string = NULL;
11616
11617         MMPLAYER_FENTER();
11618
11619         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11620         MMPLAYER_RETURN_VAL_IF_FAIL(message, FALSE);
11621
11622         s = gst_structure_copy(gst_message_get_structure(message));
11623
11624
11625         if (!gst_structure_get_uint(s, "error_id", &error_id))
11626                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
11627
11628         switch (error_id) {
11629         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
11630                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
11631                 break;
11632         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
11633                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
11634                 break;
11635         case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
11636                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
11637                 break;
11638         case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
11639                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
11640                 break;
11641         case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
11642                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
11643                 break;
11644         case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
11645                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
11646                 break;
11647         case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
11648                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
11649                 break;
11650         case MMPLAYER_STREAMING_ERROR_INVALID_URL:
11651                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
11652                 break;
11653         case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
11654                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
11655                 break;
11656         case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
11657                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
11658                 break;
11659         case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
11660                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
11661                 break;
11662         case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
11663                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
11664                 break;
11665         case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
11666                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
11667                 break;
11668         case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
11669                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
11670                 break;
11671         case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
11672                 msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
11673                 break;
11674         case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
11675                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
11676                 break;
11677         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
11678                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
11679                 break;
11680         case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
11681                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
11682                 break;
11683         case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
11684                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
11685                 break;
11686         case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
11687                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
11688                 break;
11689         case MMPLAYER_STREAMING_ERROR_GONE:
11690                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
11691                 break;
11692         case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
11693                 msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
11694                 break;
11695         case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
11696                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
11697                 break;
11698         case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
11699                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
11700                 break;
11701         case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
11702                 msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
11703                 break;
11704         case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
11705                 msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
11706                 break;
11707         case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
11708                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
11709                 break;
11710         case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
11711                 msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
11712                 break;
11713         case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
11714                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
11715                 break;
11716         case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
11717                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
11718                 break;
11719         case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
11720                 msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
11721                 break;
11722         case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
11723                 msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
11724                 break;
11725         case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
11726                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
11727                 break;
11728         case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
11729                 msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
11730                 break;
11731         case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
11732                 msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
11733                 break;
11734         case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
11735                 msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
11736                 break;
11737         case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
11738                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
11739                 break;
11740         case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
11741                 msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
11742                 break;
11743         case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
11744                 msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
11745                 break;
11746         case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
11747                 msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
11748                 break;
11749         case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
11750                 msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
11751                 break;
11752         case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
11753                 msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
11754                 break;
11755         case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
11756                 msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
11757                 break;
11758         case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
11759                 msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
11760                 break;
11761         case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
11762                 msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
11763                 break;
11764         default:
11765                 {
11766                         gst_structure_free(s);
11767                         return MM_ERROR_PLAYER_STREAMING_FAIL;
11768                 }
11769         }
11770
11771         error_string = g_strdup(gst_structure_get_string(s, "error_string"));
11772         if (error_string)
11773                 msg_param.data = (void *) error_string;
11774
11775         if (message->src) {
11776                 msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
11777
11778                 LOGE("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
11779                         msg_src_element, msg_param.code, (char*)msg_param.data);
11780         }
11781
11782         /* post error to application */
11783         if (!player->msg_posted) {
11784                 MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
11785
11786                 /* don't post more if one was sent already */
11787                 player->msg_posted = TRUE;
11788         } else
11789                 LOGD("skip error post because it's sent already.\n");
11790
11791         gst_structure_free(s);
11792         MMPLAYER_FLEAVE();
11793         g_free(error_string);
11794
11795         return TRUE;
11796
11797 }
11798
11799 static void
11800 __mmplayer_handle_eos_delay(mm_player_t* player, int delay_in_ms)
11801 {
11802         MMPLAYER_RETURN_IF_FAIL(player);
11803
11804         /* post now if delay is zero */
11805         if (delay_in_ms == 0 || player->set_mode.pcm_extraction) {
11806                 LOGD("eos delay is zero. posting EOS now\n");
11807                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11808
11809                 if (player->set_mode.pcm_extraction)
11810                         __mmplayer_cancel_eos_timer(player);
11811
11812                 return;
11813         }
11814
11815         /* cancel if existing */
11816         __mmplayer_cancel_eos_timer(player);
11817
11818         /* init new timeout */
11819         /* NOTE : consider give high priority to this timer */
11820         LOGD("posting EOS message after [%d] msec\n", delay_in_ms);
11821
11822         player->eos_timer = g_timeout_add(delay_in_ms,
11823                 __mmplayer_eos_timer_cb, player);
11824
11825         player->context.global_default = g_main_context_default();
11826         LOGD("global default context = %p, eos timer id = %d", player->context.global_default, player->eos_timer);
11827
11828         /* check timer is valid. if not, send EOS now */
11829         if (player->eos_timer == 0) {
11830                 LOGW("creating timer for delayed EOS has failed. sending EOS now\n");
11831                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11832         }
11833 }
11834
11835 static void
11836 __mmplayer_cancel_eos_timer(mm_player_t* player)
11837 {
11838         MMPLAYER_RETURN_IF_FAIL(player);
11839
11840         if (player->eos_timer) {
11841                 LOGD("cancel eos timer");
11842                 __mmplayer_remove_g_source_from_context(player->context.global_default, player->eos_timer);
11843                 player->eos_timer = 0;
11844         }
11845
11846         return;
11847 }
11848
11849 static gboolean
11850 __mmplayer_eos_timer_cb(gpointer u_data)
11851 {
11852         mm_player_t* player = NULL;
11853         MMHandleType attrs = 0;
11854         int count = 0;
11855
11856         MMPLAYER_RETURN_VAL_IF_FAIL(u_data, FALSE);
11857
11858         player = (mm_player_t*) u_data;
11859         attrs = MMPLAYER_GET_ATTRS(player);
11860
11861         mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
11862
11863         if (count == -1) {
11864                 gint ret_value = 0;
11865                 ret_value = __gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
11866                 if (ret_value != MM_ERROR_NONE)
11867                         LOGE("seeking to 0 failed in repeat play");
11868         } else {
11869                 /* posting eos */
11870                 MMPLAYER_POST_MSG(player, MM_MESSAGE_END_OF_STREAM, NULL);
11871         }
11872
11873         /* we are returning FALSE as we need only one posting */
11874         return FALSE;
11875 }
11876
11877 /* sending event to one of sinkelements */
11878 static gboolean
11879 __gst_send_event_to_sink(mm_player_t* player, GstEvent* event)
11880 {
11881         GstEvent * event2 = NULL;
11882         GList *sinks = NULL;
11883         gboolean res = FALSE;
11884         MMPLAYER_FENTER();
11885
11886         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
11887         MMPLAYER_RETURN_VAL_IF_FAIL(event, FALSE);
11888
11889         /* While adding subtitles in live feeds seek is getting called.
11890            Adding defensive check in framework layer.*/
11891         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
11892                 if (MMPLAYER_IS_LIVE_STREAMING(player)) {
11893                         LOGE("Should not send seek event during live playback");
11894                         return TRUE;
11895                 }
11896         }
11897
11898         if (player->play_subtitle)
11899                 event2 = gst_event_copy((const GstEvent *)event);
11900
11901         sinks = player->sink_elements;
11902         while (sinks) {
11903                 GstElement *sink = GST_ELEMENT_CAST(sinks->data);
11904
11905                 if (GST_IS_ELEMENT(sink)) {
11906                         /* keep ref to the event */
11907                         gst_event_ref(event);
11908
11909                         if ((res = gst_element_send_event(sink, event))) {
11910                                 LOGD("sending event[%s] to sink element [%s] success!\n",
11911                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
11912
11913                                 /* rtsp case, asyn_done is not called after seek during pause state */
11914                                 if (MMPLAYER_IS_RTSP_STREAMING(player)) {
11915                                         if (GST_EVENT_TYPE(event) == GST_EVENT_SEEK) {
11916                                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED) {
11917                                                         LOGD("RTSP seek completed, after pause state..\n");
11918                                                         player->doing_seek = FALSE;
11919                                                         MMPLAYER_POST_MSG(player, MM_MESSAGE_SEEK_COMPLETED, NULL);
11920                                                 }
11921
11922                                         }
11923                                 }
11924
11925                                 if (MMPLAYER_IS_MS_BUFF_SRC(player)) {
11926                                         sinks = g_list_next(sinks);
11927                                         continue;
11928                                 } else {
11929                                         break;
11930                                 }
11931                         }
11932
11933                         LOGD("sending event[%s] to sink element [%s] failed. try with next one.\n",
11934                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink));
11935                 }
11936
11937                 sinks = g_list_next(sinks);
11938         }
11939
11940         /* Note : Textbin is not linked to the video or audio bin.
11941          * It needs to send the event to the text sink seperatelly.
11942          */
11943          if (player->play_subtitle && player->pipeline) {
11944                 GstElement *text_sink = GST_ELEMENT_CAST(player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst);
11945
11946                 if (GST_IS_ELEMENT(text_sink)) {
11947                         /* keep ref to the event */
11948                         gst_event_ref(event2);
11949
11950                         if ((res = gst_element_send_event(text_sink, event2)))
11951                                 LOGD("sending event[%s] to subtitle sink element [%s] success!\n",
11952                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
11953                         else
11954                                 LOGE("sending event[%s] to subtitle sink element [%s] failed!\n",
11955                                         GST_EVENT_TYPE_NAME(event2), GST_ELEMENT_NAME(text_sink));
11956
11957                         gst_event_unref(event2);
11958                 }
11959          }
11960
11961         gst_event_unref(event);
11962
11963         MMPLAYER_FLEAVE();
11964
11965         return res;
11966 }
11967
11968 static void
11969 __mmplayer_add_sink(mm_player_t* player, GstElement* sink)
11970 {
11971         MMPLAYER_FENTER();
11972
11973         MMPLAYER_RETURN_IF_FAIL(player);
11974         MMPLAYER_RETURN_IF_FAIL(sink);
11975
11976         player->sink_elements =
11977                 g_list_append(player->sink_elements, sink);
11978
11979         MMPLAYER_FLEAVE();
11980 }
11981
11982 static void
11983 __mmplayer_del_sink(mm_player_t* player, GstElement* sink)
11984 {
11985         MMPLAYER_FENTER();
11986
11987         MMPLAYER_RETURN_IF_FAIL(player);
11988         MMPLAYER_RETURN_IF_FAIL(sink);
11989
11990         player->sink_elements =
11991                         g_list_remove(player->sink_elements, sink);
11992
11993         MMPLAYER_FLEAVE();
11994 }
11995
11996 static gboolean
11997 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
11998                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
11999                         gint64 cur, GstSeekType stop_type, gint64 stop)
12000 {
12001         GstEvent* event = NULL;
12002         gboolean result = FALSE;
12003
12004         MMPLAYER_FENTER();
12005
12006         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12007
12008         if (player->pipeline && player->pipeline->textbin)
12009                 __mmplayer_drop_subtitle(player, FALSE);
12010
12011         event = gst_event_new_seek(rate, format, flags, cur_type,
12012                 cur, stop_type, stop);
12013
12014         result = __gst_send_event_to_sink(player, event);
12015
12016         MMPLAYER_FLEAVE();
12017
12018         return result;
12019 }
12020
12021 /* NOTE : be careful with calling this api. please refer to below glib comment
12022  * glib comment : Note that there is a bug in GObject that makes this function much
12023  * less useful than it might seem otherwise. Once gobject is disposed, the callback
12024  * will no longer be called, but, the signal handler is not currently disconnected.
12025  * If the instance is itself being freed at the same time than this doesn't matter,
12026  * since the signal will automatically be removed, but if instance persists,
12027  * then the signal handler will leak. You should not remove the signal yourself
12028  * because in a future versions of GObject, the handler will automatically be
12029  * disconnected.
12030  *
12031  * It's possible to work around this problem in a way that will continue to work
12032  * with future versions of GObject by checking that the signal handler is still
12033  * connected before disconnected it:
12034  *
12035  *  if (g_signal_handler_is_connected(instance, id))
12036  *    g_signal_handler_disconnect(instance, id);
12037  */
12038 static void
12039 __mmplayer_release_signal_connection(mm_player_t* player, MMPlayerSignalType type)
12040 {
12041         GList* sig_list = NULL;
12042         MMPlayerSignalItem* item = NULL;
12043
12044         MMPLAYER_FENTER();
12045
12046         MMPLAYER_RETURN_IF_FAIL(player);
12047
12048         LOGD("release signals type : %d", type);
12049
12050         if (type >= MM_PLAYER_SIGNAL_TYPE_ALL) {
12051                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUTOPLUG);
12052                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_VIDEOBIN);
12053                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_AUDIOBIN);
12054                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
12055                 __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_OTHERS);
12056                 return;
12057         }
12058
12059         sig_list = player->signals[type];
12060
12061         for (; sig_list; sig_list = sig_list->next) {
12062                 item = sig_list->data;
12063
12064                 if (item && item->obj && GST_IS_ELEMENT(item->obj)) {
12065                         if (g_signal_handler_is_connected(item->obj, item->sig))
12066                                 g_signal_handler_disconnect(item->obj, item->sig);
12067                 }
12068
12069                 MMPLAYER_FREEIF(item);
12070         }
12071
12072         g_list_free(player->signals[type]);
12073         player->signals[type] = NULL;
12074
12075         MMPLAYER_FLEAVE();
12076
12077         return;
12078 }
12079
12080 int _mmplayer_change_videosink(MMHandleType handle, MMDisplaySurfaceType surface_type, void *display_overlay)
12081 {
12082         mm_player_t* player = 0;
12083         int prev_display_surface_type = 0;
12084         void *prev_display_overlay = NULL;
12085         const gchar *klass = NULL;
12086         gchar *cur_videosink_name = NULL;
12087         int ret = 0;
12088         int i = 0;
12089         int num_of_dec = 2; /* DEC1, DEC2 */
12090
12091         MMPLAYER_FENTER();
12092
12093         MMPLAYER_RETURN_VAL_IF_FAIL(handle, MM_ERROR_COMMON_INVALID_ARGUMENT);
12094         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
12095
12096         player = MM_PLAYER_CAST(handle);
12097
12098         if (surface_type >= MM_DISPLAY_SURFACE_NUM) {
12099                 LOGE("Not support this surface type(%d) for changing vidoesink", surface_type);
12100                 MMPLAYER_FLEAVE();
12101                 return MM_ERROR_INVALID_ARGUMENT;
12102         }
12103
12104         /* load previous attributes */
12105         if (player->attrs) {
12106                 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &prev_display_surface_type);
12107                 mm_attrs_get_data_by_name(player->attrs, "display_overlay", &prev_display_overlay);
12108                 LOGD("[0: Video surface, 4: EVAS surface] previous surface type(%d), new surface type(%d)", prev_display_surface_type, surface_type);
12109                 if (prev_display_surface_type == surface_type) {
12110                         LOGD("incoming display surface type is same as previous one, do nothing..");
12111                         MMPLAYER_FLEAVE();
12112                         return MM_ERROR_NONE;
12113                 }
12114         } else {
12115                 LOGE("failed to load attributes");
12116                 MMPLAYER_FLEAVE();
12117                 return MM_ERROR_PLAYER_INTERNAL;
12118         }
12119
12120         /* check videosink element is created */
12121         if (!player->pipeline || !player->pipeline->videobin ||
12122                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
12123                 LOGD("videosink element is not yet ready");
12124
12125                 /* videobin is not created yet, so we just set attributes related to display surface */
12126                 LOGD("store display attribute for given surface type(%d)", surface_type);
12127                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
12128                 mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
12129                 if (mmf_attrs_commit(player->attrs)) {
12130                         LOGE("failed to commit attribute");
12131                         MMPLAYER_FLEAVE();
12132                         return MM_ERROR_PLAYER_INTERNAL;
12133                 }
12134                 MMPLAYER_FLEAVE();
12135                 return MM_ERROR_NONE;
12136         } else {
12137                 /* get player command status */
12138                 if (!(player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME || player->cmd == MMPLAYER_COMMAND_PAUSE)) {
12139                         LOGE("invalid player command status(%d), __mmplayer_do_change_videosink() is only available with START/RESUME/PAUSE command", player->cmd);
12140                         MMPLAYER_FLEAVE();
12141                         return MM_ERROR_PLAYER_INVALID_STATE;
12142                 }
12143
12144                 /* surface change */
12145                 for (i = 0 ; i < num_of_dec ; i++) {
12146                         if (player->pipeline->mainbin &&
12147                                 player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst) {
12148                                 GstElementFactory *decfactory;
12149                                 decfactory = gst_element_get_factory(player->pipeline->mainbin[MMPLAYER_M_DEC1+i].gst);
12150
12151                                 klass = gst_element_factory_get_metadata(decfactory, GST_ELEMENT_METADATA_KLASS);
12152                                 if ((g_strrstr(klass, "Codec/Decoder/Video"))) {
12153                                         if ((prev_display_surface_type == MM_DISPLAY_SURFACE_OVERLAY) && (surface_type == MM_DISPLAY_SURFACE_REMOTE)) {
12154                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, "fakesink", surface_type, display_overlay);
12155                                                 if (ret) {
12156                                                         goto ERROR_CASE;
12157                                                 } else {
12158                                                         LOGW("success to changing display surface(%d)", surface_type);
12159                                                         MMPLAYER_FLEAVE();
12160                                                         return MM_ERROR_NONE;
12161                                                 }
12162                                         } else if ((prev_display_surface_type == MM_DISPLAY_SURFACE_REMOTE) && (surface_type == MM_DISPLAY_SURFACE_OVERLAY)) {
12163                                                 ret = __mmplayer_do_change_videosink(player, MMPLAYER_M_DEC1+i, player->ini.videosink_element_overlay, surface_type, display_overlay);
12164                                                 if (ret) {
12165                                                         goto ERROR_CASE;
12166                                                 } else {
12167                                                         LOGW("success to changing display surface(%d)", surface_type);
12168                                                         MMPLAYER_FLEAVE();
12169                                                         return MM_ERROR_NONE;
12170                                                 }
12171                                         } else {
12172                                                 LOGE("invalid incoming surface type(%d) and current videosink_name(%s) for changing display surface", surface_type, cur_videosink_name);
12173                                                 ret = MM_ERROR_PLAYER_INTERNAL;
12174                                                 goto ERROR_CASE;
12175                                         }
12176                                 }
12177                         }
12178                 }
12179         }
12180
12181 ERROR_CASE:
12182         /* rollback to previous attributes */
12183         mm_attrs_set_int_by_name(player->attrs, "display_surface_type", prev_display_surface_type);
12184         mm_attrs_set_data_by_name(player->attrs, "display_overlay", prev_display_overlay, sizeof(void*));
12185         if (mmf_attrs_commit(player->attrs)) {
12186                 LOGE("failed to commit attributes to rollback");
12187                 MMPLAYER_FLEAVE();
12188                 return MM_ERROR_PLAYER_INTERNAL;
12189         }
12190         MMPLAYER_FLEAVE();
12191         return ret;
12192 }
12193
12194 /* NOTE : It does not support some use cases, eg using colorspace converter */
12195 int
12196 __mmplayer_do_change_videosink(mm_player_t* player, const int dec_index, const char *videosink_element, MMDisplaySurfaceType surface_type, void *display_overlay)
12197 {
12198         GstPad *src_pad_dec = NULL;
12199         GstPad *sink_pad_videosink = NULL;
12200         GstPad *sink_pad_videobin = NULL;
12201         GstClock *clock = NULL;
12202         MMPlayerStateType previous_state = MM_PLAYER_STATE_NUM;
12203         int ret = MM_ERROR_NONE;
12204         gboolean is_audiobin_created = TRUE;
12205
12206         MMPLAYER_FENTER();
12207
12208         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_COMMON_INVALID_ARGUMENT);
12209         MMPLAYER_RETURN_VAL_IF_FAIL(videosink_element, MM_ERROR_COMMON_INVALID_ARGUMENT);
12210         MMPLAYER_RETURN_VAL_IF_FAIL(display_overlay, MM_ERROR_COMMON_INVALID_ARGUMENT);
12211
12212         LOGD("video dec is found(idx:%d), we are going to change videosink to %s", dec_index, videosink_element);
12213         LOGD("surface type(%d), display overlay(%x)", surface_type, display_overlay);
12214
12215         /* get information whether if audiobin is created */
12216         if (!player->pipeline->audiobin ||
12217                      !player->pipeline->audiobin[MMPLAYER_A_SINK].gst) {
12218                 LOGW("audiobin is null, this video content may not have audio data");
12219                 is_audiobin_created = FALSE;
12220         }
12221
12222         /* get current state of player */
12223         previous_state = MMPLAYER_CURRENT_STATE(player);
12224         LOGD("previous state(%d)", previous_state);
12225
12226
12227         /* get src pad of decoder and block it */
12228         src_pad_dec = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), "src");
12229         if (!src_pad_dec) {
12230                 LOGE("failed to get src pad from decode in mainbin");
12231                 return MM_ERROR_PLAYER_INTERNAL;
12232         }
12233
12234         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
12235                 LOGW("trying to block pad(video)");
12236 //              if (!gst_pad_set_blocked(src_pad_dec, TRUE))
12237                 gst_pad_add_probe(src_pad_dec, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
12238                         NULL, NULL, NULL);
12239                 {
12240                         LOGE("failed to set block pad(video)");
12241                         return MM_ERROR_PLAYER_INTERNAL;
12242                 }
12243                 LOGW("pad is blocked(video)");
12244         } else {
12245                 /* no data flows, so no need to do pad_block */
12246                 if (player->doing_seek)
12247                         LOGW("not completed seek(%d), do nothing", player->doing_seek);
12248
12249                 LOGD("MM_PLAYER_STATE is not PLAYING now, skip pad-block(TRUE)");
12250         }
12251
12252         /* remove pad */
12253         if (!gst_element_remove_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst,
12254                 GST_PAD_CAST(GST_GHOST_PAD(player->ghost_pad_for_videobin)))) {
12255                 LOGE("failed to remove previous ghost_pad for videobin");
12256                 return MM_ERROR_PLAYER_INTERNAL;
12257         }
12258
12259         /* change state of videobin to NULL */
12260         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_NULL);
12261         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_NULL);
12262         if (ret != GST_STATE_CHANGE_SUCCESS) {
12263                 LOGE("failed to change state of videobin to NULL");
12264                 return MM_ERROR_PLAYER_INTERNAL;
12265         }
12266
12267         /* unlink between decoder and videobin and remove previous videosink from videobin */
12268         gst_element_unlink(GST_ELEMENT(player->pipeline->mainbin[dec_index].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst));
12269         if (!gst_bin_remove(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst))) {
12270                 LOGE("failed to remove former videosink from videobin");
12271                 return MM_ERROR_PLAYER_INTERNAL;
12272         }
12273
12274         __mmplayer_del_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12275
12276         /* create a new videosink and add it to videobin */
12277         player->pipeline->videobin[MMPLAYER_V_SINK].gst = gst_element_factory_make(videosink_element, "videosink");
12278         if (!player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
12279                 LOGE("failed to create videosink element\n");
12280                 MMPLAYER_FLEAVE();
12281                 return MM_ERROR_PLAYER_INTERNAL;
12282         }
12283         gst_bin_add(GST_BIN(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst));
12284         __mmplayer_add_sink(player, player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12285         g_object_set(G_OBJECT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
12286
12287         /* save attributes */
12288         if (player->attrs) {
12289                 /* set a new display surface type */
12290                 mm_attrs_set_int_by_name(player->attrs, "display_surface_type", surface_type);
12291                 /* set a new diplay overlay */
12292                 switch (surface_type) {
12293                 case MM_DISPLAY_SURFACE_OVERLAY:
12294                         LOGD("save attributes related to video display surface : id = %d", *(int*)display_overlay);
12295                         mm_attrs_set_data_by_name(player->attrs, "display_overlay", display_overlay, sizeof(display_overlay));
12296                         break;
12297                 default:
12298                         LOGE("invalid type(%d) for changing display surface", surface_type);
12299                         MMPLAYER_FLEAVE();
12300                         return MM_ERROR_INVALID_ARGUMENT;
12301                 }
12302                 if (mmf_attrs_commit(player->attrs)) {
12303                         LOGE("failed to commit");
12304                         MMPLAYER_FLEAVE();
12305                         return MM_ERROR_PLAYER_INTERNAL;
12306                 }
12307         } else {
12308                 LOGE("player->attrs is null, failed to save attributes");
12309                 MMPLAYER_FLEAVE();
12310                 return MM_ERROR_PLAYER_INTERNAL;
12311         }
12312
12313         /* update video param */
12314         if (MM_ERROR_NONE != _mmplayer_update_video_param(player, "update_all_param")) {
12315                 LOGE("failed to update video param");
12316                 return MM_ERROR_PLAYER_INTERNAL;
12317         }
12318
12319         /* change state of videobin to READY */
12320         LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_READY);
12321         ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_READY);
12322         if (ret != GST_STATE_CHANGE_SUCCESS) {
12323                 LOGE("failed to change state of videobin to READY");
12324                 return MM_ERROR_PLAYER_INTERNAL;
12325         }
12326
12327         /* change ghostpad */
12328         sink_pad_videosink = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_SINK].gst), "sink");
12329         if (!sink_pad_videosink) {
12330                 LOGE("failed to get sink pad from videosink element");
12331                 return MM_ERROR_PLAYER_INTERNAL;
12332         }
12333         player->ghost_pad_for_videobin = gst_ghost_pad_new("sink", sink_pad_videosink);
12334         if (!gst_pad_set_active(player->ghost_pad_for_videobin, TRUE)) {
12335                 LOGE("failed to set active to ghost_pad");
12336                 return MM_ERROR_PLAYER_INTERNAL;
12337         }
12338         if (FALSE == gst_element_add_pad(player->pipeline->videobin[MMPLAYER_V_BIN].gst, player->ghost_pad_for_videobin)) {
12339                 LOGE("failed to change ghostpad for videobin");
12340                 return MM_ERROR_PLAYER_INTERNAL;
12341         }
12342         gst_object_unref(sink_pad_videosink);
12343
12344         /* link decoder with videobin */
12345         sink_pad_videobin = gst_element_get_static_pad(GST_ELEMENT(player->pipeline->videobin[MMPLAYER_V_BIN].gst), "sink");
12346         if (!sink_pad_videobin) {
12347                 LOGE("failed to get sink pad from videobin");
12348                 return MM_ERROR_PLAYER_INTERNAL;
12349         }
12350         if (GST_PAD_LINK_OK != gst_pad_link(src_pad_dec, sink_pad_videobin)) {
12351                 LOGE("failed to link");
12352                 return MM_ERROR_PLAYER_INTERNAL;
12353         }
12354         gst_object_unref(sink_pad_videobin);
12355
12356         /* clock setting for a new videosink plugin */
12357         /* NOTE : Below operation is needed, because a new videosink plugin doesn't have clock for basesink,
12358                         so we set it from audiosink plugin or pipeline(system clock) */
12359         if (!is_audiobin_created) {
12360                 LOGW("audiobin is not created, get clock from pipeline..");
12361                 clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
12362         } else {
12363                 clock = GST_ELEMENT_CLOCK(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
12364         }
12365         if (clock) {
12366                 GstClockTime now;
12367                 GstClockTime base_time;
12368                 LOGD("set the clock to videosink");
12369                 gst_element_set_clock(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), clock);
12370                 clock = GST_ELEMENT_CLOCK(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
12371                 if (clock) {
12372                         LOGD("got clock of videosink");
12373                         now = gst_clock_get_time(clock);
12374                         base_time = GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst)->base_time;
12375                         LOGD("at time %" GST_TIME_FORMAT ", base %"
12376                                         GST_TIME_FORMAT, GST_TIME_ARGS(now), GST_TIME_ARGS(base_time));
12377                 } else {
12378                         LOGE("failed to get clock of videosink after setting clock");
12379                         return MM_ERROR_PLAYER_INTERNAL;
12380                 }
12381         } else
12382                 LOGW("failed to get clock, maybe it is the time before first playing");
12383
12384         if (!player->doing_seek && previous_state == MM_PLAYER_STATE_PLAYING) {
12385                 /* change state of videobin to PAUSED */
12386                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PLAYING);
12387                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PLAYING);
12388                 if (ret != GST_STATE_CHANGE_FAILURE) {
12389                         LOGW("change state of videobin to PLAYING, ret(%d)", ret);
12390                 } else {
12391                         LOGE("failed to change state of videobin to PLAYING");
12392                         return MM_ERROR_PLAYER_INTERNAL;
12393                 }
12394
12395                 /* release blocked and unref src pad of video decoder */
12396                 #if 0
12397                 if (!gst_pad_set_blocked(src_pad_dec, FALSE)) {
12398                         LOGE("failed to set pad blocked FALSE(video)");
12399                         return MM_ERROR_PLAYER_INTERNAL;
12400                 }
12401                 #endif
12402                 LOGW("pad is unblocked(video)");
12403         } else {
12404                 if (player->doing_seek)
12405                         LOGW("not completed seek(%d)", player->doing_seek);
12406                 /* change state of videobin to PAUSED */
12407                 LOGD("setting [%s] state to : %d", GST_ELEMENT_NAME(player->pipeline->videobin[MMPLAYER_V_BIN].gst), GST_STATE_PAUSED);
12408                 ret = gst_element_set_state(player->pipeline->videobin[MMPLAYER_V_BIN].gst, GST_STATE_PAUSED);
12409                 if (ret != GST_STATE_CHANGE_FAILURE) {
12410                         LOGW("change state of videobin to PAUSED, ret(%d)", ret);
12411                 } else {
12412                         LOGE("failed to change state of videobin to PLAYING");
12413                         return MM_ERROR_PLAYER_INTERNAL;
12414                 }
12415
12416                 /* already skipped pad block */
12417                 LOGD("previous MM_PLAYER_STATE is not PLAYING, skip pad-block(FALSE)");
12418         }
12419
12420         /* do get/set position for new videosink plugin */
12421         {
12422                 unsigned long position = 0;
12423                 gint64 pos_msec = 0;
12424
12425                 LOGD("do get/set position for new videosink plugin");
12426                 if (__gst_get_position(player, MM_PLAYER_POS_FORMAT_TIME, &position)) {
12427                         LOGE("failed to get position");
12428                         return MM_ERROR_PLAYER_INTERNAL;
12429                 }
12430 #ifdef SINKCHANGE_WITH_ACCURATE_SEEK
12431                 /* accurate seek */
12432                 if (__gst_set_position(player, MM_PLAYER_POS_FORMAT_TIME, position, TRUE)) {
12433                         LOGE("failed to set position");
12434                         return MM_ERROR_PLAYER_INTERNAL;
12435                 }
12436 #else
12437                 /* key unit seek */
12438                 pos_msec = position * G_GINT64_CONSTANT(1000000);
12439                 ret = __gst_seek(player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
12440                                 GST_FORMAT_TIME, (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
12441                                                         GST_SEEK_TYPE_SET, pos_msec,
12442                                                         GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
12443                 if (!ret) {
12444                         LOGE("failed to set position");
12445                         return MM_ERROR_PLAYER_INTERNAL;
12446                 }
12447 #endif
12448         }
12449
12450         if (src_pad_dec)
12451                 gst_object_unref(src_pad_dec);
12452         LOGD("success to change sink");
12453
12454         MMPLAYER_FLEAVE();
12455
12456         return MM_ERROR_NONE;
12457 }
12458
12459
12460 /* Note : if silent is true, then subtitle would not be displayed. :*/
12461 int _mmplayer_set_subtitle_silent(MMHandleType hplayer, int silent)
12462 {
12463         mm_player_t* player = (mm_player_t*) hplayer;
12464
12465         MMPLAYER_FENTER();
12466
12467         /* check player handle */
12468         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12469
12470         player->set_mode.subtitle_off = silent;
12471
12472         LOGD("subtitle is %s.\n", player->set_mode.subtitle_off ? "ON" : "OFF");
12473
12474         MMPLAYER_FLEAVE();
12475
12476         return MM_ERROR_NONE;
12477 }
12478
12479 int _mmplayer_sync_subtitle_pipeline(mm_player_t* player)
12480 {
12481         MMPlayerGstElement* mainbin = NULL;
12482         MMPlayerGstElement* textbin = NULL;
12483         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
12484         GstState current_state = GST_STATE_VOID_PENDING;
12485         GstState element_state = GST_STATE_VOID_PENDING;
12486         GstState element_pending_state = GST_STATE_VOID_PENDING;
12487         gint64 time = 0;
12488         GstEvent *event = NULL;
12489         int result = MM_ERROR_NONE;
12490
12491         GstClock *curr_clock = NULL;
12492         GstClockTime base_time, start_time, curr_time;
12493
12494
12495         MMPLAYER_FENTER();
12496
12497         /* check player handle */
12498         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
12499                                                                 player->pipeline &&
12500                                                                 player->pipeline->mainbin &&
12501                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12502
12503         mainbin = player->pipeline->mainbin;
12504         textbin = player->pipeline->textbin;
12505
12506         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12507
12508         // sync clock with current pipeline
12509         curr_clock = GST_ELEMENT_CLOCK(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
12510         curr_time = gst_clock_get_time(curr_clock);
12511
12512         base_time = gst_element_get_base_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
12513         start_time = gst_element_get_start_time(GST_ELEMENT_CAST(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
12514
12515         LOGD("state: %d, base_time=%" GST_TIME_FORMAT " start_time=%" GST_TIME_FORMAT " curr_time=%" GST_TIME_FORMAT,
12516                 current_state, GST_TIME_ARGS(base_time), GST_TIME_ARGS(start_time), GST_TIME_ARGS(curr_time));
12517
12518         if (current_state > GST_STATE_READY) {
12519                 // sync state with current pipeline
12520                 gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_PAUSED);
12521                 gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_PAUSED);
12522                 gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_PAUSED);
12523
12524                 ret = gst_element_get_state(mainbin[MMPLAYER_M_SUBSRC].gst, &element_state, &element_pending_state, 5 * GST_SECOND);
12525                 if (GST_STATE_CHANGE_FAILURE == ret) {
12526                         LOGE("fail to state change.\n");
12527                         result = MM_ERROR_PLAYER_INTERNAL;
12528                         goto ERROR;
12529                 }
12530         }
12531
12532         gst_element_set_base_time(textbin[MMPLAYER_T_BIN].gst, base_time);
12533         gst_element_set_start_time(textbin[MMPLAYER_T_BIN].gst, start_time);
12534
12535         if (curr_clock) {
12536                 gst_element_set_clock(textbin[MMPLAYER_T_BIN].gst, curr_clock);
12537                 gst_object_unref(curr_clock);
12538         }
12539
12540         // seek to current position
12541         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
12542                 result = MM_ERROR_PLAYER_INVALID_STATE;
12543                 LOGE("gst_element_query_position failed, invalid state\n");
12544                 goto ERROR;
12545         }
12546
12547         LOGD("seek time = %lld, rate = %f\n", time, player->playback_rate);
12548         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);
12549         if (event) {
12550                 __gst_send_event_to_sink(player, event);
12551         } else {
12552                 result = MM_ERROR_PLAYER_INTERNAL;
12553                 LOGE("gst_event_new_seek failed"); /* pipeline will got error and can not be recovered */
12554                 goto ERROR;
12555         }
12556
12557         /* sync state with current pipeline */
12558         gst_element_sync_state_with_parent(textbin[MMPLAYER_T_BIN].gst);
12559         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBPARSE].gst);
12560         gst_element_sync_state_with_parent(mainbin[MMPLAYER_M_SUBSRC].gst);
12561
12562         return MM_ERROR_NONE;
12563
12564 ERROR:
12565         /* release text pipeline resource */
12566         player->textsink_linked = 0;
12567
12568         /* release signal */
12569         __mmplayer_release_signal_connection(player, MM_PLAYER_SIGNAL_TYPE_TEXTBIN);
12570
12571         /* release textbin with it's childs */
12572         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->textbin, MMPLAYER_T_BIN);
12573         MMPLAYER_FREEIF(player->pipeline->textbin);
12574         player->pipeline->textbin = NULL;
12575
12576         /* release subtitle elem */
12577         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBSRC);
12578         MMPLAYER_RELEASE_ELEMENT(player, player->pipeline->mainbin, MMPLAYER_M_SUBPARSE);
12579
12580         return result;
12581 }
12582
12583 static int
12584 __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* filepath)
12585 {
12586         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
12587         GstState current_state = GST_STATE_VOID_PENDING;
12588
12589         MMHandleType attrs = 0;
12590         MMPlayerGstElement* mainbin = NULL;
12591         MMPlayerGstElement* textbin = NULL;
12592
12593         gchar* subtitle_uri = NULL;
12594         int result = MM_ERROR_NONE;
12595         const gchar *charset = NULL;
12596
12597         MMPLAYER_FENTER();
12598
12599         /* check player handle */
12600         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
12601                                                                 player->pipeline &&
12602                                                                 player->pipeline->mainbin &&
12603                                                                 player->pipeline->textbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
12604         MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
12605
12606         mainbin = player->pipeline->mainbin;
12607         textbin = player->pipeline->textbin;
12608
12609         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12610         if (current_state < GST_STATE_READY) {
12611                 result = MM_ERROR_PLAYER_INVALID_STATE;
12612                 LOGE("Pipeline is not in proper state\n");
12613                 goto EXIT;
12614         }
12615
12616         attrs = MMPLAYER_GET_ATTRS(player);
12617         if (!attrs) {
12618                 LOGE("cannot get content attribute\n");
12619                 result = MM_ERROR_PLAYER_INTERNAL;
12620                 goto EXIT;
12621         }
12622
12623         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
12624         if (!subtitle_uri || strlen(subtitle_uri) < 1) {
12625                 LOGE("subtitle uri is not proper filepath\n");
12626                 result = MM_ERROR_PLAYER_INVALID_URI;
12627                 goto EXIT;
12628         }
12629
12630         if (!util_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) {
12631                 LOGE("failed to get storage info of subtitle path");
12632                 result = MM_ERROR_PLAYER_INVALID_URI;
12633                 goto EXIT;
12634         }
12635
12636         LOGD("old subtitle file path is [%s]\n", subtitle_uri);
12637         LOGD("new subtitle file path is [%s]\n", filepath);
12638
12639         if (!strcmp(filepath, subtitle_uri)) {
12640                 LOGD("No need to swtich subtitle, as input filepath is same as current filepath\n");
12641                 goto EXIT;
12642         } else {
12643                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12644                 if (mmf_attrs_commit(player->attrs)) {
12645                         LOGE("failed to commit.\n");
12646                         goto EXIT;
12647                 }
12648         }
12649
12650         //gst_pad_set_blocked_async(src-srcpad, TRUE)
12651         MMPLAYER_SUBTITLE_INFO_LOCK(player);
12652         player->subtitle_language_list = NULL;
12653         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
12654
12655         ret = gst_element_set_state(textbin[MMPLAYER_T_BIN].gst, GST_STATE_READY);
12656         if (ret != GST_STATE_CHANGE_SUCCESS) {
12657                 LOGE("failed to change state of textbin to READY");
12658                 result = MM_ERROR_PLAYER_INTERNAL;
12659                 goto EXIT;
12660         }
12661
12662         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBPARSE].gst, GST_STATE_READY);
12663         if (ret != GST_STATE_CHANGE_SUCCESS) {
12664                 LOGE("failed to change state of subparse to READY");
12665                 result = MM_ERROR_PLAYER_INTERNAL;
12666                 goto EXIT;
12667         }
12668
12669         ret = gst_element_set_state(mainbin[MMPLAYER_M_SUBSRC].gst, GST_STATE_READY);
12670         if (ret != GST_STATE_CHANGE_SUCCESS) {
12671                 LOGE("failed to change state of filesrc to READY");
12672                 result = MM_ERROR_PLAYER_INTERNAL;
12673                 goto EXIT;
12674         }
12675
12676         __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_TEXT);
12677
12678         g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL);
12679
12680         charset = util_get_charset(filepath);
12681         if (charset) {
12682                 LOGD("detected charset is %s\n", charset);
12683                 g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBPARSE].gst), "subtitle-encoding", charset, NULL);
12684         }
12685
12686         result = _mmplayer_sync_subtitle_pipeline(player);
12687
12688 EXIT:
12689         MMPLAYER_FLEAVE();
12690         return result;
12691 }
12692
12693 /* API to switch between external subtitles */
12694 int _mmplayer_set_external_subtitle_path(MMHandleType hplayer, const char* filepath)
12695 {
12696         int result = MM_ERROR_NONE;
12697         mm_player_t* player = (mm_player_t*)hplayer;
12698         char *path = NULL;
12699
12700         MMPLAYER_FENTER();
12701
12702         /* check player handle */
12703         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12704
12705         /* filepath can be null in idle state */
12706         if (filepath) {
12707                 /* check file path */
12708                 if ((path = strstr(filepath, "file://")))
12709                         result = util_exist_file_path(path + 7);
12710                 else
12711                         result = util_exist_file_path(filepath);
12712
12713                 if (result != MM_ERROR_NONE) {
12714                         LOGE("invalid subtitle path 0x%X", result);
12715                         return result; /* file not found or permission denied */
12716                 }
12717         }
12718
12719         if (!player->pipeline) {
12720                 /* IDLE state */
12721                 mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12722                 if (mmf_attrs_commit(player->attrs)) {
12723                         LOGE("failed to commit");       /* subtitle path will not be created */
12724                         return MM_ERROR_PLAYER_INTERNAL;
12725                 }
12726         } else {
12727                 /* cur state <> IDLE(READY, PAUSE, PLAYING..) */
12728                 /* check filepath */
12729                 MMPLAYER_RETURN_VAL_IF_FAIL(filepath, MM_ERROR_COMMON_INVALID_ARGUMENT);
12730
12731                 if (!__mmplayer_check_subtitle(player)) {
12732                         mm_attrs_set_string_by_name(player->attrs, "subtitle_uri", filepath);
12733                         if (mmf_attrs_commit(player->attrs)) {
12734                                 LOGE("failed to commit");
12735                                 return MM_ERROR_PLAYER_INTERNAL;
12736                         }
12737
12738                         if (MM_ERROR_NONE != __mmplayer_gst_create_text_pipeline(player)) {
12739                                 LOGE("fail to create text pipeline");
12740                                 return MM_ERROR_PLAYER_INTERNAL;
12741                         }
12742
12743                         result = _mmplayer_sync_subtitle_pipeline(player);
12744                 } else {
12745                         result = __mmplayer_change_external_subtitle_language(player, filepath);
12746                 }
12747
12748                 MMPLAYER_BUS_MSG_THREAD_SIGNAL(player);
12749                 player->is_external_subtitle_added_now = TRUE;
12750
12751                 MMPLAYER_SUBTITLE_INFO_LOCK(player);
12752                 if (!player->subtitle_language_list) {
12753                         gint64 timeout = g_get_monotonic_time() + G_TIME_SPAN_SECOND; /* wait 1 sec */
12754                         if (!MMPLAYER_SUBTITLE_INFO_WAIT_UNTIL(player, timeout))
12755                                 LOGW("subtitle language list is not updated yet");
12756                 }
12757                 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
12758         }
12759
12760         MMPLAYER_FLEAVE();
12761         return result;
12762 }
12763
12764 static int
12765 __mmplayer_change_selector_pad(mm_player_t* player, MMPlayerTrackType type, int index)
12766 {
12767         int result = MM_ERROR_NONE;
12768         gchar* change_pad_name = NULL;
12769         GstPad* sinkpad = NULL;
12770         MMPlayerGstElement* mainbin = NULL;
12771         enum MainElementID elemId = MMPLAYER_M_NUM;
12772         GstCaps* caps = NULL;
12773         gint total_track_num = 0;
12774
12775         MMPLAYER_FENTER();
12776
12777         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline && player->pipeline->mainbin,
12778                                                                                                         MM_ERROR_PLAYER_NOT_INITIALIZED);
12779
12780         LOGD("Change Track(%d) to %d\n", type, index);
12781
12782         mainbin = player->pipeline->mainbin;
12783
12784         if (type == MM_PLAYER_TRACK_TYPE_AUDIO) {
12785                 elemId = MMPLAYER_M_A_INPUT_SELECTOR;
12786         } else if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
12787                 elemId = MMPLAYER_M_T_INPUT_SELECTOR;
12788         } else {
12789                 /* Changing Video Track is not supported. */
12790                 LOGE("Track Type Error\n");
12791                 goto EXIT;
12792         }
12793
12794         if (mainbin[elemId].gst == NULL) {
12795                 result = MM_ERROR_PLAYER_NO_OP;
12796                 LOGD("Req track doesn't exist\n");
12797                 goto EXIT;
12798         }
12799
12800         total_track_num = player->selector[type].total_track_num;
12801         if (total_track_num <= 0) {
12802                 result = MM_ERROR_PLAYER_NO_OP;
12803                 LOGD("Language list is not available \n");
12804                 goto EXIT;
12805         }
12806
12807         if ((index < 0) || (index >= total_track_num)) {
12808                 result = MM_ERROR_INVALID_ARGUMENT;
12809                 LOGD("Not a proper index : %d \n", index);
12810                 goto EXIT;
12811         }
12812
12813         /*To get the new pad from the selector*/
12814         change_pad_name = g_strdup_printf("sink_%u", index);
12815         if (change_pad_name == NULL) {
12816                 result = MM_ERROR_PLAYER_INTERNAL;
12817                 LOGD("Pad does not exists\n");
12818                 goto EXIT;
12819         }
12820
12821         LOGD("new active pad name: %s\n", change_pad_name);
12822
12823         sinkpad = gst_element_get_static_pad(mainbin[elemId].gst, change_pad_name);
12824         if (sinkpad == NULL) {
12825                 LOGD("sinkpad is NULL");
12826                 result = MM_ERROR_PLAYER_INTERNAL;
12827                 goto EXIT;
12828         }
12829
12830         LOGD("Set Active Pad - %s:%s\n", GST_DEBUG_PAD_NAME(sinkpad));
12831         g_object_set(mainbin[elemId].gst, "active-pad", sinkpad, NULL);
12832
12833         caps = gst_pad_get_current_caps(sinkpad);
12834         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
12835
12836         if (sinkpad)
12837                 gst_object_unref(sinkpad);
12838
12839         if (type == MM_PLAYER_TRACK_TYPE_AUDIO)
12840                 __mmplayer_set_audio_attrs(player, caps);
12841
12842 EXIT:
12843
12844         MMPLAYER_FREEIF(change_pad_name);
12845         return result;
12846 }
12847
12848 int _mmplayer_change_track_language(MMHandleType hplayer, MMPlayerTrackType type, int index)
12849 {
12850         int result = MM_ERROR_NONE;
12851         mm_player_t* player = NULL;
12852         MMPlayerGstElement* mainbin = NULL;
12853
12854         gint current_active_index = 0;
12855
12856         GstState current_state = GST_STATE_VOID_PENDING;
12857         GstEvent* event = NULL;
12858         gint64 time = 0;
12859
12860         MMPLAYER_FENTER();
12861
12862         player = (mm_player_t*)hplayer;
12863         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12864
12865         if (!player->pipeline) {
12866                 LOGE("Track %d pre setting -> %d\n", type, index);
12867
12868                 player->selector[type].active_pad_index = index;
12869                 goto EXIT;
12870         }
12871
12872         mainbin = player->pipeline->mainbin;
12873
12874         current_active_index = player->selector[type].active_pad_index;
12875
12876         /*If index is same as running index no need to change the pad*/
12877         if (current_active_index == index)
12878                 goto EXIT;
12879
12880         if (!gst_element_query_position(mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &time)) {
12881                 result = MM_ERROR_PLAYER_INVALID_STATE;
12882                 goto EXIT;
12883         }
12884
12885         current_state = GST_STATE(mainbin[MMPLAYER_M_PIPE].gst);
12886         if (current_state < GST_STATE_PAUSED) {
12887                 result = MM_ERROR_PLAYER_INVALID_STATE;
12888                 LOGW("Pipeline not in porper state\n");
12889                 goto EXIT;
12890         }
12891
12892         result = __mmplayer_change_selector_pad(player, type, index);
12893         if (result != MM_ERROR_NONE) {
12894                 LOGE("change selector pad error\n");
12895                 goto EXIT;
12896         }
12897
12898         player->selector[type].active_pad_index = index;
12899
12900         if (current_state == GST_STATE_PLAYING) {
12901                 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);
12902                 if (event) {
12903                         __gst_send_event_to_sink(player, event);
12904                 } else {
12905                         result = MM_ERROR_PLAYER_INTERNAL;
12906                         goto EXIT;
12907                 }
12908         }
12909
12910 EXIT:
12911         return result;
12912 }
12913
12914 int _mmplayer_get_subtitle_silent(MMHandleType hplayer, int* silent)
12915 {
12916         mm_player_t* player = (mm_player_t*) hplayer;
12917
12918         MMPLAYER_FENTER();
12919
12920         /* check player handle */
12921         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12922
12923         *silent = player->set_mode.subtitle_off;
12924
12925         LOGD("subtitle is %s.\n", silent ? "ON" : "OFF");
12926
12927         MMPLAYER_FLEAVE();
12928
12929         return MM_ERROR_NONE;
12930 }
12931
12932 gboolean
12933 __is_ms_buff_src(mm_player_t* player)
12934 {
12935         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12936
12937         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_MS_BUFF) ? TRUE : FALSE;
12938 }
12939
12940 gboolean
12941 __has_suffix(mm_player_t* player, const gchar* suffix)
12942 {
12943         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
12944         MMPLAYER_RETURN_VAL_IF_FAIL(suffix, FALSE);
12945
12946         gboolean ret = FALSE;
12947         gchar* t_url = g_ascii_strdown(player->profile.uri, -1);
12948         gchar* t_suffix = g_ascii_strdown(suffix, -1);
12949
12950         if (g_str_has_suffix(player->profile.uri, suffix))
12951                 ret = TRUE;
12952
12953         MMPLAYER_FREEIF(t_url);
12954         MMPLAYER_FREEIF(t_suffix);
12955
12956         return ret;
12957 }
12958
12959 int
12960 _mmplayer_set_video_hub_download_mode(MMHandleType hplayer, bool mode)
12961 {
12962         mm_player_t* player = (mm_player_t*) hplayer;
12963
12964         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12965
12966         if (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_NULL) {
12967                 MMPLAYER_PRINT_STATE(player);
12968                 LOGE("wrong-state : can't set the download mode to parse");
12969                 return MM_ERROR_PLAYER_INVALID_STATE;
12970         }
12971
12972         LOGD("set video hub download mode to %s", (mode) ? "ON" : "OFF");
12973         player->video_hub_download_mode = mode;
12974
12975         return MM_ERROR_NONE;
12976 }
12977
12978 int
12979 _mmplayer_enable_sync_handler(MMHandleType hplayer, bool enable)
12980 {
12981         mm_player_t* player = (mm_player_t*) hplayer;
12982
12983         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
12984
12985         LOGD("enable sync handler : %s", (enable) ? "ON" : "OFF");
12986         player->sync_handler = enable;
12987
12988         return MM_ERROR_NONE;
12989 }
12990
12991 int
12992 _mmplayer_set_video_share_master_clock(MMHandleType hplayer,
12993                                         long long clock,
12994                                         long long clock_delta,
12995                                         long long video_time,
12996                                         long long media_clock,
12997                                         long long audio_time)
12998 {
12999         mm_player_t* player = (mm_player_t*) hplayer;
13000         MMPlayerGstElement* mainbin = NULL;
13001         GstClockTime start_time_audio = 0, start_time_video = 0;
13002         GstClockTimeDiff base_time = 0, new_base_time = 0;
13003         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
13004         gint64 api_delta = 0;
13005         gint64 position = 0, position_delta = 0;
13006         gint64 adj_base_time = 0;
13007         GstClock *curr_clock = NULL;
13008         GstClockTime curr_time = 0;
13009         gboolean query_ret = TRUE;
13010         int result = MM_ERROR_NONE;
13011
13012         MMPLAYER_FENTER();
13013
13014         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
13015         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
13016         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
13017
13018         // LOGD("in(us) : %lld, %lld, %lld, %lld, %lld", clock, clock_delta, video_time, media_clock, audio_time);
13019
13020         if ((video_time < 0) || (player->doing_seek)) {
13021                 LOGD("skip setting master clock.  %lld", video_time);
13022                 goto EXIT;
13023         }
13024
13025         mainbin = player->pipeline->mainbin;
13026
13027         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
13028         curr_time = gst_clock_get_time(curr_clock);
13029
13030         current_state = MMPLAYER_CURRENT_STATE(player);
13031
13032         if (current_state == MM_PLAYER_STATE_PLAYING)
13033                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
13034
13035         if ((current_state != MM_PLAYER_STATE_PLAYING) ||
13036                 (!query_ret)) {
13037                 position = player->last_position;
13038                 LOGD("query fail. %lld", position);
13039         }
13040
13041         clock *= GST_USECOND;
13042         clock_delta *= GST_USECOND;
13043
13044         api_delta = clock - curr_time;
13045         if ((player->video_share_api_delta == 0) || (player->video_share_api_delta > api_delta))
13046                 player->video_share_api_delta = api_delta;
13047         else
13048                 clock_delta += (api_delta - player->video_share_api_delta);
13049
13050         if ((player->video_share_clock_delta == 0) || (player->video_share_clock_delta > clock_delta)) {
13051                 player->video_share_clock_delta = (gint64)clock_delta;
13052
13053                 position_delta = (position/GST_USECOND) - video_time;
13054                 position_delta *= GST_USECOND;
13055
13056                 adj_base_time = position_delta;
13057                 LOGD("video_share_clock_delta = %lld, adj = %lld", player->video_share_clock_delta, adj_base_time);
13058
13059         } else {
13060                 gint64 new_play_time = 0;
13061                 gint64 network_delay = 0;
13062
13063                 video_time *= GST_USECOND;
13064
13065                 network_delay = clock_delta - player->video_share_clock_delta;
13066                 new_play_time = video_time + network_delay;
13067
13068                 adj_base_time = position - new_play_time;
13069
13070                 LOGD("%lld(delay) = %lld - %lld / %lld(adj) = %lld(slave_pos) - %lld(master_pos) - %lld(delay)",
13071                         network_delay, clock_delta, player->video_share_clock_delta, adj_base_time, position, video_time, network_delay);
13072         }
13073
13074         /* Adjust Current Stream Time with base_time of sink
13075          * 1. Set Start time to CLOCK NONE, to control the base time by MSL
13076          * 2. Set new base time
13077          *    if adj_base_time is positive value, the stream time will be decreased.
13078          * 3. If seek event is occurred, the start time will be reset. */
13079         if ((player->pipeline->audiobin) &&
13080                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst)) {
13081                 start_time_audio = gst_element_get_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
13082
13083                 if (start_time_audio != GST_CLOCK_TIME_NONE) {
13084                         LOGD("audio sink : gst_element_set_start_time -> NONE");
13085                         gst_element_set_start_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst, GST_CLOCK_TIME_NONE);
13086                 }
13087
13088                 base_time = gst_element_get_base_time(player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
13089         }
13090
13091         if ((player->pipeline->videobin) &&
13092                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst)) {
13093                 start_time_video = gst_element_get_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13094
13095                 if (start_time_video != GST_CLOCK_TIME_NONE) {
13096                         LOGD("video sink : gst_element_set_start_time -> NONE");
13097                         gst_element_set_start_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst, GST_CLOCK_TIME_NONE);
13098                 }
13099
13100                 // if videobin exist, get base_time from videobin.
13101                 base_time = gst_element_get_base_time(player->pipeline->videobin[MMPLAYER_V_SINK].gst);
13102         }
13103
13104         new_base_time = base_time + adj_base_time;
13105
13106         if ((player->pipeline->audiobin) &&
13107                 (player->pipeline->audiobin[MMPLAYER_A_SINK].gst))
13108                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), (GstClockTime)new_base_time);
13109
13110         if ((player->pipeline->videobin) &&
13111                 (player->pipeline->videobin[MMPLAYER_V_SINK].gst))
13112                 gst_element_set_base_time(GST_ELEMENT_CAST(player->pipeline->videobin[MMPLAYER_V_SINK].gst), (GstClockTime)new_base_time);
13113
13114 EXIT:
13115         MMPLAYER_FLEAVE();
13116
13117         return result;
13118 }
13119
13120 int
13121 _mmplayer_get_video_share_master_clock(MMHandleType hplayer,
13122                                         long long *video_time,
13123                                         long long *media_clock,
13124                                         long long *audio_time)
13125 {
13126         mm_player_t* player = (mm_player_t*) hplayer;
13127         MMPlayerGstElement* mainbin = NULL;
13128         GstClock *curr_clock = NULL;
13129         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
13130         gint64 position = 0;
13131         gboolean query_ret = TRUE;
13132
13133         MMPLAYER_FENTER();
13134
13135         MMPLAYER_RETURN_VAL_IF_FAIL(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
13136         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin, MM_ERROR_PLAYER_NOT_INITIALIZED);
13137         MMPLAYER_RETURN_VAL_IF_FAIL(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, MM_ERROR_PLAYER_NOT_INITIALIZED);
13138
13139         MMPLAYER_RETURN_VAL_IF_FAIL(video_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
13140         MMPLAYER_RETURN_VAL_IF_FAIL(media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT);
13141         MMPLAYER_RETURN_VAL_IF_FAIL(audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
13142
13143         mainbin = player->pipeline->mainbin;
13144
13145         curr_clock = gst_pipeline_get_clock(GST_PIPELINE_CAST(mainbin[MMPLAYER_M_PIPE].gst));
13146
13147         current_state = MMPLAYER_CURRENT_STATE(player);
13148
13149         if (current_state != MM_PLAYER_STATE_PAUSED)
13150                 query_ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position);
13151
13152         if ((current_state == MM_PLAYER_STATE_PAUSED) ||
13153                 (!query_ret))
13154                 position = player->last_position;
13155
13156         *media_clock = *video_time = *audio_time = (position/GST_USECOND);
13157
13158         LOGD("media_clock: %lld, video_time: %lld(us)", *media_clock, *video_time);
13159
13160         if (curr_clock)
13161                 gst_object_unref(curr_clock);
13162
13163         MMPLAYER_FLEAVE();
13164
13165         return MM_ERROR_NONE;
13166 }
13167
13168 static gboolean
13169 __mmplayer_add_dump_buffer_probe(mm_player_t *player, GstElement *element)
13170 {
13171         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13172         MMPLAYER_RETURN_VAL_IF_FAIL(element, FALSE);
13173
13174         gchar *factory_name = GST_OBJECT_NAME(gst_element_get_factory(element));
13175         gchar dump_file_name[PLAYER_INI_MAX_STRLEN*2];
13176
13177         int idx = 0;
13178
13179         for (idx = 0; player->ini.dump_element_keyword[idx][0] != '\0'; idx++) {
13180                 if (g_strrstr(factory_name, player->ini.dump_element_keyword[idx])) {
13181                         LOGD("dump [%s] sink pad", player->ini.dump_element_keyword[idx]);
13182                         mm_player_dump_t *dump_s;
13183                         dump_s = g_malloc(sizeof(mm_player_dump_t));
13184
13185                         if (dump_s == NULL) {
13186                                 LOGE("malloc fail");
13187                                 return FALSE;
13188                         }
13189
13190                         dump_s->dump_element_file = NULL;
13191                         dump_s->dump_pad = NULL;
13192                         dump_s->dump_pad = gst_element_get_static_pad(element, "sink");
13193
13194                         if (dump_s->dump_pad) {
13195                                 memset(dump_file_name, 0x00, PLAYER_INI_MAX_STRLEN*2);
13196                                 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]);
13197                                 dump_s->dump_element_file = fopen(dump_file_name, "w+");
13198                                 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);
13199                                 /* add list for removed buffer probe and close FILE */
13200                                 player->dump_list = g_list_append(player->dump_list, dump_s);
13201                                 LOGD("%s sink pad added buffer probe for dump", factory_name);
13202                                 return TRUE;
13203                         } else {
13204                                 g_free(dump_s);
13205                                 dump_s = NULL;
13206                                 LOGE("failed to get %s sink pad added", factory_name);
13207                         }
13208
13209
13210                 }
13211         }
13212         return FALSE;
13213 }
13214
13215 static GstPadProbeReturn
13216 __mmplayer_dump_buffer_probe_cb(GstPad *pad,  GstPadProbeInfo *info, gpointer u_data)
13217 {
13218         FILE *dump_data = (FILE *) u_data;
13219 //      int written = 0;
13220         GstBuffer *buffer = gst_pad_probe_info_get_buffer(info);
13221         GstMapInfo probe_info = GST_MAP_INFO_INIT;
13222
13223         MMPLAYER_RETURN_VAL_IF_FAIL(dump_data, FALSE);
13224
13225         gst_buffer_map(buffer, &probe_info, GST_MAP_READ);
13226
13227 //      LOGD("buffer timestamp = %" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
13228
13229         fwrite(probe_info.data, 1, probe_info.size , dump_data);
13230
13231         return GST_PAD_PROBE_OK;
13232 }
13233
13234 static void
13235 __mmplayer_release_dump_list(GList *dump_list)
13236 {
13237         if (dump_list) {
13238                 GList *d_list = dump_list;
13239                 for (; d_list; d_list = g_list_next(d_list)) {
13240                         mm_player_dump_t *dump_s = d_list->data;
13241                         if (dump_s->dump_pad) {
13242                                 if (dump_s->probe_handle_id)
13243                                         gst_pad_remove_probe(dump_s->dump_pad, dump_s->probe_handle_id);
13244                         }
13245                         if (dump_s->dump_element_file) {
13246                                 fclose(dump_s->dump_element_file);
13247                                 dump_s->dump_element_file = NULL;
13248                         }
13249                         MMPLAYER_FREEIF(dump_s);
13250                 }
13251                 g_list_free(dump_list);
13252                 dump_list = NULL;
13253         }
13254 }
13255
13256 int
13257 _mmplayer_has_closed_caption(MMHandleType hplayer, bool* exist)
13258 {
13259         mm_player_t* player = (mm_player_t*) hplayer;
13260
13261         MMPLAYER_FENTER();
13262
13263         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13264         MMPLAYER_RETURN_VAL_IF_FAIL(exist, MM_ERROR_INVALID_ARGUMENT);
13265
13266         *exist = player->has_closed_caption;
13267
13268         MMPLAYER_FLEAVE();
13269
13270         return MM_ERROR_NONE;
13271 }
13272
13273 void _mm_player_video_stream_internal_buffer_unref(void *buffer)
13274 {
13275         MMPLAYER_FENTER();
13276         if (buffer) {
13277                 // LOGD("unref internal gst buffer %p", buffer);
13278                 gst_buffer_unref((GstBuffer *)buffer);
13279                 buffer = NULL;
13280         }
13281         MMPLAYER_FLEAVE();
13282 }
13283
13284 void
13285 __gst_appsrc_feed_audio_data(GstElement *element, guint size, gpointer user_data)
13286 {
13287         mm_player_t *player  = (mm_player_t*)user_data;
13288         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13289         guint64 current_level_bytes = 0;
13290
13291         MMPLAYER_RETURN_IF_FAIL(player);
13292
13293         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13294
13295         LOGI("app-src: feed audio(%llu)\n", current_level_bytes);
13296         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13297
13298         if (player->media_stream_buffer_status_cb[type])
13299                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13300         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13301
13302 }
13303
13304 void
13305 __gst_appsrc_feed_video_data(GstElement *element, guint size, gpointer user_data)
13306 {
13307         mm_player_t *player  = (mm_player_t*)user_data;
13308         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13309         guint64 current_level_bytes = 0;
13310
13311         MMPLAYER_RETURN_IF_FAIL(player);
13312
13313         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13314
13315         LOGI("app-src: feed video(%llu)\n", current_level_bytes);
13316
13317         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13318         if (player->media_stream_buffer_status_cb[type])
13319                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13320         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13321 }
13322
13323 void
13324 __gst_appsrc_feed_subtitle_data(GstElement *element, guint size, gpointer user_data)
13325 {
13326         mm_player_t *player  = (mm_player_t*)user_data;
13327         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
13328         guint64 current_level_bytes = 0;
13329
13330         MMPLAYER_RETURN_IF_FAIL(player);
13331
13332         LOGI("app-src: feed subtitle\n");
13333
13334         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13335
13336         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13337         if (player->media_stream_buffer_status_cb[type])
13338                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_UNDERRUN, current_level_bytes, player->buffer_cb_user_param[type]);
13339
13340         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13341 }
13342
13343 void
13344 __gst_appsrc_enough_audio_data(GstElement *element, gpointer user_data)
13345 {
13346         mm_player_t *player  = (mm_player_t*)user_data;
13347         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13348         guint64 current_level_bytes = 0;
13349
13350         MMPLAYER_RETURN_IF_FAIL(player);
13351
13352         LOGI("app-src: audio buffer is full.\n");
13353
13354         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13355
13356         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13357
13358         if (player->media_stream_buffer_status_cb[type])
13359                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
13360
13361         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13362 }
13363
13364 void
13365 __gst_appsrc_enough_video_data(GstElement *element, gpointer user_data)
13366 {
13367         mm_player_t *player  = (mm_player_t*)user_data;
13368         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13369         guint64 current_level_bytes = 0;
13370
13371         MMPLAYER_RETURN_IF_FAIL(player);
13372
13373         LOGI("app-src: video buffer is full.\n");
13374
13375         g_object_get(G_OBJECT(element), "current-level-bytes", &current_level_bytes, NULL);
13376
13377         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13378         if (player->media_stream_buffer_status_cb[type])
13379                 player->media_stream_buffer_status_cb[type](type, MM_PLAYER_MEDIA_STREAM_BUFFER_OVERFLOW, current_level_bytes, player->buffer_cb_user_param[type]);
13380
13381         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13382 }
13383
13384 gboolean
13385 __gst_seek_audio_data(GstElement * appsrc, guint64 position, gpointer user_data)
13386 {
13387         mm_player_t *player  = (mm_player_t*)user_data;
13388         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_AUDIO;
13389
13390         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13391
13392         LOGD("app-src: seek audio data %llu\n", position);
13393         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13394
13395         if (player->media_stream_seek_data_cb[type])
13396                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13397         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13398
13399         return TRUE;
13400 }
13401
13402 gboolean
13403 __gst_seek_video_data(GstElement * appsrc, guint64 position, gpointer user_data)
13404 {
13405         mm_player_t *player  = (mm_player_t*)user_data;
13406         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_VIDEO;
13407
13408         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13409
13410         LOGD("app-src: seek video data %llu\n", position);
13411         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13412         if (player->media_stream_seek_data_cb[type])
13413                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13414         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13415
13416         return TRUE;
13417 }
13418
13419 gboolean
13420 __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, gpointer user_data)
13421 {
13422         mm_player_t *player  = (mm_player_t*)user_data;
13423         MMPlayerStreamType type = MM_PLAYER_STREAM_TYPE_TEXT;
13424
13425         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
13426
13427         LOGD("app-src: seek subtitle data\n");
13428         MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(player);
13429
13430         if (player->media_stream_seek_data_cb[type])
13431                 player->media_stream_seek_data_cb[type](type, position, player->seek_cb_user_param[type]);
13432         MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(player);
13433
13434         return TRUE;
13435 }
13436
13437 int
13438 _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel)
13439 {
13440         mm_player_t* player = (mm_player_t*) hplayer;
13441
13442         MMPLAYER_FENTER();
13443
13444         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13445
13446         player->pcm_samplerate = samplerate;
13447         player->pcm_channel = channel;
13448
13449         MMPLAYER_FLEAVE();
13450         return MM_ERROR_NONE;
13451 }
13452
13453 int _mmplayer_get_timeout(MMHandleType hplayer, int *timeout)
13454 {
13455         mm_player_t* player = (mm_player_t*) hplayer;
13456
13457         MMPLAYER_FENTER();
13458
13459         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13460         MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
13461
13462         if (MMPLAYER_IS_STREAMING(player))
13463                 *timeout = player->ini.live_state_change_timeout;
13464         else
13465                 *timeout = player->ini.localplayback_state_change_timeout;
13466
13467         LOGD("timeout = %d\n", *timeout);
13468
13469         MMPLAYER_FLEAVE();
13470         return MM_ERROR_NONE;
13471 }
13472
13473 int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num)
13474 {
13475         mm_player_t* player = (mm_player_t*) hplayer;
13476
13477         MMPLAYER_FENTER();
13478
13479         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13480         MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT);
13481
13482         *num = player->video_num_buffers;
13483         *extra_num = player->video_extra_num_buffers;
13484
13485         LOGD("state %d, num %d(%d)\n", MMPLAYER_CURRENT_STATE(player), *num, *extra_num);
13486
13487         MMPLAYER_FLEAVE();
13488         return MM_ERROR_NONE;
13489 }
13490
13491 static void
13492 __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type)
13493 {
13494         int i = 0;
13495         MMPLAYER_FENTER();
13496         MMPLAYER_RETURN_IF_FAIL(player);
13497
13498         for (i = 0; i < MMPLAYER_PATH_MAX; i++) {
13499
13500                 if (path_type == MMPLAYER_PATH_MAX || path_type == i) {
13501                         player->storage_info[i].type = STORAGE_TYPE_INTERNAL;
13502                         player->storage_info[i].state = STORAGE_STATE_UNMOUNTABLE;
13503                         player->storage_info[i].id = -1;
13504                         memset(player->storage_info[i].path, 0x00, MM_MAX_URL_LEN);
13505
13506                         if (path_type != MMPLAYER_PATH_MAX)
13507                                 break;
13508                 }
13509         }
13510
13511         MMPLAYER_FLEAVE();
13512 }
13513
13514 int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int id, int state)
13515 {
13516         int ret = MM_ERROR_NONE;
13517         mm_player_t* player = (mm_player_t*)hplayer;
13518         MMMessageParamType msg_param = {0, };
13519
13520         MMPLAYER_FENTER();
13521         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13522
13523         LOGW("state changed storage %d:%d", id, state);
13524
13525         if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED)
13526                 return MM_ERROR_NONE;
13527
13528         /* FIXME: text path should be handled seperately. */
13529         if (((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_VOD].id == id)) ||
13530                 ((player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL) && (player->storage_info[MMPLAYER_PATH_TEXT].id == id))) {
13531                 LOGW("external storage is removed");
13532
13533                 if (player->msg_posted == FALSE) {
13534                         memset(&msg_param, 0, sizeof(MMMessageParamType));
13535                         msg_param.code = MM_ERROR_PLAYER_INVALID_URI;
13536                         MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param);
13537                         player->msg_posted = TRUE;
13538                 }
13539
13540                 /* unrealize the player */
13541                 ret = _mmplayer_unrealize(hplayer);
13542                 if (ret != MM_ERROR_NONE)
13543                         LOGE("failed to unrealize");
13544         }
13545
13546         MMPLAYER_FLEAVE();
13547         return ret;
13548 }
13549
13550 int _mmplayer_get_adaptive_variant_info(MMHandleType hplayer, int *num, char **var_info)
13551 {
13552         int ret = MM_ERROR_NONE;
13553         mm_player_t* player = (mm_player_t*) hplayer;
13554         int idx = 0, total = 0;
13555         gchar *result = NULL, *tmp = NULL;
13556
13557         MMPLAYER_FENTER();
13558         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13559         MMPLAYER_RETURN_VAL_IF_FAIL(num && var_info, MM_ERROR_COMMON_INVALID_ARGUMENT);
13560
13561         total = *num = g_list_length(player->adaptive_info.var_list);
13562         if (total <= 0) {
13563                 LOGW("There is no stream variant info.");
13564                 return ret;
13565         }
13566
13567         result = g_strdup("");
13568         for (idx = 0 ; idx < total ; idx++) {
13569                 VariantData *v_data = NULL;
13570                 v_data = g_list_nth_data(player->adaptive_info.var_list, idx);
13571
13572                 if (v_data) {
13573                         gchar data[64] = {0};
13574                         snprintf(data, sizeof(data), "%d,%d,%d,", v_data->bandwidth, v_data->width, v_data->height);
13575
13576                         tmp = g_strconcat(result, data, NULL);
13577                         g_free(result);
13578                         result = tmp;
13579                 } else {
13580                         LOGW("There is no variant data in %d", idx);
13581                         (*num)--;
13582                 }
13583         }
13584
13585         *var_info = (char *)result;
13586
13587         LOGD("variant info %d:%s", *num, *var_info);
13588         MMPLAYER_FLEAVE();
13589         return ret;
13590 }
13591
13592 int _mmplayer_set_max_adaptive_variant_limit(MMHandleType hplayer, int bandwidth, int width, int height)
13593 {
13594         int ret = MM_ERROR_NONE;
13595         mm_player_t* player = (mm_player_t*) hplayer;
13596
13597         MMPLAYER_FENTER();
13598         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13599
13600         LOGD("set limit to [b]%d, [w]%d, [h]%d", bandwidth, width, height);
13601
13602         player->adaptive_info.limit.bandwidth = (bandwidth >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (bandwidth) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13603         player->adaptive_info.limit.width = (width >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (width) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13604         player->adaptive_info.limit.height = (height >= ADAPTIVE_VARIANT_DEFAULT_VALUE) ? (height) : (ADAPTIVE_VARIANT_DEFAULT_VALUE);
13605
13606         if (player->pipeline && player->pipeline->mainbin && player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst) {
13607                 LOGD("update max limit of %s", GST_ELEMENT_NAME(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst));
13608                 g_object_set(player->pipeline->mainbin[MMPLAYER_M_ADAPTIVE_DEMUX].gst,
13609                                                 "max-bandwidth", bandwidth, "max-video-width", width, "max-video-height", height, NULL);
13610
13611                 /* FIXME: seek to current position for applying new variant limitation */
13612         }
13613
13614         MMPLAYER_FLEAVE();
13615         return ret;
13616
13617 }
13618
13619 int _mmplayer_get_max_adaptive_variant_limit(MMHandleType hplayer, int *bandwidth, int *width, int *height)
13620 {
13621         int ret = MM_ERROR_NONE;
13622         mm_player_t* player = (mm_player_t*) hplayer;
13623
13624         MMPLAYER_FENTER();
13625         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13626         MMPLAYER_RETURN_VAL_IF_FAIL(bandwidth && width && height, MM_ERROR_COMMON_INVALID_ARGUMENT);
13627
13628         *bandwidth = player->adaptive_info.limit.bandwidth;
13629         *width = player->adaptive_info.limit.width;
13630         *height = player->adaptive_info.limit.height;
13631
13632         LOGD("get limit to [b]%d, [w]%d, [h]%d", *bandwidth, *width, *height);
13633
13634         MMPLAYER_FLEAVE();
13635         return ret;
13636 }
13637
13638 int _mmplayer_set_streaming_buffering_time(MMHandleType hplayer, int buffer_ms, int rebuffer_ms)
13639 {
13640         int ret = MM_ERROR_NONE;
13641         mm_player_t* player = (mm_player_t*) hplayer;
13642
13643         MMPLAYER_FENTER();
13644         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13645
13646         if (MMPLAYER_CURRENT_STATE(player) !=  MM_PLAYER_STATE_NULL)
13647                 LOGW("buffer_ms will not be applied.");
13648
13649
13650         LOGD("set buffering time %d ms / %d ms", buffer_ms, rebuffer_ms);
13651
13652         if (player->streamer == NULL) {
13653                 player->streamer = __mm_player_streaming_create();
13654                 __mm_player_streaming_initialize(player->streamer);
13655         }
13656
13657         if (buffer_ms >= 0)
13658                 player->streamer->buffering_req.prebuffer_time = buffer_ms;
13659
13660         if (rebuffer_ms >= 0)
13661                 player->streamer->buffering_req.rebuffer_time = rebuffer_ms;
13662
13663         MMPLAYER_FLEAVE();
13664         return ret;
13665
13666 }
13667
13668 int _mmplayer_get_streaming_buffering_time(MMHandleType hplayer, int *buffer_ms, int *rebuffer_ms)
13669 {
13670         int ret = MM_ERROR_NONE;
13671         mm_player_t* player = (mm_player_t*) hplayer;
13672
13673         MMPLAYER_FENTER();
13674         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13675         MMPLAYER_RETURN_VAL_IF_FAIL(buffer_ms && rebuffer_ms, MM_ERROR_COMMON_INVALID_ARGUMENT);
13676
13677         if (player->streamer == NULL) {
13678                 player->streamer = __mm_player_streaming_create();
13679                 __mm_player_streaming_initialize(player->streamer);
13680         }
13681
13682         *buffer_ms = player->streamer->buffering_req.prebuffer_time;
13683         *rebuffer_ms = player->streamer->buffering_req.rebuffer_time;
13684
13685         LOGD("buffering time %d ms / %d ms", *buffer_ms, *rebuffer_ms);
13686
13687         MMPLAYER_FLEAVE();
13688         return ret;
13689 }
13690
13691 int _mmplayer_set_codec_type(MMHandleType hplayer, MMPlayerStreamType stream_type, MMPlayerVideoCodecType codec_type)
13692 {
13693 #define IDX_FIRST_SW_CODEC 0
13694         mm_player_t* player = (mm_player_t*) hplayer;
13695         const char* attr_name = (stream_type == MM_PLAYER_STREAM_TYPE_AUDIO) ? (MM_PLAYER_AUDIO_CODEC_TYPE) : (MM_PLAYER_VIDEO_CODEC_TYPE);
13696         MMHandleType attrs = 0;
13697
13698         MMPLAYER_FENTER();
13699         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13700
13701         LOGD("ini setting : [a][h:%s][s:%s] / [v][h:%s][s:%s]",
13702                 player->ini.audiocodec_element_hw, player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC],
13703                 player->ini.videocodec_element_hw, player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC]);
13704
13705         switch (stream_type) {
13706         case MM_PLAYER_STREAM_TYPE_AUDIO:
13707                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
13708                          (!strcmp(player->ini.audiocodec_element_hw, ""))) ||
13709                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
13710                          (!strcmp(player->ini.audiocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
13711                         LOGE("There is no a codec for codec_type %d", codec_type);
13712                         return MM_ERROR_PLAYER_NO_OP;
13713                 }
13714         break;
13715         case MM_PLAYER_STREAM_TYPE_VIDEO:
13716                 if (((codec_type == MM_PLAYER_CODEC_TYPE_HW) &&
13717                          (!strcmp(player->ini.videocodec_element_hw, ""))) ||
13718                         ((codec_type == MM_PLAYER_CODEC_TYPE_SW) &&
13719                          (!strcmp(player->ini.videocodec_element_sw[IDX_FIRST_SW_CODEC], "")))) {
13720                         LOGE("There is no v codec for codec_type %d", codec_type);
13721                         return MM_ERROR_PLAYER_NO_OP;
13722                 }
13723
13724         break;
13725         default:
13726                 LOGE("Invalid stream type %d", stream_type);
13727                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
13728         break;
13729         }
13730
13731         LOGD("update %s codec_type to %d", attr_name, codec_type);
13732
13733         attrs = MMPLAYER_GET_ATTRS(player);
13734         mm_attrs_set_int_by_name(attrs, attr_name, codec_type);
13735
13736         if (mmf_attrs_commit(player->attrs)) {
13737                 LOGE("failed to commit codec_type attributes");
13738                 return MM_ERROR_PLAYER_INTERNAL;
13739         }
13740
13741         MMPLAYER_FLEAVE();
13742         return MM_ERROR_NONE;
13743 }
13744
13745 int
13746 _mmplayer_set_replaygain_enabled(MMHandleType hplayer, bool enabled)
13747 {
13748         mm_player_t* player = (mm_player_t*) hplayer;
13749         GstElement* rg_vol_element = NULL;
13750
13751         MMPLAYER_FENTER();
13752
13753         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13754
13755         player->sound.rg_enable = enabled;
13756
13757         /* just hold rgvolume enable value if pipeline is not ready */
13758         if (!player->pipeline || !player->pipeline->audiobin) {
13759                 LOGD("pipeline is not ready. holding rgvolume enable value\n");
13760                 return MM_ERROR_NONE;
13761         }
13762
13763         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
13764
13765         if (!rg_vol_element) {
13766                 LOGD("rgvolume element is not created");
13767                 return MM_ERROR_PLAYER_INTERNAL;
13768         }
13769
13770         if (enabled)
13771                 g_object_set(rg_vol_element, "enable-rgvolume", TRUE, NULL);
13772         else
13773                 g_object_set(rg_vol_element, "enable-rgvolume", FALSE, NULL);
13774
13775         MMPLAYER_FLEAVE();
13776
13777         return MM_ERROR_NONE;
13778 }
13779
13780 int
13781 _mmplayer_is_replaygain_enabled(MMHandleType hplayer, bool *enabled)
13782 {
13783         mm_player_t* player = (mm_player_t*) hplayer;
13784         GstElement* rg_vol_element = NULL;
13785         gboolean enable = FALSE;
13786
13787         MMPLAYER_FENTER();
13788
13789         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
13790         MMPLAYER_RETURN_VAL_IF_FAIL(enabled, MM_ERROR_INVALID_ARGUMENT);
13791
13792         /* just hold enable_rg value if pipeline is not ready */
13793         if (!player->pipeline || !player->pipeline->audiobin) {
13794                 LOGD("pipeline is not ready. holding rgvolume value (%d)\n", player->sound.rg_enable);
13795                 *enabled = player->sound.rg_enable;
13796                 return MM_ERROR_NONE;
13797         }
13798
13799         rg_vol_element = player->pipeline->audiobin[MMPLAYER_A_RGVOL].gst;
13800
13801         if (!rg_vol_element) {
13802                 LOGD("rgvolume element is not created");
13803                 return MM_ERROR_PLAYER_INTERNAL;
13804         }
13805
13806         g_object_get(rg_vol_element, "enable-rgvolume", &enable, NULL);
13807         *enabled = enable;
13808
13809         MMPLAYER_FLEAVE();
13810
13811         return MM_ERROR_NONE;
13812 }